origin:http://www.51hei.com/bbs/dpj-39846-1.html

看到有朋友遇到Hard Fault 异常错误,特地找到一篇飞思卡尔工程师写的一片经验帖,定位Hard Fault 异常。

Kinetis MCU 采用 Cortex-M4 的内核,该内核的 Fault 异常可以捕获非法的内存访问和非法的编程行为。Fault 异常能够检测到以下几类非法行为:

·        总线 Fault:  在取址、数据读/写、取中断变量、进入/退出中断时寄存器堆栈操作(入栈/出栈)时检测到内存访问错误。
·        存储器管理 Fault: 检测到内存访问违反了内存保护单元(MPU, MemoryProtection Unit)定义的区域。
·        用法 Fault:  检测到未定义的指令异常,未对其的多重加载/存储内存访问。如果使能相应控制位,还可以检测出除数为零以及其他未对齐的内存访问。
·        硬 Fault:  如果上述的总线 Fault、存储器管理 Fault、用法 Fault 的处理程序不能被执行(例如禁能了总线 Fault、存储器管理Fault、用法Fault 的异常或者在这些异常处理程序中又出现了新的Fault)则触发硬Fault。
在 MQX 操作系统启动的时候会安装上默认的异常中断处理函数,当系统异常时会产生一个“unexpected ”中断,内核就会自动调用异常处理函数,同时也将运行用户自定义的处理函数,来实现特殊故障的定位方法。
默认情况下,MQX 把出现异常的任务挂起,避免故障进一步扩大。通过TAD 任务感知调试插件的Task summary 功能,我们可以观察到出现异常的任务情况。
开发人员在调试期间,需要弄清楚系统异常触发了哪类Fault,由什么原因触发了Fault 以及定位触发Fault 的代码。在这种情况下,可以利用自定义的Fault 中断处理程序来分析
Fault 出错原因。
为了解释所述的 Fault 中断处理程序的原理,这里重述一下当系统产生异常时 MCU 的处理过程:
·        有一个压栈的过程,若产生异常时使用 PSP(进程栈指针),就压入到 PSP 中,若产生异常时使用MSP(主栈指针),就压入MSP 中。
·        会根据处理器的模式和使用的堆栈,设置 LR 的值(当然设置完的LR 的值再压栈)。
·        异常保存,硬件自动把 8 个寄存器的值压入堆栈(8 个寄存器依次为 xPSR、PC、LR、R12以及 R3~R0)。如果异常发生时,当前的代码正在使用PSP,则上面8 个寄存器压入PSP; 否则就压入MSP。
当系统产生异常时,我们需要两个关键寄存器值,一个是 PC ,一个是 LR (链接寄存器),通过 LR找到相应的堆栈,再通过堆栈找到触发异常的PC 值。将产生异常时压入栈的 PC 值取出,并与反汇编的代码对比就能得到哪条指令产生了异常。
这里解释一下关于 LR 寄存器的工作原理。如上所述,当 Cortex-M4 处理器接受了一个异常后,寄存器组中的一些寄存器值会被自动压入当前栈空间里,这其中就包括链接寄存器(LR )。这时的 LR 会被更新为异常返回时需要使用的特殊值(EXC_RETURN)。关于
EXC_RETURN 的定义如下,其为 32 位数值,高 28 位置 1,第 0 位到第三位则提供了异常返回机制所需的信息,如下表所示。可见其中第 2 位标示着进入异常前使用的栈是 MSP还是PSP。在异常处理过程结束时,MCU 需要根据该值来分配 SP 的值。这也是本方法中用来判断所使用堆栈的原理,其实现方法可以从后面_init_hardfault_isr 中看到。
另外,我们可以利用 MQX 的控制台串口输出Fault 异常信息来帮助调试。编写Fault 处理程序时,将启动代码中默认的Fault 处理程序跟换成自己需要的Fault 处理程序。需要注意的是,由于是在中断中进行打印输出,MQX的控制台串口只能使用POLL 轮询模式的驱动,不能使用中断模式的驱动。
用户可以编写自定义的硬 Fault 处理程序_int_hardfault_isr,修改 MQX 的中断向量定义vector.c,把里面的DEFAULT_VECTOR 代码段换成下面的代码。当系统出现硬Fault 异常时,将会调用自定义的Fault 处理_int_hardfault_isr函数。在这个函数,我们可以通过StackTrace-back 回溯出现问题的代码。
我们可以在_int_hardfault_isr 函数里将出现异常时的寄存器、堆栈、状态寄存器等信息打印出来。如果系统出现异常时,一般情况都会通过串口控制台打印出LR,PC的值。然后根据编译器生成的map 文件,找到出现问题的具体函数。
从上图的串口输出我们可以看到 PC 和 LR 寄存器值,PC 的值为 0x56c6,我们根据汇编代码可以找到出现问题的指令。从而大大缩小了查找出现问题的范围,可以帮助开发人员快速定位问题的根本原因。
附录Fault异常中断处理代码:

  1. // hard fault handler in C,
  2. // with stack frame location as input parameter
  3. void hard_fault_handler_c (unsigned int * hardfault_args)
  4. {
  5. unsigned int stacked_r0;
  6. unsigned int stacked_r1;
  7. unsigned int stacked_r2;
  8. unsigned int stacked_r3;
  9. unsigned int stacked_r12;
  10. unsigned int stacked_lr;
  11. unsigned int stacked_pc;
  12. unsigned int stacked_psr;
  13. stacked_r0 = ((unsigned long)hardfault_args[0]);
  14. stacked_r1 = ((unsigned long)hardfault_args[1]);
  15. stacked_r2 = ((unsigned long)hardfault_args[2]);
  16. stacked_r3 = ((unsigned long)hardfault_args[3]);
  17. stacked_r12 = ((unsigned long)hardfault_args[4]);
  18. stacked_lr = ((unsigned long)hardfault_args[5]);
  19. stacked_pc = ((unsigned long)hardfault_args[6]);
  20. stacked_psr = ((unsigned long) hardfault_args[7]);
  21. printf ("\n\n[Hard faulthandler - all numbers in hex]\n");
  22. printf ("R0 = %x\n",stacked_r0);
  23. printf ("R1 = %x\n",stacked_r1);
  24. printf ("R2 = %x\n",stacked_r2);
  25. printf ("R3 = %x\n",stacked_r3);
  26. printf ("R12 = %x\n",stacked_r12);
  27. printf ("LR [R14] = %x  subroutine call return address\n",stacked_lr);
  28. printf ("PC [R15] = %x  program counter\n", stacked_pc);
  29. printf ("PSR = %x\n",stacked_psr);
  30. /******************* Add yourdebug trace here ***********************/
  31. _int_kernel_isr();
  32. }
  33. /* hard fault interrupt handler */
  34. void _int_hardfault_isr( )
  35. {
  36. __asm("TST LR, #4");
  37. __asm("ITE EQ");
  38. __asm("MRSEQ R0,MSP");
  39. __asm("MRSNE R0,PSP");
  40. __asm("Bhard_fault_handler_c");
  41. }

