打印
[应用相关]

单片机硬错误排查方法

[复制链接]
440|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
HardFault 错误调试定位方法
1、首先更改 startup.s 的启动文件,把里面的 HardFault_Handler 代码段换成下
面的代码:
HardFault_Handler\
PROC
IMPORT hard_fault_handler_c
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B hard_fault_handler_c
ENDP



使用特权

评论回复
沙发
paotangsan|  楼主 | 2021-6-3 16:08 | 只看该作者
2、然后把 hard_fault_handler_c 函数放在 c 文件的代码中。代码如下:
void hard_fault_handler_c(unsigned int * hardfault_args)
{
        static unsigned int stacked_r0;
        static unsigned int stacked_r1;
        static unsigned int stacked_r2;
        static unsigned int stacked_r3;
        static unsigned int stacked_r12;
        static unsigned int stacked_lr;
        static unsigned int stacked_pc;
        static unsigned int stacked_psr;
        static unsigned int SHCSR;
        static unsigned char MFSR;
        static unsigned char BFSR;
        static unsigned short int UFSR;
        static unsigned int HFSR;
        static unsigned int DFSR;
        static unsigned int MMAR;
        static unsigned int BFAR;
        stacked_r0 = ((unsigned long) hardfault_args[0]);
        stacked_r1 = ((unsigned long) hardfault_args[1]);
        stacked_r2 = ((unsigned long) hardfault_args[2]);
        stacked_r3 = ((unsigned long) hardfault_args[3]);
        stacked_r12 = ((unsigned long) hardfault_args[4]);
        /*异常中断发生时,这个异常模式特定的物理 R14,即 lr 被设置成该异常模式将要返回的
        地址*/
        stacked_lr = ((unsigned long) hardfault_args[5]);
        stacked_pc = ((unsigned long) hardfault_args[6]);
        stacked_psr = ((unsigned long) hardfault_args[7]);
        SHCSR = (*((volatile unsigned long *)(0xE000ED24))); //系统 Handler 控制及状态寄存器
        MFSR = (*((volatile unsigned char *)(0xE000ED28))); //存储器管理 fault 状态寄存器
        BFSR = (*((volatile unsigned char *)(0xE000ED29))); //总线 fault 状态寄存器
        UFSR = (*((volatile unsigned short int *)(0xE000ED2A)));//用法 fault 状态寄存器
        HFSR = (*((volatile unsigned long *)(0xE000ED2C))); //硬 fault 状态寄存器
        DFSR = (*((volatile unsigned long *)(0xE000ED30))); //调试 fault 状态寄存器
        MMAR = (*((volatile unsigned long *)(0xE000ED34))); //存储管理地址寄存器
        BFAR = (*((volatile unsigned long *)(0xE000ED38))); //总线 fault 地址寄存器
        printf("r0: %X\n",stacked_r0);
        printf("r1: %X\n",stacked_r1);
        printf("r2: %X\n",stacked_r2);
        printf("r3: %X\n",stacked_r3);
        printf("r12: %X\n",stacked_r12);
        printf("lr: %X\n",stacked_lr);
        printf("pc: %X\n",stacked_pc);
        printf("psr: %X\n",stacked_psr);
        printf("SHCSR: %X\n",SHCSR);
        printf("MFSR: %X\n",MFSR);
        printf("DFSR: %X\n",DFSR);
        printf("MMAR: %X\n",MMAR);
        printf("BFAR: %X\n",BFAR);
        printf("UFSR: %X\n",UFSR);
        printf("HFSR: %X\n",HFSR);
        printf("BFSR: %X\n",BFSR);
        while (1);
}


使用特权

评论回复
板凳
paotangsan|  楼主 | 2021-6-3 16:08 | 只看该作者
3、执行程序后,若发生内核错误,则程序会运行到最后的 while(1)处。此时观察相应的堆
栈和故障寄存器值, stacked_lr 即为故障发生时进入故障中断前 pc 的值,在 MDK 软件调试
状态下,假如 stacked_lr 的值为 0x1A002D08,在左下方的命令窗口输入“pc = 0x1A002D08”,
回车,即可定位发生错误的代码位置。


使用特权

评论回复
地板
paotangsan|  楼主 | 2021-6-3 16:08 | 只看该作者

4、根据内核错误状态寄存器的值,对应下面的说明,也可以看出是发生了何种内核错误。
附录:Cortex-M3 内核错误寄存器说明






使用特权

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

本版积分规则

51

主题

3939

帖子

0

粉丝