搜索
bottom↓
回复: 77

调试必备,一个HardFault_Handler处理代码(非原创)

  [复制链接]

出0入0汤圆

发表于 2016-2-25 06:21:10 | 显示全部楼层 |阅读模式
最近看好几个人做Bootloader被HardFault折磨的不行,我潜水太久太无聊出来冒个泡。

原文地址: Developing a Generic Hard Fault handler for ARM Cortex-M3/Cortex-M4

我看大家进到HardFault_Handler基本都是靠看LR 寄存器进行猜测,有人做了个很好用的HardFault_Handler处理代码,可以直接把错误类型和寄存器内容通过SWO打印出来。
由于ARM在中断的时候会把主要的CPU寄存器自动入栈,所以用这个代码显示出来的结果更精确,尤其是PC跑到0xffffff00左右的情况。

先上个例子,我把PC直接加了0x01000000:



我自从用了以后根本停不下来,直接加到所有工程模板里面了,从Cortex M3 到M7都能用,M0没设备没试过。

不废话了上代码:
  1. /* Private typedef -----------------------------------------------------------*/
  2. enum { r0, r1, r2, r3, r12, lr, pc, psr};
  3. /* Private define ------------------------------------------------------------*/
  4. /* Private macro -------------------------------------------------------------*/
  5. /* Private variables ---------------------------------------------------------*/
  6. /* Private function prototypes -----------------------------------------------*/
  7. void Hard_Fault_Handler(uint32_t stack[]);
  8. /* Private functions ---------------------------------------------------------*/
  9. static void printErrorMsg(const char * errMsg)
  10. {
  11.    while(*errMsg != '\0'){
  12.       ITM_SendChar(*errMsg);
  13.       ++errMsg;
  14.    }
  15. }

  16. static void printUsageErrorMsg(uint32_t CFSRValue)
  17. {
  18.    printErrorMsg("Usage fault: \n");
  19.    CFSRValue >>= 16; // right shift to lsb

  20.    if((CFSRValue & (1<<9)) != 0) {
  21.       printErrorMsg("Divide by zero\n");
  22.    }
  23.    if((CFSRValue & (1<<8)) != 0) {
  24.       printErrorMsg("Unaligned access\n");
  25.    }
  26. }

  27. static void printBusFaultErrorMsg(uint32_t CFSRValue)
  28. {
  29.    printErrorMsg("Bus fault: \n");
  30.    CFSRValue = ((CFSRValue & 0x0000FF00) >> 8); // mask and right shift to lsb
  31. }

  32. static void printMemoryManagementErrorMsg(uint32_t CFSRValue)
  33. {
  34.    printErrorMsg("Memory Management fault: \n");
  35.    CFSRValue &= 0x000000FF; // mask just mem faults
  36. }

  37. static void stackDump(uint32_t stack[])
  38. {
  39.    static char msg[80];
  40.    sprintf(msg, "R0  = 0x%08x\n", stack[r0]);  printErrorMsg(msg);
  41.    sprintf(msg, "R1  = 0x%08x\n", stack[r1]);  printErrorMsg(msg);
  42.    sprintf(msg, "R2  = 0x%08x\n", stack[r2]);  printErrorMsg(msg);
  43.    sprintf(msg, "R3  = 0x%08x\n", stack[r3]);  printErrorMsg(msg);
  44.    sprintf(msg, "R12 = 0x%08x\n", stack[r12]); printErrorMsg(msg);
  45.    sprintf(msg, "LR  = 0x%08x\n", stack[lr]);  printErrorMsg(msg);
  46.    sprintf(msg, "PC  = 0x%08x\n", stack[pc]);  printErrorMsg(msg);
  47.    sprintf(msg, "PSR = 0x%08x\n", stack[psr]); printErrorMsg(msg);
  48. }

  49. void Hard_Fault_Handler(uint32_t stack[])
  50. {
  51.    static char msg[80];
  52.    //if((CoreDebug->DHCSR & 0x01) != 0) {
  53.       printErrorMsg("\nIn Hard Fault Handler\n");
  54.       sprintf(msg, "SCB->HFSR = 0x%08x\n", SCB->HFSR);
  55.       printErrorMsg(msg);
  56.       if ((SCB->HFSR & (1 << 30)) != 0) {
  57.          printErrorMsg("Forced Hard Fault\n");
  58.          sprintf(msg, "SCB->CFSR = 0x%08x\n", SCB->CFSR );
  59.          printErrorMsg(msg);
  60.          if((SCB->CFSR & 0xFFFF0000) != 0) {
  61.             printUsageErrorMsg(SCB->CFSR);
  62.          }
  63.          if((SCB->CFSR & 0xFF00) != 0) {
  64.             printBusFaultErrorMsg(SCB->CFSR);
  65.          }
  66.          if((SCB->CFSR & 0xFF) != 0) {
  67.             printMemoryManagementErrorMsg(SCB->CFSR);
  68.          }
  69.       }
  70.       stackDump(stack);
  71.       __ASM volatile("BKPT #01");
  72.    //}
  73.    while(1);
  74. }
  75. /******************************************************************************/
  76. /*            Cortex-M7 Processor Exceptions Handlers                         */
  77. /******************************************************************************/

  78. /**
  79.   * @brief  This function handles NMI exception.
  80.   * @param  None
  81.   * @retval None
  82.   */
  83. void NMI_Handler(void)
  84. {
  85. }

  86. /**
  87.   * @brief  This function handles Hard Fault exception.
  88.   * @param  None
  89.   * @retval None
  90. */
  91. void HardFault_Handler(void)
  92. {
  93.    __asm("TST lr, #4");
  94.    __asm("ITE EQ \n"
  95.          "MRSEQ r0, MSP \n"
  96.          "MRSNE r0, PSP");
  97.    __asm("B Hard_Fault_Handler");
  98. }
