news 2026/6/26 9:29:46

S32K3xx系列在未使用 HSE 时,使用密码限制JTAG调试访问

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
S32K3xx系列在未使用 HSE 时,使用密码限制JTAG调试访问

目录

前提

整体流程

设置ADKP

设置LC,推进生命周期

查看

解锁调试接口

小结

前提

在芯片量产阶段通常需要关闭JTAG调试口。针对NXP的K3系列芯片,对于未使用过HSE的工程师,可设置密码(ADKP)来实现JTAG的禁用。

整体流程

  1. 第一,设置ADKP即调试密码;
  2. 第二,设置LC,推进生命周期
  3. 第三,使用PE官方的脚本解锁调试

设置ADKP

这里只需要设置16Byte的密码(0x1B000080-0x1B00008F),剩余的是预留位(0x1B000090-0x1B00009F)。

注意一点,ADKP写入后无法变更且必须在LC推进之前设置,否则会跑飞。

boolean Set_Jtag_ADKP(void)//一旦写入无法变更 { //ADKP uint8_t FLS_MASTER_ID =0U; uint8_t FLS_BUF_SIZE=16U; uint32_t FLS_SECTOR_ADDR=0x1B000080U; uint8 TxBuffer[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; /* Password */ if(*((uint32*)FLS_SECTOR_ADDR)!=0xFFFFFFFF) //已写入ADKP { return 1; } C40_Ip_StatusType C40_Ip_Status=C40_Ip_Init(&C40_Ip_InitCfg); C40_IP_DEV_ASSERT(C40_Ip_Status ==STATUS_C40_IP_SUCCESS ); uint8_t VSector=C40_Ip_GetSectorNumberFromAddress(FLS_SECTOR_ADDR); //unlock do{ C40_Ip_ClearLock(VSector, FLS_MASTER_ID); }while(0x09!=C40_Ip_GetLock(VSector)); //Erase C40_Ip_MainInterfaceSectorErase(VSector, FLS_MASTER_ID); do{ C40_Ip_Status=C40_Ip_MainInterfaceSectorEraseStatus(); }while(C40_Ip_Status==STATUS_C40_IP_BUSY); C40_IP_DEV_ASSERT(C40_Ip_Status ==STATUS_C40_IP_SUCCESS ); //Write C40_Ip_MainInterfaceWrite(FLS_SECTOR_ADDR, FLS_BUF_SIZE,TxBuffer , FLS_MASTER_ID); do{ C40_Ip_Status=C40_Ip_MainInterfaceSectorEraseStatus(); }while(C40_Ip_Status==STATUS_C40_IP_BUSY); C40_IP_DEV_ASSERT(C40_Ip_Status ==STATUS_C40_IP_SUCCESS ); return C40_Ip_Status; }

设置LC,推进生命周期

LifeCycle是芯片内部的状态机制,在不同的LC状态支持某些特定的功能和配置。S32K3有4个Lifecycle阶段:CUST_DEL、OEM_PROD、IN_FIELD、FA。

出厂默认是CUST_DEL,调试接口无限制。我们需要将其推进到限制更严格的阶段比如OEM_PROD。

修改LCW为指定的值,复位后SBAF(安全启动辅助固件)会根据LCW演进到相应的Lifecycle:
• LCW = 0xDADADADA advances LC to OEM_PROD
• LCW = 0xBABABABA advances LC to IN_FIELD

注意一旦成功推进LC,则无法再回退。0x004EA000U可以是除了HSE区域以外的任何Pflash地址,建议是APP内存后面选一块Sector。

boolean Set_LC_OEM_PROD(void)//一旦写入无法变更 { uint8_t FLS_MASTER_ID =0U; uint8_t FLS_BUF_SIZE=8U; uint32_t FLS_SECTOR_ADDR=0x004EA000U; uint8_t LC_TxBuffer[8] = {0xDA, 0xDA, 0xDA, 0xDA, 0x0, 0x0, 0x0, 0x0}; /* Minimum data length 8 bytes */ if(*((uint32*)FLS_SECTOR_ADDR)!=0xFFFFFFFF) //已写入LC { return 1; } C40_Ip_StatusType C40_Ip_Status=C40_Ip_Init(&C40_Ip_InitCfg); C40_IP_DEV_ASSERT(C40_Ip_Status ==STATUS_C40_IP_SUCCESS ); uint8_t VSector=C40_Ip_GetSectorNumberFromAddress(FLS_SECTOR_ADDR); //unlock do{ C40_Ip_ClearLock(VSector, FLS_MASTER_ID); }while(0x09!=C40_Ip_GetLock(VSector)); //Erase C40_Ip_MainInterfaceSectorErase(VSector, FLS_MASTER_ID); do{ C40_Ip_Status=C40_Ip_MainInterfaceSectorEraseStatus(); }while(C40_Ip_Status==STATUS_C40_IP_BUSY); C40_IP_DEV_ASSERT(C40_Ip_Status ==STATUS_C40_IP_SUCCESS ); //Write C40_Ip_MainInterfaceWrite(FLS_SECTOR_ADDR, FLS_BUF_SIZE,LC_TxBuffer , FLS_MASTER_ID); do{ C40_Ip_Status=C40_Ip_MainInterfaceSectorEraseStatus(); }while(C40_Ip_Status==STATUS_C40_IP_BUSY); C40_IP_DEV_ASSERT(C40_Ip_Status ==STATUS_C40_IP_SUCCESS ); return C40_Ip_Status; }

