在做CORTEX-M3单片机开发的时候,如STM32,可能会遇到设备跑着跑着程序死机的情况,往往调试起来很多时候发现是程序进入HardFault_Handler系统异常,根据相关资料和M3权威指南是可以通过调试查找出程序的问题点和解决问题的。 , Y( H0 _* L6 C. c. D# p* z8 V根据CM3指南中的 Faults 可分为4类:总线 faults、存储器管理 faults、用法 faults、硬 fault; 以下是具体说明: 1、总线 Faults是当 AHB 接口上正在传送数据时,如果回复了一个错误信号,则会产生总线 faults,CM3有一个名为“总线 fault 状态寄存器”(BFSR)的。通过它,总线 fault 服务程序可以确定产生 fault 的场合是在数据访问时、在取指时、还是在中断的堆栈操作时。这个不展开细说 2、存储器管理faults多与MPU有关,其诱因常常是某次访问触犯了MPU设置的保护策略。另外,某些非法访问,例如,在不可执行的存储器区域试图取指,也会触发一个 MemManagefault,而且即使没有 MPU 也会触发。 3、用法 faults 发生的场合可以是:执行了未定义的指令;无效的中断返回(LR 中包含了无效/错误的值);使用多重加载/存储指令时,地址没有对齐;除数为零;任何未对齐的访问等等 3、重点讲的就是HardFault_Handler,如果以上3个 fault 的服务例程无法执行,它们就会成为HardFault_Handler。在NVIC 中有一个硬 fault 状态寄存器(HFSR),它指出产生硬 fault 的原因。 具体调试流程: 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(); } } 3.2等到软件运行到此处,查看(R14)LR寄存器的值;如果看到LR寄存器中的值是0xFFFFFFF9,就去看MSP的地址;如果看到LR寄存器中的值是0xFFFFFFFD,就去看PSP的地址; 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 Y3.5 另外还有通过在调试状态下,进入HardFault断点后,通过菜单栏Peripherals >Core Peripherals >FaultReports打开异常发生的报告,然后通过Call Stack查看发生异常的原因,也是可以的。 4 X1 W' q; W: m+ d8 V3.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) 分析说明:由于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 } /**************************************************************/ CM3指南截图 堆栈大小分配:
作者:woai32lala |
为什么要先开启STM32外设时钟?
【STM32MP157】从ST官方例程中分析RPMsg-TTY/SDB核间通信的使用方法
【经验分享】STM32实例-RTC实时时钟实验④-获取RTC时间函数与中断服务函数
STM32 以太网 MAC Loopback 的实现
STM32功能安全设计包,助力产品功能安全认证
基于STM32启动过程startup_xxxx.s文件经验分享
HRTIM 指南
ST 微控制器电磁兼容性 (EMC) 设计指南
适用于STM32微控制器的ΣΔ数字接口入门
STM32+FPGA FSMC实验