调试STM32遇到Hardfault知识总结

在NVIC中有一个硬fault状态寄存器(HFSR),它指出产生硬fault的原因。如果不是由于取向量造成的,则硬fault服务例程必须检查其它的fault状态寄存器,以最终决定是谁上访的。




1、寄存器描述


首先查看硬故障寄存器,判别原因。


硬故障状态寄存器


硬fault状态寄存器(地址:0xE000_ED2C)
位段   名称            描述
31     DEBUGEVT        硬fault因调试事件而产生
30     FORCED          硬fault是总线fault,存储器管理fault或是用法fault上访的结果
29:2
1      VECTBL          硬fault是在取向时发生的
0


121页手册


各个fault状态寄存器(FSRs)都保持住它们的状态,直到手工清除。Fault服务例程在处理了相应的fault后不要忘记清除这些状态,否则如果下次又有新的fault发生时,服务例程在检视fault源时又将看到早先已经处理的fault状态标志,因此无法判断哪个fault是新发生的。




293页


FORCED
使用硬故障寄存器来获取激活硬故障处理器的事件的相关信息。
寄存器地址、访问类型和复位状态:
地址          0xE000ED2C
访问类型      读/写清除
复位状态      0x00000000
HFSR是一个写-清除寄存器。即向该位写1可以将其清除。




R14,R15的地址就是我们出错的代码所在的地址,需要在这个地址基础上,首先偶数对齐,然后向上减去8个字节。



STM32出现HardFault_Handler故障的原因主要有两个方面:
1、内存溢出或者访问越界。这个需要自己写程序的时候规范代码。
2、堆栈溢出,增加堆栈的大小。


科普小知识:
LR   连接寄存器
MSP  主堆栈指针
PSP  进程堆栈指针


Banked R13:两个堆栈指针
Cortex-M3拥有来个堆栈指针,然而它们是banked,因此任一时刻只能使用其中的一个。
主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包括中断服务例程)
进程堆栈指针(PSP):由用户的应用程序代码使用。
堆栈指针的最低两位永远是0,这意味着堆栈总是4字节对齐的。


排查方法:
发生异常之后可首先查看LR寄存器中的值,确定进入异常前一刻使用的堆栈为MSP或PSP,然后找到相应堆栈的指针?
注:在HandFault_Handler(void)中断里第一条语句打断点,进入中断后,查看LR寄存器的值,如果是0XFFFFFFF9,那么中断前使用的是MSP,如果是0XFFFFFFFD,那么中断前使用的是PSP:


中断/异常的相应序列
当CM3开始相应一个中断时,会在它看不见的体内喷涌起三股暗流:
1)入栈:把8个寄存器的值压入栈。
2)取向量:从向量表中找出对应的服务新恒旭入口地址。
3)选择堆栈指针MSP/PSP,更新堆栈指针SP,更新连接器LR,更新程序计数器PC.


另一种方法:
    默认的HardFaudler 处理方法不是死循环么?将它改成BX LR直接返回的形式。然后再这条语句打个断点,一旦在断点中停下来,说明出错了,然后再返回,就可以返回到出错的位置的下一条语句哪里。
_asm void wait()
{
    BX lr  //BX无条件转移指令
}


void HardFault_Handler(void)
{
    wait();
}


你可能感兴趣的:(stm32)