STM32F103错误异常和错误处理(HardFault)

这两天在程序开发时,遇到了程序卡死的现象,所以,就怀疑是发生了HardFault,从而导致程序进入了HardFault的死循环。

参考的是这篇文章

stm32 HardFault错误调试记录_fault reports_苏提春晓_的博客-CSDN博客

不过这篇文章里有的地方没讲清楚,所以这里先对我自己的实践步骤,做一个总结,并附上额外说明。

keil排查步骤(具体细节后面再解释):

1、打开debug模式


2、打开STM32标准库工程的文件stm32f10x_it.c

找到HardFault的中断处理函数,并打一个断点

3、调试模式下,点击全速运行

运行程序,如果确实发生了HaultFault,就会跳到刚才打的断点处

4、点击Keil里的菜单Peripherals-Core Peripherals-Fault Reports(这一步是可选的)

此时就能看到刚才发生的错误报告

注意,这里打上勾的就是发生的错误类型。

注意:如果关闭该报告弹窗,下一次打开就不是当前的报告了,所以暂时不要关闭,或者截图先保存下来。

因为所有的错误都会上访成HardFault,所以HardFaults的FORCED对钩被打上了,属于强制的。

这里其实真正的错误类型是Bus Faults的IMPRECISERR。

这里可能看不太明白,但是暂且不管。

总之,要明白的是,确实发生了HardFault。

为什么上面说这个步骤是可选的呢?因为其实没有这个报告,看到程序确实进入了HardFault中断,也能做出这一判断。这里的报告只是尽可能告诉我们具体的错误类型。

接下来就是关键,要找到HardFault是从代码的什么地方进入的,因为程序的错误就存在那附近,可能是数组越界,也有可能是内存溢出等等。总之,要先找到错误的地方,然后才好排查。

5、在寄存器那个窗口找到LR寄存器的值

看该寄存器的第三位,可以看到最低位是0x9,也就是二进制的1001,从最低位开始,第三位就是0,根据这一位判断当前使用的堆栈是MSP还是PSP,具体概念先不用管

我的情况是使用的MSP

另外,还可以看到,SP寄存器的值和MSP的值是一致的,也可以说明使用的是MSP

实际上,裸机开发全程使用的只有MSP.

6、还是刚才的寄存器窗口,展开Banked,找到MSP的值

7、打开内存查看窗口

输入刚才的MSP的值,即0x20002518

注意,最好在该窗口右键切换显示方式(我这里已经切换过了)

这样才刚好是显示4个字节,即32位地址,方便查看。

8、接下来要找到发生HardFault之前的程序地址,也就是哪里发生的HardFault

从刚才显示的MSP地址处,往后加6个地址处,就是出错的地方

先不要问为什么要加6,具体可参考上面给的链接,或者《ARM Cortex-M3 Cortex-M4 权威指南》

这样,我们就找到了出错的地址08000E25

双击复制该地址

9、回到汇编窗口,右键点击跳转该地址处

粘贴刚才的地址08000E25,注意,粘贴后不要直接Go To,必须得加上个0x,要不就不对了,也就是0x08000E25

点击Go To,会同时跳到对应的汇编和C语言处 

到此,就可以知道,是这863行代码处进入了HardFault,所以,这行程序是有问题的,或者这行程序的附近是有问题的.

这里涉及到了数组的索引,猜测极有可能是发生了数组的越界问题。

10、具体得排查出错的程序,优化BUG即可。

OK排查步骤结束。

接下来好好研究下STM32的错误异常相关内容。

错误异常和错误处理

内容均参考《ARM Cortex-M3 Cortex-M4 权威指南》以及网络。

此处仅记录重点内容

错误处理函数中,也是可以进行业务操作的。

上面只是介绍了异常处理的流程,还有一些令人不太明白的地方,接下来进行补充。

要想理解上面步骤的所以然,至少需要阅读《ARM Cortex-M3 Cortex-M4 权威指南》第4章寄存器部分、第8章简介部分和第12章的几乎所有内容。

第4章:架构

第8章:深入了解异常处理

第12章:错误异常和错误处理

另外,要会用Keil的调试工具。

首先,认识错误报告

 

错误报告中,当发生对应异常后,就会被自动打上勾,表示该异常类型标志位置位了,也就是说,确实发生了对应的异常。

从上到下,分为存储器管理异常、总线异常、使用异常、硬错误、调试错误、还有辅助错误。

对于每一个错误:

Address行SCB->xFAR是错误地址寄存器;

Status行SCB->xFSR是错误状态寄存器,数值就表示这些寄存器的数值,对应了下面的那些选项,打钩的是1,没打钩的就是0;

这些寄存器都可以在上面报告里找到对应的地方。 

其他列出来的都是对应的错误状态标志位。

存储器管理异常

总线错误

上面的定位步骤中,就是发生了不精确的总线错误。

其实,按上面的方式找到的只是不准确的地址。

为了得到准确的错误地址,需要禁止写缓冲。

 

如何在C中禁止写缓冲呢?后面再优化说明。

使用错误

HardFault

 

本例中,FORCED被打钩,也就是置位了,是由于总线错误引起的。 

剩下的两种错误类型可以不必关注。 

