[STM32]KEIL调试程序进入HardFault_Handler异常处理总结

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

根据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地址就可以转到对应代码的位置,通过检查分析或者改写代码前后的语句就可以判断问题的主要原因。

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

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)

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

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

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

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

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

//系统复位

void SoftReset(void)

{

#if !IS_DEBUG

    __set_FAULTMASK(1);

    NVIC_SystemReset();

#endif

}

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

CM3指南截图

堆栈大小分配:

---------------------
作者:forgot
链接:https://bbs.21ic.com/icview-3265796-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。 

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
单片机出现硬件异常(Hard Fault)时,程序会跳转到一个叫做HardFault_Handler异常处理函数中。这个函数的作用是处理硬件异常并采取相应的措施。在NVIC中有一个硬件异常状态寄存器(HFSR),它记录了产生硬件异常的原因。 为了处理硬件异常,有时候我们会设置一个死循环来防止程序继续执行导致更严重的问题。这样当出现硬件异常时,程序就会进入一个无限循环,不会继续执行其他指令。 在STM32单片机中,导致HardFault_Handler故障的主要原因有两个方面。第一个是内存溢出或访问越界,这时需要检查自己编写的程序,规范代码并逐步排查问题。第二个原因是堆栈溢出,可以通过增加堆栈的大小来解决这个问题。 因此,当单片机进入HardFault_Handler时,说明发生了硬件异常,程序会跳转到这个异常处理函数中进行相应的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [[STM32]KEIL调试程序进入HardFault_Handler异常处理总结](https://blog.csdn.net/ic2121/article/details/128169297)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [HardFault_Handler问题查找方法](https://download.csdn.net/download/weixin_38680957/12684236)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值