STM32 Cortex-M3 HardFault异常定位

目录

1 Fault类异常

1.1 总线Fault

1.2 存储器管理Fault

1.3 用法Fault

1.4 硬件Fault

2 Core Registers

2.1 R14(LR)寄存器

2.2 R15(PC)寄存器

3 HardFault处理原理

4 真实项目调试


1 Fault类异常

Cortex-M3的Fault异常分为:

  • 总线Fault
  • 存储器管理Fault
  • 用法Fault
  • 硬件Fault

1.1 总线Fault

这里引用《Cortex-M3权威指南》说法:

可以通过地址0xe000ed29查看具体是什么异常。

1.2 存储器管理Fault

这里引用《Cortex-M3权威指南》说法:

可以通过地址0xe000ed28查看具体是什么异常。

1.3 用法Fault

这里引用《Cortex-M3权威指南》说法:

可以通过地址0xe000ed2a查看具体是什么异常。

1.4 硬件Fault

硬件Fault也就是我们所说的HardFault,只要产生了总线、存储器管理、用法Fault其中之一,就会上报给硬件Fault,所以,最终的Falut我们都可以通过HardFault查看。

可以通过地址0xe000ed2c查看具体是什么异常。

2 Core Registers

讲了几种Fault之后,我们需要了解一些基本的内核寄存器,后续查找Fault提供帮助。

2.1 R14(LR)寄存器

R14(LR):连接寄存器,当呼叫一个子程序时,由R14存储返回地址。

当只有一级子程序的时候:把返回地址直接存储在R14寄存器中,这样就无需访问内存(堆栈内存,进栈和出栈),从而提高子程序的调用效率;

当子程序多于一级的时候:前一级存储在R14的返回地址值压到堆栈里,保留最后一级的返回地址在R14里面;

注意:在RAM上编程时,应尽量只使用寄存器保存中间结果,迫不得已时才访问内存。

  1. 如图所示,当程序执行到0x08001224地址的时候,CM3内核会把0x08001228存到LR中(实际存入的是0x08001229,因为是Thumb-2指令),并在进入子程序之后把LR压栈(因为子程序里面存在子程序,如果子程序不存在子程序,就不会压栈);
  2. 当程序执行到0x08001400的时候,由于LR已经压栈,所以LR的值就会重新存储0x08001404,当执行完NVIC_Init程序之后,BL LR(LR的值为0x08001404)就会无条件跳转到0x08001404处继续执行(此时需要把LR出栈,出栈的值是0x08001228);
  3. 最后执行完NVIC_Configuration之后,就会执行BL LR返回到0x08001228处继续执行代码。

2.2 R15(PC)寄存器

R15:程序计数寄存器,指向下一次要执行的程序地址。必须保证PC的数值是奇数,用于表示在Thumb状态下执行。

当中断来临的时候,R0-R3、R12、LR、PC、xPRS寄存器会自动的压栈,如果中断中使用了其它寄存器,在进入中断之前,也会对使用到的寄存器自动的压栈。

3 HardFault处理原理

如果程序进入hardfault,那么首先找到SP指针的值,然后根据SP指针的值,找出对应地址所存放的寄存器(CM0和CM3目前这些地址存放的寄存器相同)。

然后主要是定位LR和PC的值,LR指的是发生异常前本来要执行的下一条指令的地址,但是由于异常的产生,不会执行这条指令(只需要在这个地址之前打一个断点,根据条件来找寻出错的点),PC是发生异常前紧接着执行的地址。

4 真实项目调试

真实项目中,我们大多不必关心Fault状态寄存器的值,因为只要我们定位到错误的代码的位置,我们大致都能知道是什么错误了。

1. 首先工程跑到hardfault了;

2. 通过SP指针找到PC的值为0x08000046,LR的值为0x08001DEB,可知程序在执行了0x08000046指令之后就进入了HardFault,此时程序不会执行0x08001DEB这条指令。如果程序没有进入HardFault,那么子函数就会返回0x08001DEB这条指令。

3. 找到LR和PC指针指向地址的程序位置,可知道PC指针的值是中断向量表,这里又没用开PVD中断,所以断定是这里出错了;

4. 在LR地址的前一条指令的位置打上断点,确定程序在这里执行完之后,就出错了;

5. 通过发现是(*pEpInt_IN[EPindex-1])();函数的位置出错,所以把watch窗口打开,查看这个函数的地址和返回值,发现返回值是0x08000046,所以这个值出错了,因为返回值成功是0,失败不可能是0x08000046(从调试信息可知,此函数的地址是0x20000018,所以返回值写入的是0x20000018);

6. 增加条件断点,当0x20000018地址的值被修改了之后产生断点,捕捉哪里把0x20000018的值修改为了0x08000046,通过断点可知,在下面代码的时候导致了hardfault,进一步得知是数组溢出导致。

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

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

