定位引起hardfault错误的代码

定位引起hardfault错误的故障代码

准备

  • stm32f103开发板
  • keil软件

基础知识

两个堆栈指针

Cortex-M3 拥有两个堆栈指针,然而它们是 banked,因此任一时刻只能使用其中的一个。

  • 主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包括中断服务例程)
  • 进程堆栈指针(PSP):由用户的应用程序代码使用。

入栈

响应异常的第一个行动,就是自动保存现场的必要部分:依次把xPSR, PC, LR, R12以及R3-R0由硬件自动压入适当的堆栈中:如果当响应异常时,当前的代码正在使用PSP,则压入PSP,也就是使用进程堆栈;否则就压入MSP,使用主堆栈。一旦进入了服务例程,就将一直使用主堆栈。

异常返回值

在进入异常服务程序后,将自动更新LR的值为特殊的EXC_RETURN。这是一个高28位全为1的值,只有[3:0]的值有特殊含义

在这里插入图片描述

在这里插入图片描述

具体错误举例

精确的总线错误

在正常运行的代码中添加如下代码,示例中使用的是跑freertos的代码。我们定义一个指针,不赋值,

### HardFault 异常中 Forced 类型的原因及解决方法 HardFault 异常是 ARM Cortex-M 系列微控制器中一种严重的错误中断,表明系统遇到了无法由其他异常处理机制解决的问题。在 HardFault 的触发原因中,Forced 类型的错误是一种特定情况,通常与堆栈溢出、非法内存访问或未对齐的数据访问相关[^1]。 #### Forced 类型的具体原因 1. **堆栈溢出** 当程序使用了过多的堆栈空间(例如递归调用过深或局部变量过大),可能导致 MSP 或 PSP 超出其分配范围,从而触发 HardFault 异常。这种情况属于 Forced 类型的错误[^3]。 2. **非法内存访问** 如果程序尝试访问未映射的内存地址或执行禁止的操作(如向只读存储器写入数据),也可能引发 Forced 类型的 HardFault 异常[^1]。 3. **未对齐的数据访问** 在某些 Cortex-M 内核中,如果数据访问未对齐(例如从非 4 字节对齐地址读取 32 位数据),也会导致 Forced 类型的 HardFault 异常[^4]。 #### 解决方法 以下是针对 Forced 类型 HardFault 的具体解决方法: 1. **检查堆栈大小配置** 确保为线程或任务分配了足够的堆栈空间。可以通过调整链接脚本中的堆栈大小或使用调试工具查看实际堆栈使用情况来避免堆栈溢出。 示例代码:调整堆栈大小配置 ```c /* 链接脚本中设置堆栈大小 */ _estack = 0x20008000; /* 栈顶地址 */ _min_stack_size = 0x400; /* 最小堆栈大小设置为 1KB */ ``` 2. **验证内存访问合法性** 使用调试工具检查程序是否尝试访问非法地址。可以在进入 HardFault 处理函数时,读取寄存器值以定位问题代码。例如,通过读取 LR(链接寄存器)和 PC(程序计数器)来确定错误发生的位置[^2]。 示例代码HardFault 处理函数中读取寄存器值 ```c void HardFault_Handler(void) { uint32_t stacked_r0; __asm volatile( "mov %0, r0\n" : "=r"(stacked_r0) ); // 打印或记录 stacked_r0 的值以分析问题 while (1) {} } ``` 3. **确保数据对齐** 如果硬件不支持未对齐访问,应确保所有数据访问都符合对齐要求。可以通过编译器选项或代码优化实现这一点。例如,在 GCC 中启用 `-mno-unaligned-access` 编译选项可以强制生成对齐访问代码[^4]。 4. **增加调试信息** 在 HardFault 处理函数中添加更多调试信息,帮助快速定位问题。例如,打印堆栈指针和返回地址以便进一步分析[^2]。 示例代码:打印调试信息 ```c void HardFault_Handler(void) { uint32_t stacked_r0, stacked_r1, stacked_r2, stacked_r3; uint32_t stacked_r12, stacked_lr, stacked_pc, stacked_psr; __asm volatile( "mov %0, r0\n" "mov %1, r1\n" "mov %2, r2\n" "mov %3, r3\n" "mov %4, r12\n" "mov %5, lr\n" "mov %6, pc\n" "mrs %7, psr\n" : "=r"(stacked_r0), "=r"(stacked_r1), "=r"(stacked_r2), "=r"(stacked_r3), "=r"(stacked_r12), "=r"(stacked_lr), "=r"(stacked_pc), "=r"(stacked_psr) ); // 打印或记录这些值以分析问题 while (1) {} } ``` #### 总结 Forced 类型的 HardFault 错误通常由堆栈溢出、非法内存访问或未对齐数据访问引起。通过合理配置堆栈大小、验证内存访问合法性以及确保数据对齐,可以有效避免此类问题。此外,利用调试工具和 HardFault 处理函数中的寄存器信息,能够快速定位并解决问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值