在NVIC中有一个硬fault状态寄存器(HFSR),它指出产生硬fault的原因。如果不是由于取向量造成的,则硬fault服务例程必须检查其它的fault状态寄存器,以最终决定是谁上访的。
1、寄存器描述
首先查看硬故障寄存器,判别原因。
硬故障状态寄存器
硬fault状态寄存器(地址:0xE000_ED2C)
位段名称描述
31DEBUGEVT硬fault因调试事件而产生
30FORCED硬fault是总线fault,存储器管理fault或是用法fault上访的结果
29:2
1VECTBL硬fault是在取向时发生的
0
121页手册
各个fault状态寄存器(FSRs)都保持住它们的状态,直到手工清除。Fault服务例程在处理了相应的fault后不要忘记清除这些状态,否则如果下次又有新的fault发生时,服务例程在检视fault源时又将看到早先已经处理的fault状态标志,因此无法判断哪个fault是新发生的。
293页
FORCED
使用硬故障寄存器来获取激活硬故障处理器的事件的相关信息。
寄存器地址、访问类型和复位状态:
地址0xE000ED2C
访问类型读/写清除
复位状态0x00000000
HFSR是一个写-清除寄存器。即向该位写1可以将其清除。
R14,R15的地址就是我们出错的代码所在的地址,需要在这个地址基础上,首先偶数对齐,然后向上减去8个字节。
【调试STM32遇到Hardfault知识总结】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|基于STM32和freeRTOS智能门锁设计方案
- 日常分享|共享充电宝方案原理,具体部件组成以及主控MUC参数
- #|ARM裸机开发(汇编LED灯实验(I.MX6UL芯片))
- STM32|STM32的四种IO输出模式
- STM32 远程升级(ISP / IAP)
- stm32|stm32f103can总线过滤器配置
- STM32CubeMX配置SDIO模式(非DMA方式)
- STM32|如何建一个STM32F030标准库工程模板
- STM32 时钟RCC相关配置参考stm32f10x_rcc.h
- STM32 NVIC