Cortex-M3/4的Hard Fault调试方法

1 Cortex-M3/4的Fault简介

Cortex-M3/4的Fault异常是由于非法的存储器访问(比如访问0地址、写只读存储位置等)和非法的程序行为(比如除以0等)等造成的。常见的4种异常及产生异常的情况如下:

Bus Fault:在fetch指令、数据读写、fetch中断向量或中断时存储恢复寄存器栈情况下,检测到内存访问错误则产生Bus Fault。

Memory Management Fault:访问了内存管理单元(MPU)定义的不合法的内存区域,比如向只读区域写入数据。

Usage Fault:检测到未定义指令或在存取内存时有未对齐。还可以通过软件配置是否检测到除0和其它未对齐内存访问也产生该异常,默认关闭,需要在工程初始化时配置:

[cpp] view plaincopyprint?

  1. SCB->CCR |= 0x18; // enable div-by-0 and unaligned fault

Hard Fault:在调试程序过程中,这种异常最常见。上面三种异常发生任何一种异常都会引起Hard Fault,在上面的三种异常未使能的情况下,默认发生异常时进入Hard Fault中断服务程序。使能前三种异常也要在初始化时配置:

[cpp] view plaincopyprint?

  1. SCB->SHCSR |= 0x00007000;   // enable Usage Fault, Bus Fault, and MMU Fault

在默认复位初始化时,Hard Fault使能,其它三者不使能,因此当程序中出现不合法内存访问(一般是指针错误引起)或非法的程序行为(一般就是数学里面常见的除0)时都将产生Hard Fault中断。

2 Hard Fault调试方法

假设IDE环境为Keil,芯片为STM32F103。

在stm32f10x_it.c中,添加软件断点,一旦调试时出现Hard Fault则会在停在__breakpoint(0)处。

[cpp] view plaincopyprint?

  1. /**
  2. * @brief  This function handles Hard Fault exception.
  3. * @param  None
  4. * @retval None
  5. */
  6. void HardFault_Handler(void)
  7. {
  8. /* Go to infinite loop when Hard Fault exception occurs */
  9. if (CoreDebug->DHCSR & 1) {  //check C_DEBUGEN == 1 -> Debugger Connected
  10. __breakpoint(0);  // halt program execution here
  11. }
  12. while (1)
  13. {
  14. }
  15. }

当进入Hard Fault断点后,菜单栏Peripherals >Core Peripherals >Fault Reports打开异常发生的报告,查看发生异常的原因。


上面的报告发生了BUS FAULT,并将Fault的中断服务转向Hard Fault。

相对于检测发生了什么异常,定位异常发生位置显得更重要。
(1)打开Call Stack窗口(如下图左侧,断点停在Hard Fault服务程序中)


(2)在Call Stack的HardFault_Handler上右键Show Caller Code(有的Keil版本也可以直接双击)

这时将跳转到发生异常的源代码位置(如上图),异常发生在p->hour=0这一行。这里错误很明显:指针p尚未为成员变量分配内存空间,直接访问未分配的内粗空间肯定出错。

再说明2点:
[1] 在复杂的情况下,即使定位了异常发生位置也很难容易的改正错误,要学会使用Watch窗口对发生错误的指针变量进行跟踪;
[2] 在问题不明晰的情况下,尝试分析反汇编代码,就自己遇到的,部分情况下的异常发生在BL等跳转指令处,BL跳转到了不合法的内存地址产生异常

Refrences:

[1] Application Note 209. Using Cortex-M3 and Cortex-M4 Fault Exceptions.

[2] Cortex-M3权威指南

时间: 2024-10-13 06:36:56

Cortex-M3/4的Hard Fault调试方法的相关文章

Linux 下的段错误(Segmentation fault)调试方法

