1998年五行属什么| 合财是什么意思| 肚子大了是什么原因造成的| 梦到头上长虱子什么意思| 什么的海风| 空调为什么不制冷| 腹泻拉水是什么原因| 神经病吃什么药效果好| 大黄蜂是什么车| 油粘米是什么米| 什么是月经不调| 尹是什么意思| 卧室放什么驱虫最好| 牛肚是牛的什么部位| 右侧卵巢内囊性结构什么意思| 挫败感是什么意思| 贫血打什么针效果最好| 圈癣是什么引起的| 血糖是什么| 绿心黑豆有什么功效| 紫癜有什么危害| 闰六月要给父母买什么| 蝙蝠是什么变的| 月经量少要吃什么调理| 日是什么意思| 夜尿频多吃什么药效果好| 美国fda认证是什么| 9月是什么星座| 火彩是什么| 洲际导弹是什么意思| 夏天水肿的原因是什么| 脸上长疣是什么原因| 尿频尿急尿不尽吃什么药| 人为什么会有胎记| 孕妇梦到蛇是什么意思| 涤是什么面料| 凌空什么什么| 家是什么| a醇对皮肤有什么作用| black什么颜色| 定量是什么意思| 贞洁是什么意思| spa什么服务| 阴茎不硬是什么原因| 抗衰老吃什么| 丝鸟读什么| NF什么意思| 疝气是什么症状| 一月七号是什么星座| 金银花有什么作用| 三体讲的是什么| 冠带什么意思| 人流需要准备什么东西| 周公解梦掉牙齿意味着什么| 什么床垫最健康| 25岁今年属什么生肖| 6月24号什么星座| 艮是什么意思| 肾虚用什么补最好| 耳朵发烧是什么原因| 独显是什么意思| 长期拉肚子是怎么回事什么原因造成| 家里适合养什么鱼| 产后拉肚子是什么原因引起的| 最近有什么新闻| 淋球菌是什么| 大便呈绿色是什么原因| 一年半载是什么意思| 下巴痘痘反复长是什么原因| 脂肪酶是什么意思| 母是什么结构| 处女膜破了有什么影响| 排骨是什么肉| 什么是近视| 吃卡培他滨禁止吃什么| 扶苏姓什么| 打嗝是什么引起的| 冰镇情人果是什么水果| 岬是什么意思| 天公作美是什么生肖| 贫血吃什么补血| 什么是童话故事| 血儿茶酚胺是查什么的| 海米是什么| 狗癣用什么药最有效| 狐狸和乌鸦告诉我们什么道理| 夏天适合种什么水果| 做梦买房子是什么预兆| 孟力念什么| 2月26日什么星座| 富丽堂皇是什么意思| 凤梨跟菠萝有什么区别| 南京立秋吃什么| 血糖高吃什么食物最好最佳| 92什么意思| 蚂蚁为什么会咬人| 中药为什么要熬两次| 晚上睡不着白天睡不醒是什么原因| 青石是什么石头| 脸上有癣用什么药膏好| 心慌是什么原因引起的| 什么洗面奶最好用排行第一| 幽门螺杆菌阴性是什么意思| 男性性功能减退吃什么药| 太平鸟属于什么档次| 如意代表什么生肖| 梦见办丧事是什么兆头| cm代表什么单位| 什么是abo文| 大心脏是什么意思| 古代质子是什么意思| 一阴一阳是什么生肖| 胃酸是什么酸| 批发零售属于什么行业| 什么气组词| 痴女是什么意思| 小孩不说话什么原因| 查电话号码打什么电话| 相得益彰是什么意思| 传染病检查项目有什么| 血压低吃什么中成药| 小宝贝是什么意思| 塑料袋属于什么垃圾| 吃什么补肾最快最有效| 群星是什么意思| 地瓜是什么| nlp是什么| 6s是什么| 蓝莓有什么营养价值| 八方来财是什么生肖| 人间仙境是什么意思| 钝角是什么意思| 霉菌性阴道炎吃什么消炎药| 婚前体检都检查什么| 毛戈平属于什么档次| 海藻是什么| 摆地摊卖什么最赚钱而且很受欢迎| 诸多是什么意思| 异卵双胞胎什么意思| 关羽的刀叫什么名字| 结婚登记需要什么材料| 早晨起来口干舌燥是什么原因| 殇字是什么意思| 里正是什么官| 目赤是什么症状| 血小板高是什么原因| 103是什么意思| 虚劳病是什么意思| 新生儿吐奶什么原因| copd是什么病的简称| 肾结石术后吃什么食物最好| 属马女和什么属相最配| 59岁生日有什么讲究| 芒果和什么不能一起吃| 人流挂什么科| 什么时候说什么话| 孕期感冒可以吃什么药| 唇周围长痘痘是什么原因| 天下无双是什么生肖| 黄芪什么季节喝最好| hpv病毒是什么病毒| 251是什么意思| 肾功能不全吃什么药| 绿茶属于什么茶| gv是什么意思| 山竹有什么功效和作用| 梦见梅花鹿是什么预兆| 吃巧克力有什么好处| 定投是什么意思| 条形码的数字代表什么| 预估是什么意思| ddg是什么意思| 朝霞不出门晚霞行千里是什么意思| 龟皮痒用什么药膏| 丁羟甲苯是什么| 手术前吃什么补充营养| 焦虑症吃什么中药| mm什么意思| 粉红色泡沫样痰是什么病| 吃飞醋是什么意思| 3月5号是什么星座| 口疮是什么原因引起的| 女生适合喝什么茶| 小孩感冒吃什么饭菜比较好| 腿水肿是什么原因引起的| 蛇信子是什么| 日单是什么意思| 大姨妈有黑色血块是什么原因| 两小儿辩日告诉我们什么道理| 乳腺癌长在什么位置| 双子座是什么星象| 化验肝功挂什么科| 桑拓木命是什么意思| 脚底出汗是什么原因| 江小白是什么酒| 1990年1月属什么生肖| 仓鼠可以吃什么| 做亲子鉴定需要什么材料| 狗吐黄水吃什么药| 34周为什么不建议保胎| 胃窦糜烂是什么意思| 老而弥坚是什么意思| 二月花是什么花| 梁下放床有什么禁忌| 冬虫夏草有什么功效与作用| 错构瘤是什么| 玄女是什么意思| 尿里有结晶是什么原因| 66年出生属什么生肖| 闻字五行属什么| 6月初三是什么日子| 清宫后可以吃什么水果| 范思哲是什么品牌| 纵欲是什么意思| 御字五行属什么| 朱元璋什么星座| 梦见被蛇咬是什么意思| 肉质瘤是什么东西| 什么样的男人值得托付终身| 苏打水配什么好喝| 桑叶泡水喝有什么功效和作用| 1949年是什么年| 为什么会得高血压| 手足口病涂抹什么药膏| 掷是什么意思| 风雨交加是什么生肖| 什么原因会导致尿路感染| 防水逆什么意思| 喝鲜羊奶有什么好处和坏处| 人血馒头是什么意思| 三十如狼四十如虎什么意思| 什么是白肉| 瘦脱相是什么意思| 枯木逢春是什么生肖| 大拇指指甲凹凸不平是什么原因| 不谷是什么意思| 备孕要注意些什么| 氢氧化钠是什么| 甲状腺弥漫性改变是什么意思| cd ts 什么意思| 尿酸高多吃什么食物好| 36是什么码| 龟头敏感吃什么药| 甲床是什么| 人巨细胞病毒是什么病| 腔隙性脑梗死吃什么药| 意犹未尽什么意思| 时机是什么意思| 双侧肾盂分离是什么意思| 1958年是什么年| 嘴唇发黑是什么原因| 孕初期有什么症状| 囊性结构是什么意思| 酉鬼念什么| 白醋加盐洗脸有什么好处| 为什么不能摸猫的肚子| 可乐不能和什么一起吃| 血红蛋白低是什么原因| 检查血脂挂什么科| 景泰蓝是什么地方的特种工艺| 血糖高喝什么好| 什么床不能睡觉| 农历7月28日是什么星座| 什么是高| 百度
这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 ? 论坛首页 ? 嵌入式开发 ? 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 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]
双肺索条灶是什么意思 宋朝后面是什么朝代 梦遗是啥意思是什么 一九三五年属什么生肖 子不教父之过是什么意思
男性阴虱用什么药最好 柏拉图式是什么意思 什么叫快闪 双肺散在纤维灶是什么意思 前庭神经炎挂什么科
坐月子可以吃什么水果 考试穿什么颜色最吉利 丿是什么字 寂寞的近义词是什么 什么是危险期
骨折恢复吃什么好 冠心病做什么检查 折叠胆囊是什么意思 前列腺吃什么食物调理 三七长什么样子图片
日安什么意思hcv8jop1ns0r.cn 肠梗阻是什么病hcv9jop6ns6r.cn 今天生猪什么价hcv8jop1ns0r.cn 流水生财是什么意思bjcbxg.com 国资委主任是什么级别hcv9jop0ns2r.cn
地中海贫血有什么症状wuhaiwuya.com 吃什么解毒最快hcv8jop6ns7r.cn 了口是什么字hcv8jop7ns9r.cn 阴道有腥味是什么原因hcv9jop5ns3r.cn kappa属于什么档次hcv9jop6ns7r.cn
子宫内膜异位症吃什么药hcv8jop8ns5r.cn 农历七月初七是什么节日bjhyzcsm.com 94属什么生肖hcv7jop9ns4r.cn 开荤什么意思hcv9jop1ns4r.cn 小儿流清鼻涕吃什么药效果好jasonfriends.com
捉虫是什么意思hcv9jop1ns6r.cn 膳是什么意思aiwuzhiyu.com 中暑是什么症状表现hcv8jop2ns8r.cn 喝什么能变白hcv9jop3ns7r.cn 紫笋茶属于什么茶hcv8jop1ns8r.cn
百度