[MM32软件] MM查找HardFault方法和步骤

[复制链接]
4374|47
 楼主| 小夏天的大西瓜 发表于 2025-2-25 21:00 | 显示全部楼层 |阅读模式

实际环境中,由于测试高压等产品常常无法连接调试器,故需要代码来定位目标语句地址,并通过一定手段保存:

在MM32F0130中,需先修改启动文件startup_mm32f013x.s:
  1. HardFault_Handler\
  2.             PROC               
  3.             IMPORT  hard_fault_handler_c;函数声明
  4.             MOVS r0, #4                   ;判断主栈指针还是进程栈指针
  5.             MOV r1, LR
  6.             TST r0, r1
  7.             BEQ stacking_used_MSP        ;如果是主栈指针
  8.             MRS R0, PSP              ;否则是进程栈指针,把进程栈指针地址付给 R0
  9.             B get_LR_and_branch          ;跳转到 HardFault 中断程序
  10.             stacking_used_MSP
  11.             MRS R0, MSP                   ;把主栈指针地址赋给 R0
  12.             get_LR_and_branch
  13.             MOV R1, LR

  14.             BL hard_fault_handler_c
  15.             ENDP


  16. 该段代码会判断当前堆栈使用的是MSP或PSP,然后将堆栈参数传递给hard_fault_handler_c函数,该函数定义如下:

  17. void hard_fault_handler_c(unsigned int * hardfault_args, unsigned lr_value)
  18. {
  19.     unsigned int stacked_r0; //压栈的 r0
  20.     unsigned int stacked_r1; //压栈的 r1
  21.     unsigned int stacked_r2; //压栈的 r2
  22.     unsigned int stacked_r3; //压栈的 r3
  23.     unsigned int stacked_r12; //压栈的 r12
  24.     unsigned int stacked_lr; //压栈的 lr
  25.     unsigned int stacked_pc; //压栈的 pc
  26.     unsigned int stacked_psr; //压栈的 psr

  27.     stacked_r0 = ((unsigned int) hardfault_args[0]);
  28.     stacked_r1 = ((unsigned int) hardfault_args[1]);
  29.     stacked_r2 = ((unsigned int) hardfault_args[2]);
  30.     stacked_r3 = ((unsigned int) hardfault_args[3]);
  31.     stacked_r12 = ((unsigned int)hardfault_args[4]);
  32.     stacked_lr = ((unsigned int) hardfault_args[5]);
  33.     stacked_pc = ((unsigned int) hardfault_args[6]);
  34.     stacked_psr = ((unsigned int) hardfault_args[7]);

  35.     while(1)
  36.     {
  37.         printf("[Hard fault handler]\r\n");
  38.         printf("R0 = %x\r\n", stacked_r0);
  39.         printf("R1 = %x\r\n", stacked_r1);
  40.         printf("R2 = %x\r\n", stacked_r2);
  41.         printf("R3 = %x\r\n", stacked_r3);
  42.         printf("R12 = %x\r\n", stacked_r12);
  43.         printf("Stacked LR = %x\r\n", stacked_lr);
  44.         printf("Stacked PC = %x\r\n", stacked_pc);
  45.         printf("Stacked PSR = %x\r\n", stacked_psr);
  46.         printf("SCB_SHCSR=%x\r\n",SCB->SHCSR);
  47.         printf("Current LR = %x\r\n", lr_value);
  48.     }
  49. }


处理器进入到HardFault,将R0~R3、R12、LR、PC信息通过串口打印,根据寄存器信息排查问题代码。



当处理器处理异常时,除非异常是一个末尾连锁异常或迟来的异常,否则,处理器把信息都压入到当前堆栈中入栈(stacking),8个数据字的结构被称为栈帧(stack frame),栈按照双字地址对齐方式。

640.png
入栈后,堆栈指针立刻指向栈帧的最低地址单元。栈包含返回地址,这是被中止的程序中下条指令的地址。这个值在异常返回时返还给 PC,使被中止的程序恢复执行。