LR的位2表示什么?

 

LR寄存器的当前值是什么意思?

阅读下方红框部分文字

 

同时,也能看出为什么要看LR的位2来判断MSP还是PSP

 

 

为什么是往后移动6个位置? 


这里要注意ARM使用的是满减栈。

综合可知

异常处理时,可以根据当前MSP的值获取到返回地址。

注意,往后+0x18(24),也就是往后移动24个字节,每个地址4个字节,也就是往后移动6个地址位置,得到的就是PC值,即返回地址。

注意,这里为什么PC就是返回地址?而不是看LR呢?

上面有讲,因为异常处理时,LR用来存放EXC_RETURN,此时的PC原本是要存在LR中的,但是LR被占用了,就只能压栈保存。

那为什么不取压栈的LR?而是看PC。

因为此时PC就是原来的LR,而此时压栈的LR,是调用该函数的后一个指令地址,不是发生异常处的地址。

举例说明:

此时的压栈LR其实是C指令的地址,而我们要的是I处的地址,也就是此时压栈的PC值。

还有个问题,就是此时得到的PC值其实并不准,需要禁止缓冲后再调试一次。

优化调试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/55811.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIP 三层交换机

一、实现VLAN间通信 在传统的交换机组网中,默认所有网络都处于同一个广播域,带来了许多问题,VLAN技术的提出,满足了二层组网隔离广播域需求,使得属于不同的VLAN间网络无法通信,但不同VLAN之间又存在着互相…

Robot Framweork之UI自动化测试---AutoItLibrary封装上传文件

在实现UI自动化的过程中,遇到了文件上传的场景,涉及到Windows系统窗口,这就需要用到AutoItLibrary库。 一、文件上传流程 1、点击上传 2、输入文件路径,点击确定 二、上传功能自动化脚本 一)点击上传 直接使用click e…

C++的vector

文章目录 迭代器失效问题构造函数赋值运算符begin() end()size() capacity() empty()reserve()operator[ ]insert()erase()resize() 迭代器失效问题 迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间 1.扩容导致迭代器失效问题 在对…

uniapp h5支付宝支付后端返回Form表单,前端如何处理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1.调取接口拿到后端返回的form表单 前言 uniapp h5 支付宝支付,后端返回一串form表单,前端如何拿到支付串并且调用支付 1.调取接口拿到…

STM32 4G学习

硬件连接 ATK-IDM750C模块可直接与正点原子 MiniSTM32F103开发板板载的ATK模块接口(ATK-MODULE)进行连接。 功能说明 ATK-IDM750C是正点原子(ALIENTEK)团队开发的一款高性能4G Cat1 DTU产品,支持移动4G、联通4G和…

Leetcode | 42.接雨水 Trapping Rain Water

Leetcode | 42.接雨水 Trapping Rain Water 文章目录 Leetcode | 42.接雨水 Trapping Rain Water题目Solution 1:动态规划Solution 2: 单调栈Solution 3 : 双指针最快的方法代码 My SolutionReference>>>>> 欢迎关注公众号【三戒纪元】 <<<<< 题…

MySQL刷题遇到的盲点(五)窗口函数

窗口函数 语法&#xff1a; <窗口函数> over (partition by <用于分组的列名>order by <用于排序的列名>) partition by&#xff1a;用来对表分组&#xff08; partition 子句可以省略&#xff0c;省略就是不指定分组&#xff09; order by&#xff1a;是…

在Volo.Abp微服务中使用SignalR

假设需要通过SignalR发送消息通知&#xff0c;并在前端接收消息通知的功能 创建SignalR服务 在项目中引用 abp add-package Volo.Abp.AspNetCore.SignalR在Module文件中添加对模块依赖 [DependsOn(...typeof(AbpAspNetCoreSignalRModule))] public class IdentityApplicati…

分页Demo

目录 一、分页对象封装 分页数据对象 分页查询实体类 实体类用到的utils ServiceException StringUtils SqlUtil BaseMapperPlus,> BeanCopyUtils 二、示例 controller service dao 一、分页对象封装 分页数据对象 import cn.hutool.http.HttpStatus; import com.…

Nios初体验之——Hello world!

文章目录 前言一、系统设计1、系统模块框图2、系统涉及到的模块1、时钟2、nios2_qsys3、片内存储&#xff08;onchip_rom、onchip_ram&#xff09;4、串行通信&#xff08;jtag_uart&#xff09;5、System ID&#xff08;sysid_qsys&#xff09; 二、硬件设计1、创建Qsys2、重命…

uni-app——下拉框多选

一、组件components/my-selectCheckbox.vue <template><view class"uni-stat__select"><span v-if"label" class"uni-label-text">{{label &#xff1a;}}</span><view class"uni-stat-box" :class"…

Vue3和TypeScript项目-移动端兼容

1 全局安装typescript 2 检测安装成功 3 写的是ts代码&#xff0c;但是最后一定要变成js代码&#xff0c;才能在浏览器使用 这样就会多一个js文件 3 ts语法 数组语法 对象语法 安装vue3项目 成功后进入app。安装依赖。因为我们用的是脚手架&#xff0c;要引入东西的时候不需要…