[STM32H5] 读取 STM32H5 的 UID 触发 hardfault 问题分析

[复制链接]
31|0
STM新闻官 发表于 2026-6-20 22:27 | 显示全部楼层 |阅读模式
1. 问题现象客户反馈在 STM32H5 中通过代码读取 UID 时,会触发 Hardfault.

2. 问题重现及分析我手动通过 STM32CubeMx 生成一个基于 STM32H563 的测试工程。运行在 NUCLEOH563RE 板上。在代码中写了一个读取 UID 函数 :


  1. uint32_t deviceserial0, deviceserial1, deviceserial2;
  2. void ReadUIDTest(void)
  3. {
  4. deviceserial0 = HAL_GetUIDw0();
  5. deviceserial1 = HAL_GetUIDw1();
  6. deviceserial2 = HAL_GetUIDw2();
  7. }
然后在 main 函数中调用这个 ReadUIDTest()函数,发现正如客户所说,触发了hardfault。Keil 的 Call Stack 如下所示 :
668326a36a2ef1c3c2.png
这个问题能 100%重现问题,于是在 Keil 调试下查看故障报告窗口 :
742146a36a2ff91506.png
上图信息解析如下 :当前触发了 Bus Fault 中断,由于此中断在代码中并未使能,所以才升级为 hardfault.触发 Bus Fault 中断的原因是数据访问导致的,此数据地址为 : 0x08FFF800.通过代码中的宏定义 :#define UID_BASE (0x08FFF800UL) /*!< Unique device ID register baseaddress */可知,这个地址 0x08FFF800 刚好是芯片的 UID 地址。那么问题来了,为什么读取 UID 地址就会触发 hardfault 呢?查看芯片对应的参考手册 RM0481(Rev 4), 在第 7.3.2 节看到如下内容
404286a36a31b1b287.png
‘UID 所在 FLASH 区域为 RO 区域,它默认不支持 Cacheable 特性的,而在代码中若激活了 ICache(通过 STM32CubeMx 生成的工程默认会默认提示用户开户 I-Cache 以提高代码效率),那么代码访问 AHB 存储范围内的所有地址默认都是缓存的,也就是说,这种缓存机制跟 UID所在特殊区域的缓存特性冲突。要解决这种冲突,得借助 MPU 来改变局部区域(UID 的在地址)的缓存策略才行。知道了问题所在,那么对应的解决代码如下所示:
  1. /**
  2. * [url=/u/brief]@brief[/url] Configures the main MPU regions.
  3. * @param None
  4. * @retval None
  5. */
  6. void MPU_Config(void)
  7. {
  8. MPU_Region_InitTypeDef MPU_InitStruct;
  9. MPU_Attributes_InitTypeDef MPU_AttributesInit;
  10. /* Disable MPU */
  11. HAL_MPU_Disable();
  12. /* Define cacheable memory via MPU */
  13. MPU_AttributesInit.Number = 0;
  14. MPU_AttributesInit.Attributes = MPU_NOT_CACHEABLE;
  15. HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
  16. /* Configure UID region as Region Number 0 */
  17. MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  18. MPU_InitStruct.BaseAddress = 0x08FFF800;
  19. MPU_InitStruct.LimitAddress = 0x08FFFFFF;
  20. MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RO;
  21. MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
  22. MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  23. MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  24. MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  25. HAL_MPU_ConfigRegion(&MPU_InitStruct);
  26. /* Enable MPU (any access not covered by any enabled region will cause a fault) */
  27. HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
  28. }
在代码访问 UID 之前,先用 MPU 将 UID 所在地址区域的缓存属性关闭,如此,即可解决问题。除 UID 之外,EData, OTP 区域也有类似问题,且这种问题在以前传统的 MCU 中并不会遇到的,这也是 STM32H5 比较特别的地方之一,大家需要注意这一点。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:您的嵌入式应用将得益于意法半导体领先的产品架构、技术、多源产地和全方位支持。意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器。

1635

主题

2154

帖子

25

粉丝
快速回复 在线客服 返回列表 返回顶部
0