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
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);
}
3、执行程序后,若发生内核错误,则程序会运行到最后的 while(1)处。此时观察相应的堆
栈和故障寄存器值, stacked_lr 即为故障发生时进入故障中断前 pc 的值,在 MDK 软件调试
状态下,假如 stacked_lr 的值为 0x1A002D08,在左下方的命令窗口输入“pc = 0x1A002D08”,
回车,即可定位发生错误的代码位置。
4、根据内核错误状态寄存器的值,对应下面的说明,也可以看出是发生了何种内核错误。
附录:Cortex-M3 内核错误寄存器说明