网站首页 > 技术文章 正文
一、定位HardFault的核心方法
- 启用调试器捕获异常上下文
- 在Keil中启动调试模式,当程序触发HardFault时,调试器会自动暂停。通过查看Call Stack窗口和寄存器窗口(如LR、PC、SP),可获取异常发生时的程序状态。
- 关键寄存器分析:
- SCB->CFSR(可配置故障状态寄存器):判断故障类型(如内存访问错误、未对齐访问、指令执行错误)。
- SCB->HFSR(硬件故障状态寄存器):确认是否为HardFault的直接触发原因。
- SCB->MMFAR/SCB->BFAR:记录导致内存管理或总线故障的具体地址。
- 堆栈回溯分析
- 通过SP寄存器获取异常时的堆栈指针,手动解析堆栈中保存的返回地址(PC值)。在反汇编文件(.map或.lst)中查找对应的代码位置。
- 示例步骤:
- 在调试器中查看SP的值,找到堆栈中保存的PC(通常位于SP+24偏移处)。
- 使用fromelf工具生成反汇编文件(.axf转.lst),根据PC值定位出错的汇编指令及对应的C代码行。
- 自定义HardFault处理函数
- 在代码中重写HardFault_Handler函数,捕获异常信息并输出(如通过串口)。需在启动文件(如startup_stm32fxxx.s)中确保异常向量指向此函数。
- 示例代码片段:
void HardFault_Handler(void) {
volatile uint32_t *sp = (uint32_t*)__get_MSP(); // 获取堆栈指针
uint32_t pc = sp[6]; // 提取PC值
printf("HardFault at 0x%08X\n", pc);
while(1);
}
4.示例讲解
(1)HardFault_Handler出现的情况一般有两种:
一种是:数组越界.
一种是:堆栈溢出,程序指针指飞。
(2)制造一个HardFault故障;
void Test_UART(void)
{
uint8_t *pData;
*pData = 10;
printf("%d,\r\n", *pData);
}
(3)将上面函数Test_UART放在程序里面运行,将会出现以下情况:
(4)值得特别注意是,你要先判断将MSP(R14(LR) = 0xFFFFFFE9)或PSP(R14(LR) = 0xFFFFFFFD)的值作为SP值来使用。在Registers里面找到R14(LR)的值,我的这里是:0xFFFFFFFD
说明一下:
0xFFFFFFF9对应的是要看MSP寄存器
0xFFFFFFFD对应的是要看PSP寄存器
所以这里需要查找的内存地址是MSP的值:0x20005EA8
(5)在memory里面查找MSP的值:0x20005EA8,然后在对应的行里面找到地址,地址一般格式都是:0x080085EF这样的。
(6)在Disassembly里面右键选择Show Code at Address,把找到的地址输进去进行搜索,然后就会找到相对应的代码,这里的代码就是在进入循环中断之前的时候的情况,仔细查看这部分函数被调用或者数组内存使用情况。
不过你也可以简单这样操作:
在中断HardFault_Handler中的while()处打上断点,让程序执行到此处停止。
在keil中打开Call Stack + Locals,然后在HardFault_Handler上 右键选择:Show Caller Code,就会跳转到进入循环中断之前的函数处。仔细查看这部分函数被调用或者数组内存使用情况。
关注我,获取更多技术干货
猜你喜欢
- 2025-05-23 STM32学习笔记-CubeMX使用
- 2025-05-23 嵌入式开发丨51、STM32、Linux点灯的区别
- 2025-05-23 【基础】STM32F103C8T6制作舵机测试仪详细图文教程
- 2025-05-23 利用Proteus仿真STM32实现DHT11温湿度检测
- 2025-05-23 《GD32开发实战指南》第13章 DAC
- 2025-05-23 51-FORTH(1): 8051计算机诞生记
- 2025-05-23 _attribute__((weak))关键字如何使用?
- 2025-05-23 终极调试利器,各种Link通吃
- 2025-05-23 循环队列原理及在单片机串口通讯中的应用(二)
- 2025-05-23 超详细的FreeRTOS移植全教程——基于stm32
- 05-25菜籽饼窝料自制秘方!三步搞定野钓爆护神器,鲫鲤草鱼通杀
- 05-25将DeepSeek接入WPS,只要三步
- 05-25一文搞懂 VBA 循环结构,附超实用应用方案!
- 05-25Deepseek嵌入Excel,帮你自动做表格,感觉我要失业了
- 05-25怎么样获取剪贴板中格式的类型,VBA编程教你这样操作
- 05-25tdlex是什么文件
- 05-252分钟教你学会Word接入deepseek
- 05-25Word接入DeepSeek方法:第二版解决宏消失保存失败。
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)