公开课是什么意思| 寿命是什么意思| 体重kg是什么意思| 的近义词是什么| 夹页念什么| 脖子有痣代表什么意思| 心悸心慌焦虑吃什么药能缓解| 长期熬夜吃什么可以补回来| 舌系带短挂什么科| 血压高吃什么菜和水果能降血压| 整体认读音节有什么| 挑食是什么意思| 扁桃体发炎有什么症状| 鸟牌是什么牌子的衣服| 中校相当于政府什么官| 女人高潮是什么感觉| 什么药治咳嗽最好| 斐乐是什么档次| 反酸水吃什么药| 不可抗力是什么意思| 介入室是干什么的| 排卵期出血是什么原因引起的| 日语亚麻得是什么意思| 米线里的麻油是什么油| 老人肚子胀是什么原因| 运营商是什么意思| 第二性征是什么意思| 嘎哈是什么意思| 狗不能吃什么东西| 焦亚硫酸钠是什么| 脚发胀是什么前兆| 窦性心动过速是什么意思| 借口是什么意思| 老鼠的尾巴有什么作用| 肝炎五项检查是什么| 左小腹疼是什么原因| 儿童发育过早应该挂什么科| gsp全称是什么| 厥是什么意思| 什么是同比| 以什么之名| 普陀山求什么最灵验| 吃桂圆干有什么好处和坏处| 什么是气血不足| 涩是什么意思| 支原体感染是什么引起的| 女孩第一次来月经需要注意什么| 肚子大腿细是什么原因| 2001属什么生肖| 补气养血吃什么中成药| 肺有问题挂什么科| 饴糖是什么糖| 白猫来家里有什么预兆| 蜜蜡属于什么五行属性| 月经一直不干净是什么原因引起的| kick什么意思| 下饭是什么意思| 家里来猫是什么征兆| 流口水是什么病的前兆| 肌层回声欠均匀是什么意思| 火龙果什么人不能吃| 脚脖子疼是什么原因| 急性支气管炎吃什么药| 布洛芬吃多了有什么后果| 怀孕不能吃什么| 茉莉花茶有什么作用| 艾滋通过什么途径传播| 为什么不能拜女娲娘娘| 10.30什么星座| 黄精泡水喝有什么功效| 卵泡期什么意思| 2021属什么生肖| 有什么水果| 成龙真名叫什么名字| 桦树茸有什么作用| 姑息治疗什么意思| 1a是什么意思| 怀孕不能吃什么药| 什么是脑中风| 兵马俑在什么地方| 农历8月15是什么节日| 上午10点半是什么时辰| 县武装部长是什么级别| 坐骨神经痛用什么药最好| 孕妇什么水果不能吃| vogue是什么意思| 吃什么可以淡化黄褐斑| 蓝色的小药丸是什么药| 1940年出生属什么生肖| c60是什么| 坐飞机不能带什么物品| 维生素c补什么| 吃什么可以美白| 甲功能5项检查是查的什么| 属马女和什么属相最配| 蔻驰手表属于什么档次| 永字五行属什么| 猫起什么名字好| 嘴巴很臭是什么原因引起的| nb是什么意思| 柏字五行属什么| 什么是肿瘤| 毛笔是用什么毛做的| 血糖高的人吃什么好| 尿结晶是什么意思| 足是什么结构| 头孢是治疗什么病的| 121是什么意思| 柱状上皮外移什么意思| 96是什么意思| 左下腹是什么器官| 世界上最硬的东西是什么| 执子之手什么意思| 包皮溃烂是什么原因| 空调制热效果不好什么原因| 心胸狭窄是什么意思| 按摩有什么好处和坏处| 2027年属什么生肖| 梦见过河是什么意思| 天天想睡觉没精神是什么原因| 橄榄油什么牌子最好| 蚂蚁上树是什么菜| 养血清脑颗粒治什么病| 左边太阳穴疼是什么原因| 穿什么衣服| 古代四大发明是什么| 唐卡是什么材料做的| 什么是善| 吕布的坐骑是什么| 刘庄为什么要灭了阴家| 不知道干什么| 潘多拉属于什么档次| 化疗能吃什么水果| 唐氏是什么意思| 原生家庭是什么意思| 小孩c反应蛋白高说明什么| 男人鼻头有痣代表什么| 失眠挂什么科| 牙龈肿痛挂什么科| 什么什么致志| 情非得已是什么生肖| 心慌是什么感觉| 省内流量是什么意思| 缘起缘灭是什么意思| 什么人需要做心脏造影| 天荒地老什么意思| 弥留之际什么意思| 冷喷机喷脸有什么好处| 圆脸适合什么镜框| 矜贵是什么意思| 人力资源是什么意思| 什么是天珠| xo是什么酒| 结婚12年是什么婚| 高脂血症吃什么药| 甜醋是什么醋| 开市是什么意思| 广东有什么好玩的地方| 项羽的老婆叫什么| 什么样的西瓜甜| 想留不能留才最寂寞是什么歌| 血常规主要检查什么| 什么米好吃又香又软| 蛇蛋是什么样子的| 角质是什么| utc是什么时间| 阴阳二气是什么意思| 琉璃色是什么颜色| 什么是癔病| 做梦梦到乌龟是什么预兆| 内分泌是什么| 胰岛素高有什么危害| 刺猬的刺有什么作用| 儿童中耳炎用什么药最好| 纸是什么生肖| 穷的生肖指什么生肖| 秋后问斩是什么意思| 儿童中耳炎用什么药最好| 冠状沟是什么| 7年之痒是什么意思| 腰膝酸软是什么症状| 吸允的读音是什么| 吃什么盐最好| 10月什么星座| 多囊为什么要跳绳而不是跑步| 铁蛋白偏低是什么意思| 引力是什么| 肖想是什么意思| 紫菜不能和什么一起吃| 小孩流鼻涕咳嗽吃什么药| 为什么困但是睡不着| ped是什么意思| 肝不好吃什么药最好| 感觉牙齿松动是什么原因| 大便黑色什么原因| 翰字五行属什么| 红斑狼疮是什么| 白发缺少什么维生素| 女性下面流水什么原因| 灰指甲不治疗有什么后果| 8月是什么季节| 大宝贝是什么意思| 有口臭去医院挂什么科| 氯雷他定片治什么病| 结石有什么症状| 白龙马是什么生肖| navigare是什么牌子| 关节疼痛挂什么科| 猴戏是什么意思| 2022年属虎的是什么命| 妈咪是什么意思| 梦见狼狗是什么预兆| 羊白是什么| 严惩不贷是什么意思| 胎盘成熟度2级是什么意思| 挂匾是什么意思| 长期吸烟容易引起什么疾病| llc是什么意思| 孕酮低是什么原因| 普罗帕酮又叫什么| 自控能力是什么意思| 干咳嗽吃什么药| 女人气虚吃什么补最快| 脑震荡后眩晕吃什么药| 敌对是什么意思| 大便发黑是什么原因| hr医学上是什么意思| 痔疮应该挂什么科室| 一个万一个足念什么| 女性潮红是什么意思| 吃什么补钾| 胃隐隐作痛吃什么药| 虚岁29岁属什么生肖| 蜂蜜水什么时间喝最好| 滚刀肉是什么意思| 血管紧张素是什么意思| 股票加杠杆是什么意思| 沉不住气什么意思| 毛鸡蛋是什么| 擦汗表情是什么意思| 注明是什么意思| 乳腺导管局限性扩张是什么意思| 画什么才好看| 上天的动物是什么生肖| 尿酸高适合吃什么水果| 解脲脲原体阳性是什么病| 飞鸟集讲的是什么| 钾高了会出现什么症状| 中暑喝什么药| 米氮平是什么药| ct检查什么| 位移是什么| 巴甫洛夫的狗比喻什么| 用盐泡脚有什么好处| 扁桃体结石有什么危害| 遣返回国有什么后果| 赤道2什么时候上映| 眼袋是什么原因造成的| 蛇胆是什么| 右边锁骨疼是什么原因| 眼疖子用什么药| 饮鸩止渴是什么意思| 什么家常菜好吃| 什么的鼻子| 百度
这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 ? 论坛首页 ? 嵌入式开发 ? STM32 ? ARMCortex-M(STM32)如何调试HardFault