复制代码


最后上几个自己的USB Bootloader的照片


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-2-25 07:56:39 | 显示全部楼层
谢谢分享,比较实用

出0入0汤圆

发表于 2016-2-25 08:53:31 | 显示全部楼层
好东西 MARK

出0入0汤圆

发表于 2016-2-25 08:54:41 | 显示全部楼层
谢谢楼主,mark!!!

出0入0汤圆

发表于 2016-2-25 08:55:13 | 显示全部楼层
谢谢楼主分享!!!

出0入0汤圆

发表于 2016-2-25 08:58:38 | 显示全部楼层
UI是用什么做的?

出0入0汤圆

发表于 2016-2-25 09:02:25 | 显示全部楼层
谢谢分享,学习了。

但是有一点疑问,没看明白stack[]是从哪里获得的。

出0入0汤圆

发表于 2016-2-25 09:07:26 | 显示全部楼层

谢谢分享, 收藏备用。

出0入42汤圆

发表于 2016-2-25 09:12:29 | 显示全部楼层
之前一直是看LR,LR无法追踪就自猜或反复调试。

出0入0汤圆

发表于 2016-2-25 09:15:16 | 显示全部楼层
MARK

出0入0汤圆

发表于 2016-2-25 09:19:29 来自手机 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2016-2-25 09:32:50 | 显示全部楼层
谢谢分享

出0入42汤圆

发表于 2016-2-25 09:54:56 | 显示全部楼层
请问楼主原文地址你是怎么找到的?

出0入0汤圆

发表于 2016-2-25 10:04:10 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2016-2-25 10:36:15 | 显示全部楼层
谢谢分享,非常实用,如果能把在哪个函数的第几行打印出来,就更好啦:)

出0入0汤圆

发表于 2016-2-25 11:06:05 | 显示全部楼层
谢楼主分享!

出0入0汤圆

发表于 2016-2-25 11:21:01 | 显示全部楼层
dalarang 发表于 2016-2-25 09:02
谢谢分享,学习了。

但是有一点疑问,没看明白stack[]是从哪里获得的。

