OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3858|回复: 3

HardFault_Handler程序定位方法

[复制链接]

34

主题

322

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1838
金钱
1838
注册时间
2014-12-4
在线时间
717 小时
发表于 2017-11-16 12:44:57 | 显示全部楼层 |阅读模式
在eeworld论坛看到的定位方法分享给大家,在KEIL环境试了一下挺好用的。http://bbs.eeworld.com.cn/thread-324800-1-1.html



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


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


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2017-11-16 13:50:44 | 显示全部楼层
https://github.com/armink/CmBacktrace
用这个可以定位到具体哪一行,哪一种类型的错误
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

34

主题

322

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1838
金钱
1838
注册时间
2014-12-4
在线时间
717 小时
 楼主| 发表于 2017-11-16 14:44:38 | 显示全部楼层
ianhom 发表于 2017-11-16 13:50
https://github.com/armink/CmBacktrace
用这个可以定位到具体哪一行,哪一种类型的错误

非常感谢,下载试一试
回复 支持 反对

使用道具 举报

34

主题

322

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1838
金钱
1838
注册时间
2014-12-4
在线时间
717 小时
 楼主| 发表于 2017-11-17 21:40:21 | 显示全部楼层
本帖最后由 loudianxin 于 2017-11-17 22:05 编辑
ianhom 发表于 2017-11-16 13:50
https://github.com/armink/CmBacktrace
用这个可以定位到具体哪一行,哪一种类型的错误

固件名称:CmBacktrace,硬件版本号:V1.0.0,软件版本号:V0.1.0
在线程()中发生错误异常
错误:线程栈(00000040)发生溢出
=========== 线程堆栈信息 ===========
====================================
发生用法错误,原因:无效的异常返回码
获取函数调用栈失败



固件名称:,硬件版本号:,软件版本号:
在线程()中发生错误异常
错误:线程栈(200036d0)发生溢出
=========== 线程堆栈信息 ===========
====================================
发生用法错误,原因:试图切换到 ARM 状态
获取函数调用栈失败


我用CmBacktrace调试程序,结果串口输出以上信息,能帮忙分析下吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-10 16:44

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表