本帖最后由 AutochipsMCU 于 2019-9-2 21:21 编辑
有客户经常咨询程序跑飞怎么分析。下面整理一下方法,抛砖引玉,大家一起分享讨论 。
在系统开发的时候,有可能会遇到出现HardFault_Handler硬件异常(死机)。对于功能稍微复杂一些的系统(或带OS),逐一检查程序跑飞原因会很麻烦,如果是低概率则更麻烦。好在掌握一些技巧后,能让如此棘手的问题变得容易一些。
出现HardFalut主要有两方面的原因:
1、内存溢出或者访问越界。
2、堆栈溢出。
关于HardFalut的分析,segger官方和keil官方都有提供hardFault相关的文档和代码
对于低概率问题,若支持打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文件找到案发时附件位置。然后定位问题。
|