函数调用的时候会把关键寄存器放到堆栈里面,函数退出后在恢复到寄存器中。

堆栈压入顺序即 R0 ~ R3 ...,那根传递的参数有毛关系呢,arm编译器约定函数调用的参数在R0寄存器,这里使用堆栈中R0寄存器的地址作为索引。

不知道表达的请不清晰。。。。

出0入0汤圆

发表于 2016-2-25 11:36:23 | 显示全部楼层
没有试过,看着是个好东西

出0入0汤圆

发表于 2016-2-25 11:37:45 | 显示全部楼层
好东西,多谢分享

出0入0汤圆

发表于 2016-2-25 12:48:08 | 显示全部楼层
谢谢楼主分享!

出0入0汤圆

发表于 2016-2-25 13:17:59 | 显示全部楼层
看起来不错,比我做的简单多了。分享快乐

出0入0汤圆

 楼主| 发表于 2016-2-25 15:40:21 | 显示全部楼层
ghostxdy 发表于 2016-2-25 08:58
UI是用什么做的?

emWin,启用皮肤就是这个效果

出0入0汤圆

 楼主| 发表于 2016-2-25 15:41:34 | 显示全部楼层
liyang121316 发表于 2016-2-25 09:54
请问楼主原文地址你是怎么找到的?

人在国外,平时都习惯用Google。
还有就是因为GFW上国内网太慢。。。。

出0入0汤圆

发表于 2016-2-25 15:45:55 | 显示全部楼层
谢谢楼主,好资料!

出0入42汤圆

发表于 2016-2-25 15:53:06 | 显示全部楼层
MasterPhi 发表于 2016-2-25 15:41
人在国外,平时都习惯用Google。
还有就是因为GFW上国内网太慢。。。。  ...


了解!!!你在国外上学还是工作?嵌入式行业怎么样?

出0入16汤圆

发表于 2016-2-25 17:04:35 | 显示全部楼层
这确实是个好方法,只不过原文作者也不是原创的,我早在09年就在墙外找到这种方法并发在本坛了,可惜后来论坛转换服务器后多了很多乱码看不清楚了。前两年在STM32的技术支持网站上也看到过介绍这种方法中文文章,印象中后来的RT-Thread上也有这种处理。
09年发的原贴子:http://www.amobbs.com/thread-2013982-1-1.html

出0入0汤圆

发表于 2016-2-25 17:15:21 | 显示全部楼层

出0入0汤圆

发表于 2016-2-25 17:34:58 | 显示全部楼层
楼主,你的代码在746里面编译会出错,

出0入13汤圆

发表于 2016-2-25 18:37:50 来自手机 | 显示全部楼层
谢谢分享,好东西支持一个

出0入0汤圆

发表于 2016-2-25 20:37:08 | 显示全部楼层
很不错,谢谢分享!

出0入0汤圆

发表于 2016-2-25 20:47:44 | 显示全部楼层
Elex 发表于 2016-2-25 17:04
这确实是个好方法,只不过原文作者也不是原创的,我早在09年就在墙外找到这种方法并发在本坛了,可惜后来论 ...

一直没看过Rtt的详细代码,平时偶尔用用,原来也是这样的。我当时为了找故障,也是在.s文件里写了段代码从堆栈里把PC找到打出来。看是哪个函数出的错。

出5入10汤圆

发表于 2016-2-25 21:00:16 | 显示全部楼层
编译遇到这个错误,不知道咋回事

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-2-25 21:46:49 | 显示全部楼层
mark: HardFault_Handler处理代码

出0入0汤圆

 楼主| 发表于 2016-2-26 00:08:45 | 显示全部楼层
涵潇舒雅 发表于 2016-2-25 21:00
编译遇到这个错误,不知道咋回事

你把_asm里面的分开3行写试试,我用的iar

出0入0汤圆

发表于 2016-2-26 20:51:29 | 显示全部楼层
很实用的资料,谢谢分享了

出0入8汤圆

