在stm32调试中有时候会进入硬件异常中断HardFault_Handler。SEGGER公司(旗下有大名鼎鼎的emWin图形工具)提供一种硬件异常中断HardFault_Handler定位调试方法。在MDK和IAR开发环境都适用。 这里,我们在MDK开发环境上记录一次调试经历。
1、硬件异常案例
主函数是对按键K1和摇杆OK的接收处理操作,如伪代码1
伪代码1int main(void)
{
//按键初始化函数
key_init();
//键值读取函数
switch(get_keyVaule())
{
case KEY_DOWN_K1: /* K1键按下 */
{
printf("K1键按下\r\n");
volatile unsigned int* p;
unsigned int n;
p = (unsigned int*)0xCCCCCCCC;
n = *p;
(void)n;
}
break;
case JOY_DOWN_OK: /* 摇杆OK键按下 */
printf("摇杆OK键按下\r\n");
break;
default:
/* 其它的键值不处理 */
break;
}
}
下载后程序正常运行,但当按下按键K1时候就进入硬件异常中断,那么怎么定位硬件异常的问题点呢?这就要用到SEGGER公司(旗下有大名鼎鼎的emWin图形工具)提供的一种硬件异常中断HardFault_Handler定位调试方法。
2、移植SEGGER公司硬件异常分析文件
直接将【HardFaultHandlerMDK】文件夹中两个文件加入到工程中,如图1
图1
注:在文件 SEGGER_HardFaultHandler.c 里面都添加了串口打印功能,方便通过串口打印提示是否进入硬件异常,如代码2
代码2#if 1
{
const char *pError = ERR_INFO;
uint8_t i;
for (i = 0; i < strlen(ERR_INFO); i++)
{
USART1->TDR = pError[i];
/* 等待发送结束 */
while((USART1->ISR & USART_ISR_TC) == 0);
}
}
#endif
3、调试硬件异常步骤
开始使用SEGGER公司硬件异常分析文件定位造成硬件异常的问题点。
进入硬件调试界面,点击【Run(F5)】–引发硬件中断异常(本案例是按下K1键会造成硬件中断异常)–点击【Stop】,显示界如图2
图2
打开Watich窗口,将变量_Continue和结构体变量HardFaultRegs加入进来,并将变量_Continue改成一个非0值,如图3、图4
图3
图4
按下【Step(F11)】进行单步调试,直到_Continue=0(这个代码后面还有一个while 循环),继续将变量_Continue改成一个非0值。此时再按下【Step(F11)】进行单步调试。此时进入硬件异常前下一条要执行的指令(可能还是这个函数本身,因为一个函数由多个指令完成),定位到了出问题的地方,如图5
图5
如果此时还看不出为什么这里造成了硬件异常中断,可以通过【Watch1窗口】添加的结构体变量HardFaultRegs来参看作为提示。具体操作为:展开【HardFaultRegs】–找到【bits】显示为1的,如图6
图6
那么这个FORCED=1表示什么意思呢?通过查看SEGGER_HardFaultHandler.c文件中源码,找到FORCED定义位置,如代码3
代码3union {
volatile unsigned int byte;
struct {
unsigned int UnusedBits : 1;
unsigned int VECTBL : 1; // Indicates hard fault is caused by failed vector fetch
unsigned int UnusedBits2 : 28;
unsigned int FORCED : 1; // Indicates hard fault is taken because of bus fault/memory management fault/usage fault
unsigned int DEBUGEVT : 1; // Indicates hard fault is triggered by debug event
} bits;
} hfsr;
对于FORCED的解释为:Indicates hard fault is taken because of bus fault/memory management fault/usage fault,即总线故障或内存管理故障或使用故障。查看定位的故障点源码的前一句p = (unsigned int*)0xCCCCCCCC;我们猜测是发生了内存管理故障,我们打开【内存窗口】,如图7
图7
定位到内存位置为0xCCCCCCCC,显示都是问号,说明内存地址超过最大地址,找到产生硬件中断原因!如图8
图8
至此,stm32h7“HardFault_Handler(硬件异常)分析”操作完毕!
4、补充说明
“3、调试硬件异常步骤”操作显得比较麻烦,其实有种更加便捷方式,即还原硬件中断现场,【View】–【Call Stack Window】,如图9
图9
在【Call Stack+Locals】界面点击【HardFaultHandler】–【鼠标右键】–【Show Caller Code】,直接定位到造成硬件中断的语句,如图10
图10