如下图连接仿真器查看汇编的地址可以找到是程序问题,根据PC指针地址,在程序生成的.map中查找出问题函数。

640 (1).png

星辰大海不退缩 发表于 2025-2-26 14:40 | 显示全部楼层
非常不错的故障排除法
等你下课 发表于 2025-3-31 13:18 | 显示全部楼层
在硬件故障发生时,程序会判断当前使用的是 主栈指针还是 进程栈指针
jf101 发表于 2025-3-31 23:04 | 显示全部楼层
查找HardFault方法和步骤
bartonalfred 发表于 2025-4-4 16:45 | 显示全部楼层
HardFault 常见的原因之一是非法的内存访问,如访问未分配的内存、越界访问数组等。检查代码中所有的内存访问操作,确保没有错误。
janewood 发表于 2025-4-4 17:50 | 显示全部楼层
通过调试串口输出调试信息,将程序的运行状态和错误信息实时发送到计算机。这样可以在不影响程序运行的情况下,获取更多的调试信息。
caigang13 发表于 2025-4-5 11:08 来自手机 | 显示全部楼层
报hardfualt错误,一般都是变量操作不当导致内存溢出。
chenjun89 发表于 2025-4-5 16:47 来自手机 | 显示全部楼层
可以在容易出现hardfualt的地方添加调试打印或日志记录。
sanfuzi 发表于 2025-4-5 19:21 | 显示全部楼层
尝试简化代码,逐步排除可能导致HardFault的部分,以缩小问题范围。
minzisc 发表于 2025-4-5 22:24 | 显示全部楼层
借助像 JTAG、SWD 这类调试接口,把调试工具(例如 J-Link、ST-Link)连接到单片机。这些工具能让你在调试时访问单片机的内部寄存器与内存。
burgessmaggie 发表于 2025-4-6 07:48 | 显示全部楼层
中断处理程序可能会影响系统的稳定性。检查中断处理程序的代码逻辑,确保没有死循环、错误的寄存器操作等。
快乐制造机 发表于 2025-4-7 21:00 | 显示全部楼层
在实际开发中,能够快速定位和处理HardFault是非常重要的
pmp 发表于 2025-4-8 12:30 | 显示全部楼层
根据 PC 和 LR 的值,找到导致 HardFault 的具体代码行。
如果是堆栈溢出,检查任务堆栈大小是否足够。
如果是非法访问,检查是否有未初始化的指针或数组越界。
phoenixwhite 发表于 2025-4-8 15:46 | 显示全部楼层
在可能引发 HardFault 的代码区域设置断点,例如函数调用、中断处理程序等。通过单步执行程序,查看程序执行到哪一步时触发了 HardFault。
bartonalfred 发表于 2025-4-9 19:15 | 显示全部楼层
如果是堆栈溢出,增加任务堆栈大小或全局堆栈大小。
在 FreeRTOS 中,可以使用 configMINIMAL_STACK_SIZE 调整默认堆栈大小。
robincotton 发表于 2025-4-9 22:19 | 显示全部楼层
HardFault可能由多种原因引起,包括指针操作错误、内存分配错误、数组越界等。因此,在查找问题时需要仔细检查代码。
backlugin 发表于 2025-4-10 01:20 | 显示全部楼层
访问未分配的内存区域              
weifeng90 发表于 2025-4-10 12:34 来自手机 | 显示全部楼层
可以在hardfualt函数中添加打印函数来打印相关信息,辅助定位分析原因
sdCAD 发表于 2025-4-10 14:14 | 显示全部楼层
HardFault 发生时,程序的上下文信息会被保存到堆栈中。可以查看堆栈中的内容,包括程序计数器(PC)、链接寄存器(LR)等,确定程序崩溃时的执行位置。
uytyu 发表于 2025-4-10 15:55 | 显示全部楼层
记录HardFault发生的情况、原因和解决方法,以便未来参考。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

273

主题

2390

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部