共3条 1/1 1 跳转至

ARMCortex-M(STM32)如何调试HardFault

菜鸟
2025-08-04 16:20:57     打赏
百度 描述电竞市场规模巨大的报告数不胜数,越来越多人想要拥有一个俱乐部。

HardFault 是 ARM Cortex-M 处理器中的一种异常。当处理器遇到无法处理的错误,或者配置为处理特定类型错误(如总线错误、内存管理错误、用法错误)的异常处理程序被禁用,或者在处理这些特定错误的过程中又发生了其他错误时,就会触发 HardFault。它是一个“兜底”的异常,表明系统遇到了严重问题。

调试 HardFault 需要耐心和系统的方法。关键在于:

实现一个能捕获足够信息的 HardFault_Handler。利用调试器获取故障状态寄存器和异常堆栈帧的值。仔细解读这些值,特别是 CFSR, HFSR, MMFAR, BFAR 以及堆栈中的 PC。结合反汇编和源代码,定位到触发故障的具体指令和代码行。分析常见原因(指针、越界、堆栈、对齐、MPU 等)并修复。

发生 HardFault 时,处理器会自动将一些关键的寄存器压入当前使用的堆栈(MSP 或 PSP),并跳转到 HardFault 处理程序。

我们的首要任务就是编写一个有效的 HardFault 处理程序,从中提取有用的信息。

