stm32 出现 hard fault 的排查记录

参考链接:https://blog.csdn.net/qq_43118572/article/details/132759626

1、先验知识

先验知识1: cortex m3 在中断/异常时,会把 8 个寄存器(xPSR、PC、LR、R12 以及R3-R0)的值压入栈。入栈顺序以及入栈后堆栈中的内容如下(CM4 是从低地址到搞地质):

地址 寄存器 被保存的顺序
旧 ISP(N-0) 原先已压入栈的内容 -
(N-4) xPSR 2
(N-8) PC 1
(N-12) LR 8
(N-16) R12 7
(N-20) R3 6
(N-24) R2 5
(N-28) R1 4
新 SP(N-32) R0 3

先验知识2: 在 Keil 项目的 Options for Target 'Target 1' 的Target 选项,将 Floating Port Hardware 选项设置为 Not Use,这样的好处是在后续查看堆栈寄存器信息时,不会看到其他浮点寄存器,好根据地址推断存储的是哪个寄存器的值。
> 参考链接:https://blog.csdn.net/qq_20553613/article/details/80118444

在这里插入图片描述

先验知识3: map 文件可以查看符号表(Symbol Table)。符号表可用于确定变量或函数在内存中的位置。

2、正文

由于 arm/cortex 仅支持对齐访问,否则会出现 hard fault。我们以下述访问不对齐的代码为例,产生 Hard Fault 并进行逐一排查:(假设我们不知道是哪里出现 hard fault)

int main(void)
{
  int a = 1;
  int b = 1;
  int c = a + b;
  int *p = (int *)0xF000 0000;
  int d = *p;
  while (*p) {  // line 11
    (*p)++;  // 将在此处陷入 Hard Fault  line12
  }
  return 0;
}

Step 1:查看 map 我们可以发现栈顶位置为 0x2000 0660

Step 2:当程序陷入异常时,我们能发现当前使用的是 MSP,SP 对应的地址为 0x2000 0640,所以压入了 32/4 = 8 个寄存器(一个寄存器 32 位,即 4 个字节)。根据物理地址,发现上次压入的 PC 值为 0x0800 0336。换而言之,陷入异常的上一条指令地址为 0x0800 0336

Step 3:点击导航栏的 “Disasembly Window”,打开反汇编界面。右键并选择 “Disassembly at Address” 选项,输入 0x0800 0336 并输入 “go to”,就会跳转到该条指令。

备注: Call Stack 跟 Memory 窗口可以查看很多信息

在这里插入图片描述

posted @   MasterBean  阅读(323)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示