HardFault_Handler处理Bug
出现HardFault的原因
HardFault 的本质是 “内核执行过程中检测到异常状态”,具体原因多与非法操作相关,常见场景包括:
内存访问错误
- 访问空指针(如
int *p = NULL; *p = 10;
):试图读写地址0x00000000
及附近的无效内存。 - 数组 / 缓冲区越界访问(如定义
int arr[5];
却访问arr[10]
):读写超出内存范围的地址。 - 访问未对齐的内存(部分 Cortex-M 内核不支持非对齐访问,如 32 位数据存在奇地址)。
执行非法指令
- 调用无效的函数指针(如指针未初始化或指向错误地址,
void (*p)(void) = 0x12345678; p();
)。 - 程序代码被意外篡改(如栈溢出覆盖了代码区,导致执行错误指令)。
- 运行了内核不支持的指令(如 Cortex-M0 不支持某些 Cortex-M3 的指令)。
总线错误
- 访问不存在的外设地址(如错误配置外设寄存器地址,读写了芯片物理上不存在的地址)。
- 外设访问冲突(如同时通过 DMA 和 CPU 读写同一外设,导致总线访问异常)。
栈溢出或栈损坏
- 函数递归过深、局部变量过大,导致栈空间耗尽,进而覆盖了栈外的关键数据(如函数返回地址),内核执行返回时获取到错误地址,触发 HardFault。
除数为零(部分配置下)
- 虽然 Cortex-M 内核默认允许整数除法为零(结果不确定),但某些编译器配置或库函数可能将其视为错误,间接触发 HardFault。
如何使用HardFault去排查Bug
HardFault发生时,硬件会自动把一些寄存器值推入栈,我们可以根据栈中保留的数值还原“犯罪现场“
重点关注LR和PC寄存器.
如果LR寄存器的0xFFFFFFF9,则去查看MSP的地址。然后在MSP地址向下数6个的long地址。0x08开头的就是发生错误的程序地址。
日后功力深厚了再更新。