发表于 2016-2-27 08:43:50 | 显示全部楼层
学习了,以前遇到过的问题!

出0入0汤圆

发表于 2016-2-27 08:54:38 | 显示全部楼层
东西不错

出0入0汤圆

发表于 2016-2-27 09:03:30 | 显示全部楼层
楼主USB bootloader程序是否可以共享下。

出0入0汤圆

发表于 2016-2-27 09:04:44 | 显示全部楼层
谢谢分享,好东西

出0入31汤圆

发表于 2016-2-27 09:18:42 来自手机 | 显示全部楼层
这个不错,查问题方便

出0入0汤圆

发表于 2016-2-27 09:41:03 | 显示全部楼层
非常好,多谢LZ共享!

出0入0汤圆

发表于 2016-2-29 10:12:21 | 显示全部楼层
我也想要usb bootloader,既然秀了就要shareshare

出0入0汤圆

发表于 2016-2-29 11:48:49 | 显示全部楼层
感谢分享,以前调HardFault折腾了好久

出0入0汤圆

发表于 2016-2-29 12:00:28 | 显示全部楼层
相当赞!谢谢分享!

出5入10汤圆

发表于 2016-4-1 09:39:17 | 显示全部楼层
cdtlzhou 发表于 2016-2-29 12:00
相当赞!谢谢分享!

你能编译通过吗?

出0入0汤圆

发表于 2016-4-21 11:50:17 | 显示全部楼层
今天有时间,试了一下楼主的代码,确实编译不过。

出0入0汤圆

发表于 2016-4-21 13:50:17 | 显示全部楼层
Mark一下,虽然现在看不懂,但我相信终有一天可以看懂!!!

出0入0汤圆

 楼主| 发表于 2016-4-21 14:32:13 | 显示全部楼层
pldjn 发表于 2016-4-21 11:50
今天有时间,试了一下楼主的代码,确实编译不过。

我用的IAR 7.50,其他的编译器内嵌汇编的语法可能不同。

出0入0汤圆

发表于 2016-4-21 15:14:24 | 显示全部楼层
大神,高级的玩意,村底层的东西,老有用了。!

出0入0汤圆

发表于 2016-6-20 11:20:16 | 显示全部楼层
不错                     

出0入0汤圆

发表于 2016-6-27 18:00:19 | 显示全部楼层
谢谢分享, 收藏备用。

出0入0汤圆

发表于 2016-6-27 18:28:25 | 显示全部楼层
这个我也要试试,每次hardfault都找不到北

出0入0汤圆

发表于 2016-6-28 14:01:27 | 显示全部楼层
可以更直观地显示硬件错误类型,很方便! 直接copy到工程里了 哈哈

出0入0汤圆

发表于 2016-6-28 17:49:53 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2016-8-25 14:17:09 | 显示全部楼层
iar 需要设置吗?没有打印出来

出0入0汤圆

发表于 2016-8-25 14:50:25 | 显示全部楼层
lihaimeng@163 发表于 2016-8-25 14:17
iar 需要设置吗?没有打印出来

ITM介绍


ITM需要swd方式,并且需要接swo,是不是这个问题引起的

出0入0汤圆

发表于 2016-8-25 15:18:32 | 显示全部楼层

多设置了,没效果,设置了SWO, 用标准的JTAG口内部已经连接了SWO,还是不行

出0入0汤圆

发表于 2016-8-25 15:23:10 | 显示全部楼层
lihaimeng@163 发表于 2016-8-25 15:18
多设置了,没效果,设置了SWO, 用标准的JTAG口内部已经连接了SWO,还是不行
...

semihost retarget

出0入0汤圆

发表于 2016-8-25 15:36:12 | 显示全部楼层

放了,

#define ITM_Port8(n)    (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))
#define DEMCR           (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA          0x01000000

struct __FILE { int handle; /* Add whatever you need here */ };
    FILE __stdout;
    FILE __stdin;
   
int fputc(int ch, FILE *f)
{
    if (DEMCR & TRCENA)
    {
        while (ITM_Port32(0) == 0);
        ITM_Port8(0) = ch;
    }
    return(ch);
}


