打印
[技术问答]

HardFault异常分析

[复制链接]
2380|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 AutochipsMCU 于 2019-9-2 21:21 编辑

有客户经常咨询程序跑飞怎么分析。下面整理一下方法,抛砖引玉,大家一起分享讨论

在系统开发的时候,有可能会遇到出现HardFault_Handler硬件异常(死机)。对于功能稍微复杂一些的系统(或带OS),逐一检查程序跑飞原因会很麻烦,如果是低概率则更麻烦。好在掌握一些技巧后,能让如此棘手的问题变得容易一些。
出现HardFalut主要有两方面的原因:
1、内存溢出或者访问越界。
2、堆栈溢出。


关于HardFalut的分析,segger官方和keil官方都有提供hardFault相关的文档和代码
AN00016_AnalyzingHardFaultsOnCortexM.pdf (103.64 KB)
apnt209.pdf (1.13 MB)
对于低概率问题,若支持打log,建议做法:出现hardFalut后把出现异常时的现场通过log打印出来。结合MAP文件来进行分析定位问题。
startup_ac78xx.s关于HardFalut_Handler修改如下:
HardFault_Handler\
                PROC
                IMPORT  HardFaultDebug
                ;LDR R1, =0xE000ED0C
                ;LDR R0, =0x05FA0004
                ;STR R0, [R1]   ; RESET
                TST LR,#4
                ITE EQ
                MRSEQ R0,MSP
                MRSNE R0,PSP
                B HardFaultDebug
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP


HardFaultDebug实现如下:
void HardFaultDebug(const unsigned int * stackInfo)
{
    unsigned int stackR0;
    unsigned int stackR1;
    unsigned int stackR2;
    unsigned int stackR3;
    unsigned int stackR12;
    unsigned int stackLR;
    unsigned int stackPC;
    unsigned int stackPSR;

    stackR0 = ((unsigned long) stackInfo[0]);
    stackR1 = ((unsigned long) stackInfo[1]);
    stackR2 = ((unsigned long) stackInfo[2]);
    stackR3 = ((unsigned long) stackInfo[3]);
    stackR12 = ((unsigned long) stackInfo[4]);
    stackLR = ((unsigned long) stackInfo[5]);
    stackPC = ((unsigned long) stackInfo[6]);
    stackPSR = ((unsigned long) stackInfo[7]);

    printf("R0=%x\n", stackR0);
    printf("R1=%x\n", stackR1);
    printf("R2=%x\n", stackR2);
    printf("R3=%x\n", stackR3);
    printf("R12=%x\n", stackR12);
    printf("LR[R14]=%x subroutine call return address\n", stackLR);
    printf("PC[R15]=%x program counter\n", stackPC);
    printf("PSR=%x\n", stackPSR);

    printf("BFAR=%x\n", (*((volatile unsigned long *)(0xE000ED38))));
    printf("CFSR=%x\n", (*((volatile unsigned long *)(0xE000ED28))));
    printf("HFSR=%x\n", (*((volatile unsigned long *)(0xE000ED2C))));
    printf("DFSR=%x\n", (*((volatile unsigned long *)(0xE000ED30))));
    printf("AFSR=%x\n", (*((volatile unsigned long *)(0xE000ED3C))));

    printf("SCB_SHCSR=%x\n", SCB->SHCSR);

    while(1);
}

可基于PC地址参考该软件对于的map文件找到案发时附件位置。然后定位问题。



使用特权

评论回复

相关帖子

沙发
a20084666| | 2019-8-30 11:20 | 只看该作者
怎么不回答我问题了,无刷无感启动波形

使用特权

评论回复
板凳
AutochipsMCU|  楼主 | 2019-8-30 13:01 | 只看该作者
a20084666 发表于 2019-8-30 11:20
怎么不回答我问题了,无刷无感启动波形

不好意思,没有留意到您有回复

使用特权

评论回复
地板
a20084666| | 2019-8-30 13:40 | 只看该作者
AutochipsMCU 发表于 2019-8-30 13:01
不好意思,没有留意到您有回复

没事的,怎么称呼

使用特权

评论回复
5
XIVN1987| | 2019-9-2 15:57 | 只看该作者


你这个只能定位到发生HardFault的点,,但如果这个函数被多个函数调用,,你不知道它是被哪个函数调用时触发的HardFault,,

给你推荐个工具,,不需要在单片机上添加代码,,发生HardFault后用此工具读取芯片寄存器和RAM内容,,自动分析HardFault点和到达这一点的调用路径:

源码和exe:https://github.com/XIVN1987/JHFView


使用特权

评论回复
6
JasonLee27| | 2019-9-2 17:09 | 只看该作者
XIVN1987 发表于 2019-9-2 15:57
你这个只能定位到发生HardFault的点,,但如果这个函数被多个函数调用,,你不知道它是被哪个函数调用时 ...

好东西吖

使用特权

评论回复
7
AutochipsMCU|  楼主 | 2019-9-2 17:48 | 只看该作者
XIVN1987 发表于 2019-9-2 15:57
你这个只能定位到发生HardFault的点,,但如果这个函数被多个函数调用,,你不知道它是被哪个函数调用时 ...

谢谢分享

使用特权

评论回复
8
zlmin| | 2019-10-3 10:26 | 只看该作者
谢谢分享!

使用特权

评论回复
9
戊戌变法| | 2019-10-4 16:56 | 只看该作者
好像发现了新大陆

使用特权

评论回复
10
AutochipsMCU|  楼主 | 2019-10-8 18:07 | 只看该作者

使用特权

评论回复
11
black_code| | 2019-12-27 11:12 | 只看该作者
谢谢分享

使用特权

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

本版积分规则

认证:合肥杰发科技有限公司
简介:四维图新全资子公司 全球多地布局;专注于汽车电子芯片及相关系统的研发与设计 车规级芯片覆盖整车;客户遍及海内外 全球超过8000万辆车搭载杰发科技芯片。

59

主题

268

帖子

11

粉丝