复制代码

fault_isr.c.zip

1.42 KB, 下载次数: 7, 下载积分: 黑币 -5

vectors.c.zip

3.43 KB, 下载次数: 4, 下载积分: 黑币 -5

如何定位Kinetis MCU Hard Fault异常.pdf

362.58 KB, 下载次数: 15, 下载积分: 黑币 -5

Hard Fault 异常错误堆栈分析相关推荐

  1. python读取日志错误信息_使用Python将Exception异常错误堆栈信息写入日志文件

    假设需要把发生异常错误的信息写入到log.txt日志文件中去: import traceback import logging logging.basicConfig(filename='log.tx ...

  2. python把异常写入文件_使用Python将Exception异常错误堆栈信息写入日志文件代码

    本篇文章小编给大家分享一下使用Python将Exception异常错误堆栈信息写入日志文件代码及补充知识,对大家的学习有一定的帮助,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看 ...

  3. Segmentation fault段错误出现原因分析及解决方法笔记

    Segmentation fault段错误出现原因分析及解决方法 1.局部变量的大小过大,超过栈分配的空间导致段错误,如double a[500][500], 解决方法:大数据不要放在栈区中,可以考虑 ...

  4. logback配置控制打印台异常信息_logback异常输出详细信息(调用堆栈)分析

    Logback背景 Logback是一个开源的日志组件,是log4j的作者开发的用来替代log4j的. logback由三个部分组成,logback-core, logback-classic, lo ...

  5. php tp6 错误接管分析,ThinkPHP5 异常接管

    在实际应用中,对于异常错误处理,我们往往需要进行错误的友好处理,并且需要记录错误(越为详细越好),一方面提高了用户的体验,另一方面也可以帮助开发人员更好的调试. 首先我们在项目中自定义异常处理类: 在 ...

  6. Linux平台Segmentation fault(段错误)调试方法

    1. 段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址.访问了系统保护的内存地址.访问了只读的内存地址等等情况. 2. 段错误的原因 段错 ...

  7. 段错误原因分析和查找

    转自:http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基础之 ...

  8. 功能安全之故障(fault),错误(error),失效(failure)

    功能安全中的有些概念比较绕,比如故障(fault),错误(error),失效(failure),本文就这三个概念进行下探讨. 1. 故障 功能安全中定义的故障是指可引起要素或相关项失效的异常情况. 故 ...

  9. java堆栈分析工具_JVM内存分析工具使用

    Java 内存堆栈分析.我们在分析现网问题时候,经常会遇到一些问题从日志上无法分析的疑难问题.在我们举足无措的时候,我们可以分析一些JVM内存,来看看问题出在哪里了. 我们经常用到的一工具: 分析栈内 ...

最新文章

  1. 自动布局按钮排列平均分布
  2. hibernate 集合类(Collections)映射
  3. 第二周 第七节 列表的使用
  4. Linux下计划任务:crontab 命令的权限说明
  5. python发邮件有什么意思_python发邮件要装什么
  6. 系统分析与设计结对项目———Wordcount
  7. mate 树莓派4b安装ubuntu_树莓派4B安装安装Ubuntu Mate 16.04
  8. 数学建模(5)---煤矸石堆积问题
  9. python 3.5 format_python 3.5学习笔记(第四章)
  10. 利用python并发模块进行网站的状态检测
  11. mapjoin的使用方法以及注意事项
  12. I2S协议及在verilog中实现
  13. 如何设置路由器wifi的用户黑名单?(使别人不能连接你家WIFI)
  14. Windows11跳过联网激活方法
  15. shiro.crypto.CryptoException: Unable to correctly extract the Initialization Vector or ciphertext
  16. Python实现久坐提醒小助手程序
  17. oracle11配置远程登录,oracle11g远程登录设置方法
  18. 【CSS】 画优惠券锯齿边框样式
  19. QT 自定义加载等待(Loading)提示框
  20. linux常用命令||

热门文章

  1. 大量数据转录的多线程和同步处理实现
  2. http状态码、含义大全
  3. 计算机更改显卡,如何更换显卡
  4. 使用MAC进行软件开发
  5. 为什么小姐姐能摇一晚上不倒?
  6. 如何获取特定用户组内的无效账户?
  7. 阿里天池——Numpy实战
  8. 程序员必读书单 1.0 ----转自Lucida
  9. cnki登录显示服务器或网络异常,知网查重官网为什么无法登录?
  10. (递推)常用递推式总结及实现