1、步骤 1: 实现一个有效的 HardFault 处理程序

默认的 HardFault_Handler 通常是一个无限循环 while(1);。我们需要替换它,使其能够捕获并报告故障信息。

在你的项目中(通常在 stm32xxxx_it.c 或类似文件中)找到 HardFault_Handler 函数,并用以下代码替换或修改:

// 定义一个结构体来存储从堆栈中提取的寄存器值
typedefstruct {
    uint32_t r0;
    uint32_t r1;
    uint32_t r2;
    uint32_t r3;
    uint32_t r12;
    uint32_t lr; // Link Register
    uint32_t pc; // Program Counter
    uint32_t psr;// Program Status Register
} HardFaultRegs_t;
// 全局变量,用于在调试器中查看
volatile HardFaultRegs_t stacked_regs;
volatileuint32_t cfsr_val;
volatileuint32_t hfsr_val;
volatileuint32_t dfsr_val;
volatileuint32_t afsr_val;
volatileuint32_t mmfar_val;
volatileuint32_t bfar_val;
volatileuint32_t stacked_sp; // 保存堆栈指针本身的值
// HardFault 处理函数
// 使用 __attribute__((naked)) 避免编译器生成额外的栈操作代码
voidHardFault_Handler(void) __attribute__((naked));
voidHardFault_Handler(void)
{
    // 获取当前使用的堆栈指针 (MSP 或 PSP)
    // TST LR, #4 测试 LR 的 bit 2 (EXC_RETURN 的 bit 2)
    // 如果 bit 2 为 1,表示异常返回时使用 PSP;否则使用 MSP
    __asm volatile(
        " TST LR, #4n"          // Test bit 2 of LR: 0 = MSP, 1 = PSP
        " ITE EQn"             // If-Then-Else based on EQ flag (result of TST)
        " MRSEQ R0, MSPn"      // EQ=1 (bit 2 is 0): Use MSP, move MSP to R0
        " MRSNE R0, PSPn"      // NE=0 (bit 2 is 1): Use PSP, move PSP to R0
        " MOV %0, R0n"         // Move the selected stack pointer to the C variable 'stacked_sp'
        : "=r" (stacked_sp)    // Output operand: stacked_sp C variable
        :                      // Input operands: none
        : "r0"                 // Clobbered registers: R0 is used internally
    );
    // 从获取的堆栈指针处加载寄存器值到结构体
    // stacked_sp 现在指向 R0 的位置
    stacked_regs.r0 = *((volatileuint32_t*)(stacked_sp + 0));
    stacked_regs.r1 = *((volatileuint32_t*)(stacked_sp + 4));
    stacked_regs.r2 = *((volatileuint32_t*)(stacked_sp + 8));
    stacked_regs.r3 = *((volatileuint32_t*)(stacked_sp + 12));
    stacked_regs.r12= *((volatileuint32_t*)(stacked_sp + 16));
    stacked_regs.lr = *((volatileuint32_t*)(stacked_sp + 20));
    stacked_regs.pc = *((volatileuint32_t*)(stacked_sp + 24));
    stacked_regs.psr= *((volatileuint32_t*)(stacked_sp + 28));
    // 读取故障状态寄存器
    cfsr_val = (*((volatileuint32_t*)0xE000ED28));
    hfsr_val = (*((volatileuint32_t*)0xE000ED2C)); // 注意:HFSR 地址是 0xE000ED2C
    dfsr_val = (*((volatileuint32_t*)0xE000ED30));
    afsr_val = (*((volatileuint32_t*)0xE000ED3C));
    // 检查 MMFAR 和 BFAR 是否有效并读取
    if (cfsr_val & (1 << 7)) { // MMARVALID bit in MMFSR
        mmfar_val = (*((volatileuint32_t*)0xE000ED34));
    } else {
        mmfar_val = 0xFFFFFFFF; // 无效
    }
    if (cfsr_val & (1 << 15)) { // BFARVALID bit in BFSR
        bfar_val = (*((volatileuint32_t*)0xE000ED38));
    } else {
        bfar_val = 0xFFFFFFFF; // 无效
    }
    // 在这里可以添加代码将这些变量的值通过串口、SWO 或其他方式打印出来
    // printf("HardFault!n");
    // printf("SP = 0x%08Xn", stacked_sp);
    // printf("R0 = 0x%08Xn", stacked_regs.r0);
    // printf("R1 = 0x%08Xn", stacked_regs.r1);
    // ... (打印其他寄存器)
    // printf("PC = 0x%08Xn", stacked_regs.pc); // 出错指令的下一条地址
    // printf("LR = 0x%08Xn", stacked_regs.lr);
    // printf("PSR= 0x%08Xn", stacked_regs.psr);
    // printf("CFSR=0x%08Xn", cfsr_val);
    // printf("HFSR=0x%08Xn", hfsr_val);
    // printf("MMFAR=0x%08Xn", mmfar_val);
    // printf("BFAR=0x%08Xn", bfar_val);
    // 设置一个断点在这里,或者进入无限循环等待调试器连接
    __asm volatile("BKPT #0n"); // Software breakpoint
    // 或者
    // while(1);
}

