打印
[MM32软件]

MM查找HardFault方法和步骤

[复制链接]
1138|34
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层

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

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

            BL hard_fault_handler_c
            ENDP


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

void hard_fault_handler_c(unsigned int * hardfault_args, unsigned lr_value)
{
    unsigned int stacked_r0; //压栈的 r0
    unsigned int stacked_r1; //压栈的 r1
    unsigned int stacked_r2; //压栈的 r2
    unsigned int stacked_r3; //压栈的 r3
    unsigned int stacked_r12; //压栈的 r12
    unsigned int stacked_lr; //压栈的 lr
    unsigned int stacked_pc; //压栈的 pc
    unsigned int stacked_psr; //压栈的 psr

    stacked_r0 = ((unsigned int) hardfault_args[0]);
    stacked_r1 = ((unsigned int) hardfault_args[1]);
    stacked_r2 = ((unsigned int) hardfault_args[2]);
    stacked_r3 = ((unsigned int) hardfault_args[3]);
    stacked_r12 = ((unsigned int)hardfault_args[4]);
    stacked_lr = ((unsigned int) hardfault_args[5]);
    stacked_pc = ((unsigned int) hardfault_args[6]);
    stacked_psr = ((unsigned int) hardfault_args[7]);

    while(1)
    {
        printf("[Hard fault handler]\r\n");
        printf("R0 = %x\r\n", stacked_r0);
        printf("R1 = %x\r\n", stacked_r1);
        printf("R2 = %x\r\n", stacked_r2);
        printf("R3 = %x\r\n", stacked_r3);
        printf("R12 = %x\r\n", stacked_r12);
        printf("Stacked LR = %x\r\n", stacked_lr);
        printf("Stacked PC = %x\r\n", stacked_pc);
        printf("Stacked PSR = %x\r\n", stacked_psr);
        printf("SCB_SHCSR=%x\r\n",SCB->SHCSR);
        printf("Current LR = %x\r\n", lr_value);
    }
}


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



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


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



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



使用特权

评论回复
34
robincotton| | 2025-4-14 16:27 | 只看该作者
问题类型        可能原因        解决方案
数组越界        访问数组时索引超出范围。        检查数组边界,避免越界访问。
堆栈溢出        局部变量过多或递归过深。        增大堆栈大小,优化递归逻辑。
非法内存访问        访问未分配或受保护的内存区域。        检查指针初始化和内存分配逻辑。
总线错误        外设通信故障或存储器访问错误。        检查外设驱动和存储器映射配置。
未定义指令        执行了非法或未实现的指令。        检查编译器设置和代码逻辑,确保指令集兼容。

使用特权

评论回复
33
updownq| | 2025-4-14 14:37 | 只看该作者
查找单片机HardFault的方法和步骤涉及查看寄存器、设置断点和单步执行、查看调用栈以及程序查找等多个方面。

使用特权

评论回复
32
nomomy| | 2025-4-14 12:49 | 只看该作者
HardFault是ARM Cortex-M系列处理器中优先级最高的系统异常。它可能由以下情况之一触发:

存储器访问错误
总线错误
执行非法指令
未处理的异常

使用特权

评论回复
31
jimmhu| | 2025-4-14 11:00 | 只看该作者
使用未赋值的指针导致野指针访问。

使用特权

评论回复
30
janewood| | 2025-4-14 08:09 | 只看该作者
初始化所有指针变量,避免使用未初始化的指针。
使用静态分析工具(如 MISRA-C 检查工具)检测潜在的非法访问。

使用特权

评论回复
29
albertaabbot| | 2025-4-13 19:53 | 只看该作者
在代码中添加日志输出语句,记录程序的执行流程和关键变量的值。当 HardFault 发生时,可以根据日志信息了解程序的运行状态,帮助定位问题。

使用特权

评论回复
28
benjaminka| | 2025-4-13 16:10 | 只看该作者
若 PC 指向 Flash 中的未初始化代码段,可能是代码区损坏。
若 PC 指向 RAM 中的非法地址,可能是堆栈溢出或野指针。

使用特权

评论回复
27
biechedan| | 2025-4-13 14:28 | 只看该作者
递归调用过深或局部变量占用过多栈空间。

使用特权

评论回复
26
ulystronglll| | 2025-4-13 12:36 | 只看该作者
运行程序直到 HardFault 发生,调试器会自动停在异常处理入口。

使用特权

评论回复
25
sdlls| | 2025-4-13 10:39 | 只看该作者
根据异常堆栈回溯,开发者可以定位到产生问题的具体代码位置。如果是因为非法指令导致的HardFault,那么可能是编译器的问题,或者是使用了不支持的指令集。如果是内存访问错误,应检查指针操作的合法性以及指针是否被正确初始化。

使用特权

评论回复
24
jackcat| | 2025-4-12 22:23 | 只看该作者
dFault 发生时,程序会跳转到 HardFault 异常处理函数。可以查看异常向量表,确认 HardFault 异常处理函数的入口地址,然后在代码中定位该函数。

使用特权

评论回复
23
lihuami| | 2025-4-12 20:30 | 只看该作者
可能存在问题,导致无法正确处理某些异常。确保使用最新版本的固件可以解决一些问题。

使用特权

评论回复
22
everyrobin| | 2025-4-10 21:39 | 只看该作者
当 HardFault 发生时,调试器会自动停在故障处理函数(通常是 HardFault_Handler)处。

使用特权

评论回复
21
hudi008| | 2025-4-10 19:57 | 只看该作者
确保电源稳定,避免因电压波动引发异常。

使用特权

评论回复
20
usysm| | 2025-4-10 17:55 | 只看该作者
如果无法确定 HardFault 的原因,可以逐步简化代码,只保留必要的功能。然后重新运行程序,观察 HardFault 是否仍然发生。通过这种方式,可以缩小问题的范围,找到引发 HardFault 的代码段。

使用特权

评论回复
19
uytyu| | 2025-4-10 15:55 | 只看该作者
记录HardFault发生的情况、原因和解决方法,以便未来参考。

使用特权

评论回复
18
sdCAD| | 2025-4-10 14:14 | 只看该作者
HardFault 发生时,程序的上下文信息会被保存到堆栈中。可以查看堆栈中的内容,包括程序计数器(PC)、链接寄存器(LR)等,确定程序崩溃时的执行位置。

使用特权

评论回复
17
weifeng90| | 2025-4-10 12:34 | 只看该作者
可以在hardfualt函数中添加打印函数来打印相关信息,辅助定位分析原因

使用特权

评论回复
16
backlugin| | 2025-4-10 01:20 | 只看该作者
访问未分配的内存区域              

使用特权

评论回复
15
robincotton| | 2025-4-9 22:19 | 只看该作者
HardFault可能由多种原因引起,包括指针操作错误、内存分配错误、数组越界等。因此,在查找问题时需要仔细检查代码。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

241

主题

2047

帖子

2

粉丝