news 2026/6/16 3:16:49

HardFault 怎么定位?别只怪指针,看看 LR 与 CFSA

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HardFault 怎么定位?别只怪指针,看看 LR 与 CFSA

摘要:程序突然跳进HardFault_Handler,串口打印卡死,调试器也断了?不是指针乱指这么简单,而是链接寄存器(LR)​ 和异常帧(CFSA)​ 里藏着犯罪现场。本文教你如何像侦探一样还原 HardFault 的案发现场。


一、问题描述(现象)

**系统运行几天后,突然死机;

调试器暂停,PC 停在HardFault_Handler

查看 Call Stack,只有 HardFault,看不到是谁调用的。**

很多工程师的排查方向是:

  1. 数组越界?

  2. 野指针?

  3. 堆栈溢出?


二、原理分析

1. 物理模型

当异常发生时,Cortex-M 会自动把现场压入栈中。

发生异常 -> 压栈 (R0~R3, R12, LR, PC, xPSR) -> 跳转到 HardFault_Handler

2. 核心参数

  • LR (Link Register):在异常发生时,LR 会变成特殊的EXC_RETURN​ 值。

  • CFSA (Control Flow Stack Address):异常帧在栈中的位置。

  • SCB->CFSR:可配置故障状态寄存器(告诉你具体犯了什么罪)。

3. 反直觉真相

“HardFault 就是指针错了”是片面的。

  • Usage Fault:除以 0、未对齐访问。

  • Bus Fault:访问了不存在的地址(如 0x00000000)。

  • Mem Manage Fault:MPU 保护违规。

  • HardFault:以上三种没处理,或者异常嵌套太深。


三、工程级解决方案

方案 1:在 HardFault 里打印“遗言”(最有效)

修改HardFault_Handler,把寄存器吐出来。

void HardFault_Handler(void) { __asm volatile ( " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" " mrsne r0, psp \n" " ldr r1, [r0, #24] \n" // 取出 PC " ldr r2, [r0, #28] \n" // 取出 xPSR " b HardFault_Dump \n" ); } void HardFault_Dump(uint32_t *stack) { uint32_t pc = stack[6]; // Program Counter uint32_t lr = stack[5]; // Link Register printf("HardFault! PC = 0x%08X, LR = 0x%08X\n", pc, lr); while(1); }

方案 2:解读 LR(EXC_RETURN)

LR 的值告诉你异常前用的是哪个栈

LR 值

含义

0xFFFFFFFD

异常前使用PSP(线程栈,RTOS 任务)

0xFFFFFFF1

异常前使用MSP(主栈,中断/系统)

经验:如果是0xFFFFFFFD,多半是 RTOS 任务栈溢出。

方案 3:查看 SCB->CFSR

读取故障状态寄存器,精准定罪。

uint32_t cfsr = SCB->CFSR; if (cfsr & (1<<0)) printf("Instruction access violation\n"); if (cfsr & (1<<1)) printf("Data access violation\n"); if (cfsr & (1<<8)) printf("Unaligned access\n"); if (cfsr & (1<<9)) printf("Divide by zero\n");

四、选型避坑建议

  1. 不要只用 while(1)

    • 空的 HardFault 是自杀行为,一定要打印信息。

  2. 栈大小

    • RTOS 任务栈至少 512 字节,中断栈至少 1KB。

  3. MPU(内存保护)

    • 如果开启了 MPU,一定要检查访问权限。


五、总结 Checklist

  • [ ] HardFault_Handler 中是否打印了 PC 和 LR?

  • [ ] 是否通过 LR 判断了是 MSP 还是 PSP 溢出?

  • [ ] 是否读取了 SCB->CFSR 来定位具体故障类型?

  • [ ] RTOS 任务的栈大小是否足够(> 512B)?


六、写在最后(关注我,少走弯路)

我是 gqqsherry,一个拒绝调包、专注底层逻辑的嵌入式工程师。

HardFault 不是终点,而是系统给你的最后一张求救纸条。读懂它,你就能修好那个潜伏了三个月的 Bug。

关注我的专栏《嵌入式底层避坑指南》,下一篇我们将深入解析《复位与启动系列完结篇:为什么掉电瞬间数据会丢?》

👉下一篇预告:《复位与启动系列完结篇:为什么掉电瞬间数据会丢?


原创文章,转载请注明出处。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/16 3:13:51

如何快速部署FLUX.1-dev量化模型:面向AI绘画开发者的完整指南

如何快速部署FLUX.1-dev量化模型&#xff1a;面向AI绘画开发者的完整指南 【免费下载链接】flux1-dev-bnb-nf4 项目地址: https://ai.gitcode.com/hf_mirrors/lllyasviel/flux1-dev-bnb-nf4 在AI绘画技术快速发展的今天&#xff0c;如何在有限的计算资源下运行大型扩散…

作者头像 李华
网站建设 2026/6/16 3:02:57

PCB电路板由什么材料构成?一文讲透制造流程与关键工艺解析

无论是智能手机、工业控制设备&#xff0c;还是新能源汽车、医疗仪器和机器人系统&#xff0c;几乎所有电子产品都离不开PCB&#xff08;Printed Circuit Board&#xff0c;印制电路板&#xff09;。 对于许多研发工程师和采购人员而言&#xff0c;了解“PCB是由什么材料制成的…

作者头像 李华
网站建设 2026/6/16 3:02:53

如何用开源工具快速找回遗忘的压缩包密码:终极指南

如何用开源工具快速找回遗忘的压缩包密码&#xff1a;终极指南 【免费下载链接】ArchivePasswordTestTool 利用7zip测试压缩包的功能 对加密压缩包进行自动化测试密码 项目地址: https://gitcode.com/gh_mirrors/ar/ArchivePasswordTestTool 面对加密压缩包却忘记了密码…

作者头像 李华
网站建设 2026/6/16 3:01:12

电脑变Wi-Fi热点:Windows/macOS系统原生功能与命令行创建全攻略

1. 项目概述&#xff1a;为什么我们需要电脑热点&#xff1f;在咖啡馆、机场或者临时租住的房间里&#xff0c;你手头只有一台连着有线宽带的笔记本电脑&#xff0c;但手机、平板或者同事的设备却急需网络。这时候&#xff0c;把电脑变成一个临时的Wi-Fi路由器&#xff0c;共享…

作者头像 李华
网站建设 2026/6/16 2:59:50

申论素材笔记|热点|积累

申论素材笔记|热点|积累资料全科都有申论素材笔记 PDFhttps://tool.nineya.com/s/1jr3ck8t3 【数学真题】1. 函数 f(x)x-3x 的零点个数为&#xff08; &#xff09; A. 3 B. 2 C. 1 D. 0 答案&#xff1a;A 解析&#xff1a;x-3x0 → x(x-3)0 → x0 或 x√3&#xff0c;共3个零…

作者头像 李华