[APM32F4] 在APM32F407上研究hardfault响应时机

[复制链接]
 楼主| onemoren 发表于 2025-6-25 14:44 | 显示全部楼层 |阅读模式
本帖最后由 onemoren 于 2025-6-25 14:45 编辑

#每日话题# #技术资源#

在APM32F407上研究hardfault响应时机


一般来说,在自己的软件、硬件平台上遇到hardfault还是比较容易定位的。此文以APM32F407做为实验平台,在一个GPIO的例程上制造hardfault,来看其产生后,通过栈中内容回溯hardfault产生的时机。
实验程序如下,很简单:
图片1.png
Faulttest()中包含了越界内存的写入语句,执行时必然会引起hardfault。在仿真条件下全速运行,果然看到PC跳进了硬件错误中断函数中:
图片2.png
此时可以查出SP即栈地址为0x20000640,在memory窗口中查这个地址,可以直接查到hardfault响应前的LR地址为0x08000733。在汇编程序中查找0x08000733位置(0x08000732对齐后的地址),发现LR指向的是while(1)循环体的开始语句:
图片3.png
矛盾点出现了:在调用faulttest(0x55)时,LR应该指向Delay_Init()首地址。当hardfault响应时,LR应该保持指向Delay_Init()首地址并入栈保存,LR应该是0x0800072E,而不是0x08000733。百思不得其解。
除非在hardfault响应中断前,PC指针已指向Delay_Init()甚至可能已经执行了Delay_Init()中的部分程序?
难道hardfault响应是有一定的滞后性?当程序执行*(uint8_t *)0xAF00000 = 0x55时,芯片此时并不立即响应hardfault,而是PC指针又再往下执行了若干条指令?PC指针可能跑到或跑进Delay_Init()中?
接着实验。在Delay_Init()前加入6条NOP指令:
图片4.png
可以看到,hardfault响应时,LR指向0x800072F,也就是说,LR保持着调用faulttest(0x55)时的PC返回值。Hardfault响应前,PC并没有跑到或跑进Delay_Init()中。
将NOP指令减少到3条:
图片5.png
和6条NOP指令效果一致。再将NOP指令减少到2条:
图片6.png
LR值变为0x8000737,说明hardfault产生前PC指向过或跑进过Delay_Init()。
以上实验说明,MCU遇到hardfault时,并不是在产生hardfault的那条指令上立即停止后去执行硬件错误中断服务函数,而是有一定的滞后性,PC指针可能还会向下执行几条指令,才被hardfault中断掉。
当然,我这个实验只研究了内存越界访问时的hardfault响应时机是这样。不知道其它类型的hardfault(如真正的硬件异常引起的错误)是否会“立即”中断程序执行(无滞后性)。这种缺陷芯片可要有缘遇到才有机会研究。
发光的梦 发表于 2025-6-25 17:56 | 显示全部楼层
PC指针可能还会向下执行几条指令,才被hardfault中断掉。
我还一直以为立即进入hardfault了呢?
不过,会不会是MCU对指令进行了预取了呢?
 楼主| onemoren 发表于 2025-7-11 10:04 | 显示全部楼层
如果是立即,那hardfault原因定位会变得非常容易。
jobszheng 发表于 2025-7-17 22:43 | 显示全部楼层
原来是看堆栈来分析啊!
我觉得我的水平还是分析一下源代码方便。
天体书记 发表于 2025-7-21 14:38 | 显示全部楼层
这汇编看着就头疼。
我还是小心编写代码吧
暖心小太阳 发表于 2025-7-23 08:04 | 显示全部楼层
非常有趣的实验分析!通过这种方式可以更精确地理解hardfault的响应机制。你的实验结果表明,hardfault并不是在产生错误的指令上立即响应,这对于我们理解MCU的行为模式非常有帮助。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

66

帖子

2

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