转载:定位ARM Hard Fault 的方法

转载自:http://www.openedv.com/posts/list/25030.htm

1、用Keil的话,可以做如下操作:

先将fault中断函数的内容改为:
HardFault_Handler
                PROC
                ;EXPORT  HardFault_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]
");  
printf ("R0 = %x
", stacked_r0);  
printf ("R1 = %x
", stacked_r1);  
printf ("R2 = %x
", stacked_r2);  
printf ("R3 = %x
", stacked_r3);  
printf ("R12 = %x
", stacked_r12);  
printf ("LR = %x
", stacked_lr);  
printf ("PC = %x
", stacked_pc);  
printf ("PSR = %x
", stacked_psr);  
printf ("BFAR = %x
", (*((volatile unsigned long *)(0xE000ED38))));  
printf ("CFSR = %x
", (*((volatile unsigned long *)(0xE000ED28))));  
printf ("HFSR = %x
", (*((volatile unsigned long *)(0xE000ED2C))));  
printf ("DFSR = %x
", (*((volatile unsigned long *)(0xE000ED30))));  
printf ("AFSR = %x
", (*((volatile unsigned long *)(0xE000ED3C))));  
   
while(1)
{
        ;;
} 
}  
 
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]
");  
printf ("R0 = %x
", stacked_r0);  
printf ("R1 = %x
", stacked_r1);  
printf ("R2 = %x
", stacked_r2);  
printf ("R3 = %x
", stacked_r3);  
printf ("R12 = %x
", stacked_r12);  
printf ("LR = %x
", stacked_lr);  
printf ("PC = %x
", stacked_pc);  
printf ("PSR = %x
", stacked_psr);  
printf ("BFAR = %x
", (*((volatile unsigned long *)(0xE000ED38))));  
printf ("CFSR = %x
", (*((volatile unsigned long *)(0xE000ED28))));  
printf ("HFSR = %x
", (*((volatile unsigned long *)(0xE000ED2C))));  
printf ("DFSR = %x
", (*((volatile unsigned long *)(0xE000ED30))));  
printf ("AFSR = %x
", (*((volatile unsigned long *)(0xE000ED3C))));  
  
  while(1)
  {
          ;;
  }

如果使用调试器,则可以在第一个printf处设置断点。

没有的话看串口打印结果通过查看stacked_lr的内容可以知道程序运行到哪个位置出现fault,然后查看编译后汇编代码,可以知道源程序是哪个函数哪一步出现问题,配合其它寄存器的内容来分析找出原因。

原文地址:https://www.cnblogs.com/pukaifei/p/5717675.html