注意:

__attribute__((naked)) 告诉编译器不要生成函数入口和出口代码(如压栈、出栈),因为我们需要精确控制堆栈指针。volatile 关键字确保编译器不会优化掉对这些变量的读写。代码中包含了读取 MSP 或 PSP 的汇编指令。你需要根据你的项目配置(如串口初始化)来添加打印信息的代码。最后使用 BKPT #0 可以在 HardFault 发生时触发一个软件断点,让调试器停在 HardFault_Handler 中,方便查看变量值。

2、步骤 2: 复现 HardFault 并使用调试器分析

编译并下载包含上述 HardFault_Handler 的代码到目标板。

连接调试器(如 ST-Link, J-Link)。

运行代码直到 HardFault 发生。如果设置了 BKPT #0,程序会自动停在断点处。如果没有设置断点,并且处理函数最后是 while(1);,则在 HardFault 发生后手动暂停程序,程序计数器应该停在 while(1); 循环内。

检查变量值在调试器的 Watch 窗口或 Memory 窗口中查看 stacked_regs, cfsr_val, hfsr_val, mmfar_val, bfar_val 等变量的值。

3、步骤 3: 解读故障信息

分析 CFSR

MMFSR (位 [7:0]):IACCVIOL (位 0): 指令访问冲突 (如从 XN 区域取指)。DACCVIOL (位 1): 数据访问冲突 (如写入只读区)。MUNSTKERR (位 3): MemManage Fault 在异常返回时出栈错误。MSTKERR (位 4): MemManage Fault 在异常进入时压栈错误。MLSPERR (位 5): MemManage Fault 发生在浮点惰性状态保存期间。MMARVALID (位 7): MMFAR 中的地址有效。BFSR(位 [15:8]):IBUSERR (位 8): 指令预取导致的总线错误。PRECISERR (位 9): 精确的数据总线错误。BFAR 有效。IMPRECISERR (位 10): 不精确的数据总线错误。BFAR 无效。通常由写缓冲区或缓存引起,错误点与报告点有延迟。UNSTKERR (位 11): BusFault 在异常返回时出栈错误。STKERR (位 12): BusFault 在异常进入时压栈错误。LSPERR (位 13): BusFault 发生在浮点惰性状态保存期间。BFARVALID (位 15): BFAR 中的地址有效。UFSR(位):UNDEFINSTR (位 16): 执行了未定义指令。INVSTATE (位 17): 尝试进入无效状态(如执行 ARM 指令)。INVPC (位 18): 无效的 PC 加载(如尝试跳转到 LSB=0 的地址)。NOCP (位 19): 尝试执行协处理器指令。UNALIGNED (位 24): 发生了未对齐访问(需要 CCR.UNALIGN_TRP 位使能)。DIVBYZERO (位 25): 执行了除以零的操作(需要 CCR.DIV_0_TRP 位使能)。

分析 HFSR

VECTTBL (位 1): 读取向量表时发生总线错误(通常发生在异常处理启动阶段)。FORCED (位 30): 表明 HardFault 是由一个可配置的故障(MemManage, BusFault, UsageFault)升级而来的,因为其处理程序被禁用或在处理时发生新故障。此时应重点查看 CFSR。DEBUGEVT (位 31): 表明 HardFault 是由调试事件引起的(例如,在 Halting 调试模式下)。

分析 MMFAR 和 BFAR

如果 MMARVALID 或 BFARVALID 置位,这两个寄存器会告诉你导致内存或总线错误的确切地址。检查这个地址是否在你预期的内存范围内,是否需要特殊访问权限(如 MPU 设置),或者是否指向了一个无效的外设地址。

