[!简介] HardFault是 Cortex-M 系类内核中的一种严重异常,意味着程序出现严重运行错误,CPU无法正常执行,只能进入HardFault_Handle函数中进行处理
触发Hardfault的常见原因:访问无效内存、栈溢出、执行非法指令…
定位HardFault类BUG
解析栈帧 + 获取 PC 值
无需调试器(可串口打印 / 保存故障信息) 适合栈溢出、中断嵌套异常、量产设备现场故障、复杂 HardFault
当出现HardFault时,硬件会自动把当前正在执行的任务的关键寄存器,按固定顺序压入当前栈指针(SP)指向的内存区域

- R0~R3:通用寄存器,常用于函数参数 / 临时变量
- R12:内部暂存寄存器(IP)
- LR:链接寄存器,保存函数返回地址
- PC:程序计数器,指向当前指令地址
- PSR:程序状态寄存器,保存标志位、中断优先级等 基于PC地址查反汇编即可定位绝大多数HardFault类BUG
void HardFault_Handler(void)
{ // 第一步:汇编读取栈指针,传递给 C 函数
asm(
"tst lr, #4 \n" // 检查 EXC_RETURN,判断用 MSP 还是 PSP
"ite eq \n"
"mrseq r0, msp \n" // 等于0:用主栈指针 MSP
"mrsne r0, psp \n" // 不等于0:用进程栈指针 PSP
"b HardFault_CHandler \n" // 跳转到 C 处理函数,r0=栈帧地址
);
}
void HardFault_CHandler(HardFaultStackFrame_t *stackFrame)
{
// 打印关键寄存器值(你可以改成串口输出/保存到内存)
// 核心:stackFrame->pc 是触发硬故障的指令地址!
uint32_t faultPC = stackFrame->pc;
uint32_t faultLR = stackFrame->lr;
uint32_t faultPSR = stackFrame->psr;
// 串口打印
printf("HardFault Triggered!\r\n");
printf("PC: 0x%08X\r\n", faultPC);// 关键!用这个地址查反汇编
printf("LR: 0x%08X\r\n", faultLR);
printf("PSR: 0x%08X\r\n", faultPSR);
// 死循环(避免返回后再次触发 HardFault)
while (1) { }
}asm(“bx lr”); + 调试器断点
必须连接调试器(ST-Link/J-Link)+ 断点调试 适合快速定位野指针、非法内存访问等简单故障
HardFault 99%是由于野指针和非法内存访问导致的。在HardFault函数内添加一句 asm("bx lr");, 并在此处加上断点。当代码运行至此处时,选择跳出,程序会跳转回出错之前最后一句执行的语句。
void HardFault_Handler(void)
{
asm("bx lr");
while (1) { }
}