上面代码是在一个PFALSH区域写入LC的值,我们需要通过SBAF来推进,则需要在启动文件(Startup_cm7.s)中设置LC的指针。

#define LF_CONFIG_ADDR (0x004EA000) .section ".boot_header","ax" .long SBAF_BOOT_MARKER /* IVT marker */ .long (CM7_0_ENABLE << CM7_0_ENABLE_SHIFT) | (CM7_1_ENABLE << CM7_1_ENABLE_SHIFT) | (CM7_2_ENABLE << CM7_2_ENABLE_SHIFT) /* Boot configuration word */ .long 0 /* Reserved */ .long CM7_0_VTOR_ADDR /* CM7_0 Start address */ .long 0 /* Reserved */ .long CM7_1_VTOR_ADDR /* CM7_1 Start address */ .long 0 /* Reserved */ .long CM7_2_VTOR_ADDR /* CM7_2 Start address */ .long 0 /* Reserved */ .long LF_CONFIG_ADDR /* Lifecycle configuration pointer */

查看

通过执行上面两个阶段的API,已成功写入ADKP和LC值了,下面需要硬件复位(休眠再唤醒或者Reset_B引脚接地),注意不是软复位。

我们可以通过IDE自带的Memory查看是否写入成功,如S32DS NXP官方开发工具。

调试测试

现在使用PEmicro调试,如果操作正确,应该看到以下信息:

这时的JTAG接口已经被禁用了,只有密码校验通过的设备才能够调试。

解锁调试接口

现在要解锁MCU,PEmicro提供了一些Python脚本。一般在S32DS这个IDE中自带,该文件包位于 NXP\S32K3xx 文件夹内。使用 PEmicro 脚本需要 Python 3.5 或更高版本来运行。UP使用的Python 3.14.5。

在该目录下打开CMD窗口,输入以下指令(密码与前面ADKP保持一致)

py authenticate_password_mode.py -hardwareid=USB1 -password=0102030405060708090A0B0C0D0E0F00

注意一点,USB1可以是用于调试的硬件 IP 地址、名称、序列号或端口名称等等。

不知道的可以查看,调试设备的配置

在调试器经过认证之后,开发人员就可以在 S32 Design Studio 或任何第三方集成开发环境中使用 PEmicro 插件来安全地调试设备了。注意:只有在安全调试模式下,设备才能继续被访问,直到下一次硬重置或电源重启。默认情况下,在调试过程中会触发硬重置,这会清除认证信息。为了避免这种情况,请在软件中指定“SECUREDEBUG”设备。

调试成功!!!

小结

最后讲一下,ADKP和LC推进之后,是无法再更改的。但是LC中我们配置的0x004EA000这个Pflash区域块是可以重新被擦除,写入数据的,相当于LC推进是一次性操作,操作完了。这个区域该怎么样还是怎么样。但是ADKP所在的Utest区域不一样,是不能被更改的,属于一次性编程区域OTP。

补充:一般调试禁用需要软硬件同步实施,这里的密码禁用其实依然不太安全,可以尝试当作一个31例程写入一个随机的密码,这样谁也不会知道了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 9:28:11

工业控制模块深度解析:从硬件架构到软件集成的实战指南

1. 项目概述&#xff1a;从“yl1640”看一个典型工业控制模块的深度解析 在工业自动化领域&#xff0c;我们经常会遇到一些由字母和数字组成的、看似神秘的代号&#xff0c;比如“yl1640”。对于刚入行的朋友来说&#xff0c;这串字符可能只是一个零件号&#xff1b;但对于有经…

作者头像 李华
网站建设 2026/6/26 9:18:33

【EF Core】值转换器

上面扯了堆没用的。下面咱们进入主题——值转换器。 从名字就知道&#xff0c;是用来给数据值做类型转换的。有大伙伴会问&#xff0c;是 .NET 类型与数据库类型吗&#xff1f;EF 自己不是有类型映射吗。老周觉得&#xff0c;准确地讲还真不是。应该说是 .NET 类型之间转换才对…

作者头像 李华
网站建设 2026/6/26 9:11:34

为什么Rust嵌入式开发仍然需要强大的静态分析

几十年来&#xff0c;软件工程师在构建嵌入式系统时一直高度依赖C和C。这些传统语言虽然能提供受限环境所需的深度控制和运行速度&#xff0c;但在内存管理和并发处理方面却存在不足。 Rust 编程语言正在成为一种解决方案。软件开发团队正迅速将Rust应用于嵌入式系统&#xff…

作者头像 李华
网站建设 2026/6/26 9:09:08

Java的java.util.HexFormat规模特性

Java 16引入的java.util.HexFormat类为十六进制数据处理提供了标准化解决方案&#xff0c;填补了长期以来Java在十六进制转换工具上的空白。这个轻量级工具类不仅简化了字节数组与十六进制字符串间的相互转换&#xff0c;更通过丰富的格式化选项满足了不同场景下的需求。本文将…

作者头像 李华
网站建设 2026/6/26 9:08:20

Llama 3指令微调实战:LoRA+QLoRA生产级落地指南

1. 项目概述&#xff1a;这不是“调个模型”那么简单&#xff0c;而是重新校准AI的认知刻度你看到标题里那个“Fine-Tuning Llama 4”&#xff0c;先别急着点开——目前根本不存在官方发布的 Llama 4。Meta 官方最新公开版本是 Llama 3&#xff08;2024年4月发布&#xff09;&a…

作者头像 李华