stm32触发硬件错误位置定位

1.背景 

1. 项目中,调试过程或者测试中都会出现程序跑飞问题,这个时候问题特别难查找。

2. 触发硬件错误往往是因为内存错误。这种问题特别难查找,尤其是产品到了测试阶段,而这个异常复现又比较难的情况下,简直头疼。

3. 我目前的工作完全是没有调试器的,代码都是写好了,通过bootloader烧写进去的。也就意味着不能在void HardFault_Handler(void)中打断点,然后通过当前lr寄存器中的值查看异常地址。

参考:

STM32进入HardFault_Handler的调试方法-电子工程世界 (eeworld.com.cn)

Keil环境下STM32定位hardfault位置方法和遇到的情况 - 张士玉小黑屋 (zhangshiyu.com)

MCU HardFault_Handler调试方法_根据lr寄存器值判断msp psp-CSDN博客 

RTOS系列文章(7):CM3/4之LR寄存器、EXC_RETURN深入分析-CSDN博客

还参考了很多文章, 有些写的时候都关掉了, 这里就不列出来了. 

2.裸机程序触发硬件错误

裸机触发硬件错误时, R14(LR)寄存器的值为0xFFFFFFF9,此时看的是MSP指针保存的栈顶地址,然后在Memory Window中输入这个值(0x20000738),第6个值就是错误退的地址(也就是我这个空指针的地址),查看.map文件,显然我们的0x080001D1在0x080001cd(my_test在flash的首地址)和0x080001d3(my_test1在flash的首地址)之间。因此我们就可以定位出错误就在my_test()这个函数中。

 也可以查看汇报,看到地址(不过这里看起来有点让人蒙圈)

3.RTOS程序触发硬件错误

 RTOS触发硬件错误时, R14(LR)寄存器的值为0xFFFFFFFD, 此时看的是PSP中的栈顶地址。同上分析,我们最终也能通过.map定位错误发生的位置。

补充知识:为什么裸机的是0xFFFFFFF9(9:1001)而多线程的是0xFFFFFFFD(1101),如下图,bit2是区别的关键,后面打印错误需要用到这一点。

4.在硬件错误中断打印这些值

我们最终的目的,就是在触发硬件中断的时候,要将这些值打印出来,从而准确定位出是哪个函数造成的错误。 

typedef struct
{
    u32 R0;
    u32 R1;
    u32 R2;
    u32 R3;
    u32 R12;
    u32 LR;
    u32 PC;
    u32 xPSR;
}STACK_DATA_TYPE;
void NotOSHardFault_Handler(u32 msp_addr)
{
    STACK_DATA_TYPE *p;             //堆栈中存储的数据

    printf("\r\n-----------------ERROR -----------------\r\nHardFault_Handler\r\n");

    p = (STACK_DATA_TYPE *)msp_addr;
    printf("R0:0x%08X\r\n", p->R0);
    printf("R1:0x%08X\r\n", p->R1);
    printf("R2:0x%08X\r\n", p->R2);
    printf("R3:0x%08X\r\n", p->R3);
    printf("R12:0x%08X\r\n", p->R12);
    printf("LR:0x%08X\r\n", p->LR);
    printf("PC:0x%08X\r\n", p->PC);
    printf("xPSR:0x%08X\r\n", p->xPSR);
    printf("系统即将复位 ...\r\n");
}

void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
int msp, psp;
    
    msp = __get_MSP();
    NotOSHardFault_Handler(msp);
    
    psp = __get_PSP();
    NotOSHardFault_Handler(psp);
    

  while (1)
  {
  }
}

当前还有一个问题需要解决, 我无法获取lr寄存器中保存的值, 也就是说我无法准确的确定是进程堆栈出错还是主堆栈出错.(我测试了发现在rtos中, 如果让错误放在main函数中, 此时MSP堆栈指向的位置是出错位置, 如果让错误放在任务中, 此时PSP堆栈指向的位置是出错位置, 如果在裸机程序中, 通过MSP查找, 当前我用的是keil编译的,我不知道IAR里面是否有__get_MSP(), __get_PSP())

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

入门->放弃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值