还是没效果

出0入0汤圆

发表于 2016-8-25 16:46:23 | 显示全部楼层
真的是好东西啊,

出0入0汤圆

发表于 2016-8-26 09:21:03 | 显示全部楼层

已经可以了,是硬件问题,开发板上SWO接了芯片,所以通讯可能不正常了,换了stm32  
discover 就可以了,谢谢

出0入0汤圆

发表于 2016-8-26 11:03:56 | 显示全部楼层
这方法确实不错,多谢楼主

出0入0汤圆

发表于 2016-8-26 13:39:19 | 显示全部楼层
硬件错误的处理代码,不错

出0入8汤圆

发表于 2017-8-24 14:31:36 | 显示全部楼层
__ASM volatile("BKPT #01");  这句话是什么意思     IAR中编译不过

出0入0汤圆

发表于 2017-8-24 16:25:51 | 显示全部楼层
碰到比较少,但是很有用

出0入198汤圆

发表于 2017-8-24 21:44:15 | 显示全部楼层
推荐尝试下 CmBacktrace ,一款 开源 的 针对 ARM Cortex-M 系列的 MCU 错误追踪库 https://github.com/armink/CmBacktrace ,支持追踪各种 hardfault

出0入8汤圆

发表于 2017-8-24 22:47:24 | 显示全部楼层
sunnydragon 发表于 2017-8-24 21:44
推荐尝试下 CmBacktrace ,一款 开源 的 针对 ARM Cortex-M 系列的 MCU 错误追踪库 https://github.com/arm ...

使用中硬件上需要具备哪些条件   还有那个addr2line是怎么用的

出0入0汤圆

发表于 2017-8-24 23:38:55 | 显示全部楼层
看看学习了

出0入4汤圆

发表于 2018-2-13 11:02:32 | 显示全部楼层
涵潇舒雅 发表于 2016-2-25 21:00
编译遇到这个错误,不知道咋回事

你编译通过了吗?我的和你一样。

出0入0汤圆

发表于 2018-2-13 14:02:29 | 显示全部楼层
最新版IAR已经有了异常原因分析功能

出0入0汤圆

发表于 2018-3-3 10:03:21 | 显示全部楼层
mark:调试必备,一个HardFault_Handler处理代码

出0入0汤圆

发表于 2018-3-4 00:13:17 | 显示全部楼层
mark 一下

出0入0汤圆

发表于 2018-8-8 08:43:37 | 显示全部楼层
谢谢分享, 收藏备用。

出0入0汤圆

发表于 2022-5-3 17:54:12 | 显示全部楼层
兄弟这句通不过__asm("B Hard_Fault_Handler");
错误提示,8多,9多的版本都试过
Error[Og005]: Unknown symbol in inline assembly: "Hard_Fault_Handler" N:\NewMcuLib\Apply\Algorithm\Apply_HardFault.c 115
Error[Og006]: Error in inline assembly: "Expression can not be forward" N:\NewMcuLib\Apply\Algorithm\Apply_HardFault.c 115

出0入0汤圆

发表于 2023-3-13 08:45:19 | 显示全部楼层
兄弟为什么我这个输出查看的窗口没有东西显示,网上找了一圈别人也有这样问题,照他们的方法也不行

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2023-3-14 07:24:15 | 显示全部楼层
是不是需要完整的jtag接口,才行,我现在只用swo接口的2条线

出0入0汤圆

 楼主| 发表于 2023-3-14 19:07:42 | 显示全部楼层
cnxh 发表于 2023-3-13 08:45
兄弟为什么我这个输出查看的窗口没有东西显示,网上找了一圈别人也有这样问题,照他们的方法也不行
...
(引用自75楼)

没有SWO的话得配置其他底层输出的方法,比如说RTT

出0入0汤圆

发表于 2023-3-14 19:16:32 | 显示全部楼层

硬件错误的处理代码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 03:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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