我们在用C/C++语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的.实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难免会在此处犯些小错误,而通常这些错误又是那么的浅显而易于消除.但是手工“除虫”(debug),往往是效率低下且让人厌烦的,本文将就"段错误"这个内存访问越界的错误谈谈如何快速定位这些"段错误"的语句. 下面将就以下的一个存在段错误的程序介绍几种调试方法: 1 dummy_function (void) 2 { 3 unsig

linux Ubuntu(Segmentation fault)段错误出现原因及调试方法

  在linux下编译了一个程序,尝试运行的时候出现: Segmentation fault (core dumped) 初步确认为...完全不知道是什么玩意. 于是找度娘了. ---------------------------------------------------------------------------- 出现原因 原来这个东西叫做段错误,就程序运行的时候出现内存错误.有很多原因会导致这样的内存错误,但是应该把这些问题归结于程序的错误,那么程序是出现了什么样的错误了呢,为

嵌入式linux应用程序调试方法

嵌入式linux应用程序调试方法 四 内存工具 17 4.1 MEMWATCH 17 4.2 YAMD 22 4.3 Electric Fence 24 五 C/C++代码覆盖.性能profiling工具 24 5.1 用gcov来测试代码覆盖率 25 5.2 使用gprof来优化你的C/C++程序 35 四 内存工具 您肯定不想陷入类似在几千次调用之后发生分配溢出这样的情形. 许多小组花了许许多多时间来跟踪稀奇古怪的内存错误问题.应用程序在有的开发工作站上能运行,但在新的产品工作站上,这个应用

段错误以及调试方法

---恢复内容开始--- 常见内存错误 (1)内存分配(malloc, new)未成功,却使用了它. 解决方法:在使用内存之前检查指针是否为NULL (2)内存分配成功,但是没有初始化.在定义数组时养成赋0值的习惯. (3)内存分配成功,也初始化了,操作越过了内存的边界. (4)忘记释放内存,造成内存泄漏 (5)释放了内存后继续使用,有三种情况: 程序中的对象调用过于复杂,比如: int *a = new int[10]; int *b = a; delete b;//已经将a所指向的内存释放

Linux环境下段错误的产生原因及调试方法小结(转)

最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且 项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的“段错误”(Segmentation Fault).借此机会系统学习了一下,这里对Linux环境下的段错误做个小结,方便以后同类问题的排查与解决. 1. 段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址.访问了系统保护的内存地址.访问了只读的内存地址等等情况.这里贴一个对于“段

linux设备驱动第四篇:从如何定位oops的代码行谈驱动调试方法

上一篇我们大概聊了如何写一个简单的字符设备驱动,我们不是神,写代码肯定会出现问题,我们需要在编写代码的过程中不断调试.在普通的c应用程序中,我们经常使用printf来输出信息,或者使用gdb来调试程序,那么驱动程序如何调试呢?我们知道在调试程序时经常遇到的问题就是野指针或者数组越界带来的问题,在应用程序中运行这种程序就会报segmentation fault的错误,而由于驱动程序的特殊性,出现此类情况后往往会直接造成系统宕机,并会抛出oops信息.那么我们如何来分析oops信息呢,甚至根据oop

linux设备驱动第四篇:以oops信息定位代码行为例谈驱动调试方法

上一篇我们大概聊了如何写一个简单的字符设备驱动,我们不是神,写代码肯定会出现问题,我们需要在编写代码的过程中不断调试.在普通的c应用程序中,我们经常使用printf来输出信息,或者使用gdb来调试程序,那么驱动程序如何调试呢?我们知道在调试程序时经常遇到的问题就是野指针或者数组越界带来的问题,在应用程序中运行这种程序就会报segmentation fault的错误,而由于驱动程序的特殊性,出现此类情况后往往会直接造成系统宕机,并会抛出oops信息.那么我们如何来分析oops信息呢,甚至根据oop

Linux环境下段错误的产生原因及调试方法小结

最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的“段错误”(Segmentation Fault).借此机会系统学习了一下,这里对Linux环境下的段错误做个小结,方便以后同类问题的排查与解决. 1. 段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址.访问了系统保护的内存地址.访问了只读的内存地址等等情况.这里贴一个对于“段错

【转】【调试技巧】Linux环境下段错误的产生原因及调试方法小结

本文转自:http://www.cnblogs.com/panfeng412/archive/2011/11/06/segmentation-fault-in-linux.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的“段错误”(Segmentation Fault).借此机会系统学习了一下,这里对Linux环境下的段错误做个小结,方便以后同类问题的排查与解决. 1. 段错误