你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验之谈】基于STM32 KEIL调试程序进入HardFault_Handler异常处理总结的经验分享

[复制链接]
STMCU小助手 发布时间:2022-12-8 16:00

在做CORTEX-M3单片机开发的时候,如STM32,可能会遇到设备跑着跑着程序死机的情况,往往调试起来很多时候发现是程序进入HardFault_Handler系统异常,根据相关资料和M3权威指南是可以通过调试查找出程序的问题点和解决问题的。

, Y( H0 _* L6 C. c. D# p* z8 V

根据CM3指南中的 Faults 可分为4类:总线 faults、存储器管理 faults、用法 faults、硬 fault;


; f- q  i7 [* p# }$ T

以下是具体说明:

1、总线 Faults是当 AHB 接口上正在传送数据时,如果回复了一个错误信号,则会产生总线 faults,CM3有一个名为“总线 fault 状态寄存器”(BFSR)的。通过它,总线 fault 服务程序可以确定产生 fault 的场合是在数据访问时、在取指时、还是在中断的堆栈操作时。这个不展开细说


; k  B$ j9 F! s  E: v) q2 ^- w$ G* G9 c; j

2、存储器管理faults多与MPU有关,其诱因常常是某次访问触犯了MPU设置的保护策略。另外,某些非法访问,例如,在不可执行的存储器区域试图取指,也会触发一个 MemManagefault,而且即使没有 MPU 也会触发。


  }5 e  u0 v( U: M1 j$ H4 |

3、用法 faults 发生的场合可以是:执行了未定义的指令;无效的中断返回(LR 中包含了无效/错误的值);使用多重加载/存储指令时,地址没有对齐;除数为零;任何未对齐的访问等等


9 h0 E! [( t2 w7 u. s- s

3、重点讲的就是HardFault_Handler,如果以上3个 fault 的服务例程无法执行,它们就会成为HardFault_Handler。在NVIC 中有一个硬 fault 状态寄存器(HFSR),它指出产生硬 fault 的原因。


6 d$ |5 [4 p' C/ }

具体调试流程:

3.1首先在将程序进入debug进入调试模式,在void HardFault_Handler(void)函数中打1个断点;如下,以STM32为例,程序在stm32f10x_it.c中;

void HardFault_Handler(void)

{

    /* Go to infinite loop when Hard Fault exception occurs */

    while (1) {

        //SoftReset();

    }

}


6 K9 t1 y8 C3 ~; b6 t: i

3.2等到软件运行到此处,查看(R14)LR寄存器的值;如果看到LR寄存器中的值是0xFFFFFFF9,就去看MSP的地址;如果看到LR寄存器中的值是0xFFFFFFFD,就去看PSP的地址;


( k; u( _( B2 e2 [  p1 e

3.3然后在Keil菜单栏“View”——“Memory Windows”——“Memory”,在“Address”地址栏中输入MSP或PSP的值,然后找到对应的地址。地址是以0x08开头的int位数,一般是第六个int数据;

3.4再到Keil菜单栏点击“View”——“Disassembly Window”,在“Disassembly”窗口中右击,选择“Show Disassemblyat Address...”。在弹出框“Show Code atAdress”的地址框中输入地址对应的code地址就可以转到对应代码的位置,通过检查分析或者改写代码前后的语句就可以判断问题的主要原因。

  |/ f! h" f* A! R6 a# o% u! y- \3 Y

3.5 另外还有通过在调试状态下,进入HardFault断点后,通过菜单栏Peripherals >Core Peripherals >FaultReports打开异常发生的报告,然后通过Call Stack查看发生异常的原因,也是可以的。

4 X1 W' q; W: m+ d8 V

3.6 如果不是函数语句的问题,可以通过查看编译后的.map的文件中heap与STACK所占用的地址,通过Memory内存窗口来观察堆栈的使用情况,来看是不是堆栈内存有溢出导致的。

    __heap_base                              0x2000d020   Data           0  startup_stm32f10x_hd.o(HEAP)

    __heap_limit                             0x20016420   Data           0  startup_stm32f10x_hd.o(HEAP)

    __initial_sp                             0x20017420   Data           0  startup_stm32f10x_hd.o(STACK)


* [& W3 z* ^' p8 @5 y4 A1 A* F

分析说明:由于CM3在进入异常服务程序后,LR的值被自动更新为特殊的EXC_RETURN(附图),按照文件说明这是一个高28位全为1的值,只有[3:0]的值有特殊含义,如果主程序在线程模式下运行,并且在使用MSP时被中断,则在服务例程中LR=0xFFFF_FFF9(主程序被打断前的LR已被自动入栈)。如果主程序在线程模式下运行,并且在使用PSP时被中断,则在服务例程中LR=0xFFFF_FFFD(主程序被打断前的LR已被自动入栈)。

$ e) ~7 G/ n  Y: r

总结:根据个人的一些经验,大部分时候是由于以下两种情况导致,

1内存溢出或则访问越界,比方说数组的访问。

2堆栈分配问题,堆栈不够导致堆栈溢出。

根本解决问题肯定是优化代码,但是为了保险起见,可以在HardFault_Handler程序中加入复位命令来保障设备的持续运行,

0 b/ V! \; T/ ~3 b; l

//系统复位

void SoftReset(void)

{

#if !IS_DEBUG

    __set_FAULTMASK(1);

    NVIC_SystemReset();

#endif

}


! x2 i+ z+ [! j! |- G

/**************************************************************/

CM3指南截图

堆栈大小分配:


7 ~$ W- `, \, h# I& C

作者:woai32lala


' A7 x* [9 K3 `$ j
收藏 1 评论0 发布时间:2022-12-8 16:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版