分析堆栈帧中的 PC 和 LR

stacked_regs.pc: 这是导致故障的指令的下一条指令的地址。在调试器的反汇编 (Disassembly) 窗口中跳转到 PC - 2 或 PC - 4(取决于故障指令是 16 位还是 32 位 Thumb 指令)附近,查看是哪条汇编指令触发了错误。stacked_regs.lr: 链路寄存器。如果是一般函数调用导致的 HardFault,LR 包含返回地址。如果 HardFault 发生在中断/异常处理程序内部,LR 会包含一个特殊的 EXC_RETURN 值(例如 0xFFFFFFF9, 0xFFFFFFFD 等),指示处理器状态和返回后使用的堆栈。这可以帮助判断 HardFault 是否发生在中断上下文中。


图片


4、步骤 4: 定位并修复源代码

根据反汇编窗口中定位到的指令地址,结合 .map 文件或调试器的符号信息,找到对应的 C 源代码行。

分析原因:

空指针/野指针:检查 MMFAR 或 BFAR 指向的地址,或者出错指令访问的指针变量是否为 NULL 或指向了无效/已释放的内存区域。数组越界:检查数组索引是否超出了边界,导致访问了非法内存。堆栈溢出: 如果 stacked_sp 的值非常接近或超出了定义的堆栈区域的边界,或者 PC 指向了堆栈区域,则很可能是堆栈溢出。检查函数调用深度、局部变量大小、中断嵌套。可以尝试增大堆栈空间 (startup_stm32xxxx.s 文件中定义)。未对齐访问:检查代码中是否有对 uint16_t, uint32_t 等多字节类型的指针进行强制类型转换和解引用,而该指针的地址不是 2 或 4 的倍数。例如:uint32_t* p = (uint32_t*)0x20000001; val = *p;。可以修改数据结构或使用 memcpy 来避免。除零错误:检查代码中是否存在除数为零的情况。MPU 配置错误:如果使用了 MPU,检查 MPU 区域的配置是否正确,是否允许了必要的读/写/执行权限。访问无效外设地址:检查 BFAR 是否指向了一个未启用时钟或不存在的外设寄存器地址。中断/RTOS 问题:如果 HardFault 发生在中断处理或 RTOS 任务切换期间,问题可能更复杂,可能涉及中断优先级配置错误、临界区保护不足、任务堆栈太小等。检查 LR 的 EXC_RETURN 值有助于判断上下文。

根据分析出的原因修改代码,重新编译、下载并运行代码,确保HardFault 不再发生。





关键词: Cortex-M     STM32     HardFault    

院士
2025-08-04 23:37:58     打赏
2楼

对于小型的MCU来说,hardfault也就这么几个原因。

但这个检查办法还是有必要的


助工
2025-08-04 11:13:09     打赏
3楼

我遇到过导致hardfault的原因:

1、数组越界/非法指针

2、缺中断函数


大家可以来总结总结


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]
血型b型rh阳性是什么意思 口什么舌什么 肉质瘤是什么东西 viagra是什么药 拯救银河系什么意思
荣耀是什么品牌 1980属什么 梦见空棺材是什么意思 看得什么 不劳而获是什么意思
3月12号是什么星座 什么水果消炎 检查贫血做什么检查 喝山楂水有什么功效与作用 茅台为什么这么贵
碱性磷酸酶是什么意思 尿白细胞3十什么意思 紧凑是什么意思 卡针是什么 皮蛋为什么能治口腔溃疡
青牛是什么牛hcv9jop2ns3r.cn eoa是什么意思hcv9jop8ns3r.cn her什么意思hcv9jop8ns3r.cn 什么是贫血hcv9jop2ns1r.cn 日仄念什么hcv9jop6ns3r.cn
pd是什么病hcv9jop4ns7r.cn 白带有点黄是什么原因hcv8jop0ns4r.cn 晦气是什么意思helloaicloud.com 牙合是什么字sanhestory.com 解除是什么意思hcv9jop0ns9r.cn
知了喜欢吃什么hcv8jop7ns1r.cn 步摇是什么hcv8jop4ns3r.cn 什么时候夏至hcv9jop6ns4r.cn 腹泻可以吃什么食物hcv8jop5ns1r.cn 小虾吃什么hcv8jop1ns9r.cn
农历10月22日是什么星座jinxinzhichuang.com 浮现是什么意思hcv8jop8ns5r.cn 肛瘘是什么病hcv9jop6ns3r.cn 医学影像技术是什么hcv8jop7ns5r.cn 什么食用油最好最健康1949doufunao.com
百度