定位ARM Hard Fault 的方法
1,用Keil的话,可以做如下操作:
先将fault中断函数的内容改为:
【定位Fault方法】HardFault_Handler\
PROC
;
EXPORTHardFault_Handler[WEAK]
;
B.
IMPORT hard_fault_handler_c
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B hard_fault_handler_c
ENDP
然后在源程序里添加下面的函数代码:
// hard fault handler in C,
// with stack frame location as input parameter
void hard_fault_handler_c(unsigned int * hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
unsigned int stacked_psr;
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]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
printf ("[Hard fault handler]\n");
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 ("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))));
while(1)
{
;
;
}
}
如果使用调试器,则可以在第一个printf处设置断点.没有的话看串口打印结果
通过查看stacked_lr的内容可以知道程序运行到哪个位置出现fault
然后查看编译后汇编代码,可以知道源程序是哪个函数哪一步出现问题,
配合其它寄存器的内容来分析找出原因
2.用IAR的话,把startup_ewarm.c文件中的FaultISR()函数的内容改为:
volatile unsigned int stacked_r0;
volatile unsigned int stacked_r1;
volatile unsigned int stacked_r2;
volatile unsigned int stacked_r3;
volatile unsigned int stacked_r12;
volatile unsigned int stacked_lr;
volatile unsigned int stacked_pc;
volatile unsigned int stacked_psr;
//unsigned long cc;
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]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
printf ("[Hard fault handler]\n");
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 ("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))));
while(1)
{
;
;
}
如果使用调试器,则可以在第一个printf处设置断点.没有的话看串口打印结果
通过查看stacked_lr的内容可以知道程序运行到哪个位置出现fault
然后查看编译后汇编代码,可以知道源程序是哪个函数哪一步出现问题,
配合其它寄存器的内容来分析找出原因
另一种方法:
默认的HardFaudler 处理方法不是死循环么?将它改成BX LR直接返回的形式。然后再这条语句打个断点,一旦在断点中停下来,说明出错了,然后再返回,就可以返回到出错的位置的下一条语句哪里。
_asm void wait()
{
BX lr//BX无条件转移指令
}
void HardFault_Handler(void)
{
wait();
}
搜索更多相关主题的帖子: 定位