查看: 3872|回复: 3

定位ARM Hard Fault 的方法(转)

[复制链接]
  • TA的每日心情
    擦汗
    2014-2-12 10:49
  • 签到天数: 150 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2013-8-28 09:54:47 | 显示全部楼层 |阅读模式
    分享到:
    为了定位ARM Hard Fault 可以说是愁的不行,看书、上网搜、论坛求助、群里询问。。。能想到的办法都做了,就是有点地方被绊住,就结了好几天了,一个偶然的机会看到了这个,心理说不出的激动。
    大家一起看看吧,相信对大家也会有很大的帮助。

    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]\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
    然后查看编译后汇编代码,可以知道源程序是哪个函数哪一步出现问题,
    配合其它寄存器的内容来分析找出原因

    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2016-8-25 12:42
  • 签到天数: 692 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2013-8-28 10:04:34 | 显示全部楼层
    这个资料必须得顶!在使用DFU选项功能时,经常碰到这个问题,确实找原因麻烦
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2020-9-10 08:39
  • 签到天数: 125 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2013-8-28 11:23:52 | 显示全部楼层
    这个确实没有遇到过!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2014-2-12 10:49
  • 签到天数: 150 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2013-9-11 09:34:56 | 显示全部楼层
    l廖天一阁主 发表于 2013-8-28 11:23
    这个确实没有遇到过!

    总会遇到的
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条



    手机版|小黑屋|与非网

    GMT+8, 2025-1-11 12:43 , Processed in 0.132491 second(s), 20 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.