labasi 发表于 2021-6-3 16:00

stm32 HardFault错误调试记录

本帖最后由 labasi 于 2021-6-3 16:04 编辑

当程序报错时候 我们要定位到出错位置 才能更快的解决问题。
当程序进入hardfault中断算是一个比较麻烦的bug吧。本文把当程序进入硬错误中断时候的调试方式做个记录。
先说第一种方式,第一种方式比较简单,可以直接在hardfault中断中打个断点,当程序进入hardfault中断后,查看当前的栈调用情况。进而确定出错的函数,然后查看相应函数中错误。
模拟错误
这里我直接访问一个不存在地址让程序报个中断。

int main(void)
{
      int i = 0;
      for(i = 0; i < 100; i++)
      {
                *((unsigned int *)0x08100004) = 0x1;
      }
    while(1)
      {
      }      
}


我用的是STM32F103VG的芯片,1MFlash,最大地址也就是0x08100000,所以当调试这段代码是,程序会进HardFault中断。







labasi 发表于 2021-6-3 16:02

解决bug
简单方式
我们直接在HardFault_Handler打个断点。当全速运行后程序会进入这个中断,然后再找个断点停下,此时我们去看stackcall使用情况。如下图,通过栈情况我们可以看到程序是从main进入错误中断的,所以此时我们只需要进入main函数排查错误即可。



labasi 发表于 2021-6-3 16:04

终极手段
第一种方式有时候并不合适,比如函数内代码量较多,或者程序开了优化,以上方式就不太合适了。此时可以这样做。
第一步还是一样,在HardFault_Handler打断点。
停在断点后,去查看Fault report。打开方式如图:


打开fault reports问题就一目了然了,可以看到Hard Faults的FORCED位和Bus Faults的IMPRECISERR位被置位了。我们错误代码也确实是访问一个不存在地址,所以报了总线错误。
这里为什么总线错误而触发的是Hard Fault中断呢,

查文档可以得知,所有被除能的 fault,都将“上访”(escalation) 成 硬 fault。这里就可以理解了。
进入中断之前,芯片会有压栈操作,进入错误中断也不例外,我们可以根据自己程序是使用MSP还是PSP,找到进中断之前的栈情况。

此处为什么是xSP-24,这里简单说一下,这里需要查一下stm32的自动入栈顺序。

N-32-(N-8) = N-24

此处还要注意一点,虽然是减24,但栈是向下增长的,所以实际计算应该是加地址。



查看寄存器可以看到,现在MSP值为0x20000528,然后在Memory窗口查看这个地址的代码,因为地址是32位的。所以以unsigned long格式查看,这样方便等会复制地址。上文可知要加24,24/4=6,地址加6也就是0x0800047D,然后去看汇编窗口对应地址代码


通过这种方式可以看到,定位到了相关错误代码位置,然后剩下的事情就简单多了。

总结
总的来说出现硬错误还是一件比较恶心的事情,平时编码养成好习惯,指针切记初始化,参数做范围判断,通讯尽可能考虑全出错处理。



页: [1]
查看完整版本: stm32 HardFault错误调试记录