相关文章

SQL 行转列

MySQL mysql换行使用\n SELECTpic_business_id,GROUP_CONCAT( \n类型, :, pic_med_type_name, ,金额, pic_cost ) FROMsl_patient_item_cost GROUP BYpic_business_id2. Oracle oracle换行使用CHR( 10 ) SELECTMEDICAL_RECORD_ID,IN_NUMBER,NAME,REPLACE( wmsys.wm_concat …

AI大模型-启航

文章目录 什么是大模型?(大体现在参数量巨大)大模型将会改变那些行业(大模型有哪些作用?)如何搞数据训练模型?LangChain带来的技术变革LangChain架构 什么是大模型?(大体…

云畅科技携手飞腾打造智慧园区信创低代码综合解决方案

01 方案概述 随着国家对信创产业的日益重视与大力支持,信创行业的产业化进程正在不断加快。智慧园区,作为信创产业蓬勃发展的核心载体与战略平台,正日益凸显其重要性。与此同时,在政策引导和市场需求的双重驱动下,智慧…

函数重载和运算符重载

函数重载和运算符重载 一、函数重载二、运算符重载&#xff08;一&#xff09;运算符重载&#xff08;二&#xff09;运算符重载&#xff08;三&#xff09;运算符重载&#xff08;前置和后置&#xff09;&#xff08;四&#xff09;、运算符重载&#xff08;五&#xff09;<…

【玩转408数据结构】线性表——双链表、循环链表和静态链表(线性表的链式表示 下)

知识回顾 在前面的学习中&#xff0c;我们已经了解到了链表&#xff08;线性表的链式存储&#xff09;的一些基本特点&#xff0c;并且深入的研究探讨了单链表的一些特性&#xff0c;我们知道&#xff0c;单链表在实现插入删除上&#xff0c;是要比顺序表方便的&#xff0c;但是…

为什么推荐使用ref而不是reactive

为什么推荐使用ref而不是reactive 局限性问题&#xff1a; reactive本身存在一些局限性&#xff0c;可能会在开发过程中引发一些问题。这需要额外的注意力和处理&#xff0c;否则可能对开发造成麻烦。数据类型限制&#xff1a; reactive声明的数据类型仅限于对象&#xff0c;而…

javaweb学习(day05-TomCat)

一、介绍 1 官方文档 地址: https://tomcat.apache.org/tomcat-8.0-doc/ 2 WEB 开发介绍 2.1 WEB 在英语中 web 表示网/网络资源(页面,图片,css,js)意思&#xff0c;它用于表示 WEB 服务器(主机)供浏览器访问的资源 2.2 Web 资源 WEB 服务器 ( 主机 ) 上供外界访问的 …

Spring八股 常见面试题

什么是Spring Bean 简单来说&#xff0c;Bean 代指的就是那些被 IoC 容器所管理的对象。我们需要告诉 IoC 容器帮助我们管理哪些对象&#xff0c;这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。 将一个类声明为 Bean 的注解有哪些? Com…

Docker Compose实战指南:让容器管理变得简单而强大

&#x1f9e8;个人主页&#xff1a;明明跟你说过 &#x1f6a9;欢迎&#x1f397;️点赞&#x1f638;关注❤️分享 &#x1f638;希望本文能够对您有所帮助&#xff0c;如果本文有不足之处&#xff0c;或您有更好的建议、见解&#xff0c;欢迎在评论区留下您的看法&#xff0c…

LIS(最长上升子序列, 合唱队形)

最长上升子序列 直接使用动态规划&#xff1a; 这个题目的关键就是在于我们选定一个数&#xff0c;然后利用这个数作为标准和这个数之前的所有数进行比较&#xff0c;如果比前面某一个数要大&#xff0c;那么就需要将这数自己本身的现存的最长长度与比较出来的数的最长加一&am…

Linux学习-C语言-运算符

目录 算术运算符&#xff1a; - * /:不能除0 %:不能对浮点数操作 &#xff1a;自增与运算符 i&#xff1a;先用再加 i:先加再用 --&#xff1a;自减运算符 常量&#xff0c;表达式不可以&#xff0c;--&#xff0c;变量可以 赋值运算符 三目运算符 逗号表达式 size…

OD(13)之Mermaid饼图和象限图

OD(13)之Mermaid饼图和象限图使用详解 Author: Once Day Date: 2024年2月29日 漫漫长路才刚刚开始… 全系列文章可参考专栏: Mermaid使用指南_Once_day的博客-CSDN博客 参考文章: 关于 Mermaid | Mermaid 中文网 (nodejs.cn)Mermaid | Diagramming and charting tool‍‌⁡…