当前位置: 首页 > news >正文

STM32 Hardfault异常调试-笔记

STM32 Hardfault异常调试-笔记

  • 一、基础寄存器与栈结构
    • 1.1 核心寄存器作用
    • 1.2 压栈基础知识
    • 1.3 PC指针是什么?
    • 1.3 SP指针是什么?
    • 1.4实际演练

在嵌入式开发中,Hardfault异常是常见的问题之一。当程序访问非法地址或执行非法指令时,系统会触发Hardfault中断。此时,如何通过栈地址快速定位问题根源是调试的关键,如何通过栈的地址找到我们的问题发生的地方。
在这里插入图片描述

一、基础寄存器与栈结构

1.1 核心寄存器作用

在这里插入图片描述
R0-R12:通用寄存器,用于存储临时数据和运算结果。
R13(SP):栈指针(Stack Pointer),指向当前栈顶。STM32有主栈(MSP)和进程栈(PSP)两种模式。
R14(LR):链接寄存器(Link Register),保存函数调用返回地址。(它保存的是什么呢?保存的是程序下一个要运行的地址,就是下一条要运行的指令。)
PC:程序计数器(Program Counter),指向当前执行的指令地址。

1.2 压栈基础知识

在这里插入图片描述
假如说我们的函数,我们的func_A如果调用了func_B。如果调用了func_B那么func_A在调用它之前,会把自己要运行的下一条这条return的这个地址放到R14里面。
它调用完func_B以后,R14指向func_A的return处,让它继续运行。这个就是我们的基础知识。


1.3 PC指针是什么?

PC指向的是我们当前程序所运行到的地址,PC指令装填我们当前现在即将要运行的这条指令。
在这里插入图片描述


1.3 SP指针是什么?

SP就是我们的栈顶指针,它指向哪里呢?
在这里插入图片描述
从上面的图中可以看出栈是从下依次往上,地址逐渐减小,栈指针就指向的就是这个栈顶的


1.4实际演练

在这里插入图片描述
调试一步一步走这个时候它PC指针一直在动,这个栈指针没动。我们再走一步。到达调用func_A函数。

看他把这里的0X1234678装载到R4寄存器中,R4当中这个时候它func_A,主要func_A它即将要进行一个调用。
在这里插入图片描述


这个时候你看这里的这是他的指令汇编指令,他现在知道了这一条,这一条是什么?把0XA123装到R1里面
在这里插入图片描述


0XA123在这里,比如说他先去把他在调用这个函数的时候,他先去把这个函数的第二个参数,他先装进了自己的R1寄存器。
在这里插入图片描述

#0xA123装进了我们的R1寄存器,0x12345678这里的R4值就把我们这里的R4就放到了R0。
在这里插入图片描述R4就放到了R0。

为什么把R4放?因为R4之前在"uint32_t var_main.0x12345678;“载入变量了,他再作为参数传进到"func_A”。在这里插入图片描述


在这里插入图片描述


在这里插入图片描述
R0是什么呢?R0就是它的另一个参数,所以它在调用这个函数的时候,会预先把这里传入的两个参数压到R0和R1寄存器


调试下一步进入函数
在这里插入图片描述
跳转进来,可以看到汇编的进行了一个压栈,“PUSH”。

方便我运行完function a以后,我还能知道我退出function a以后,我是要运行这一段指令“在这里插入图片描述

现在看下R13(SP)寄存器 地址为“在这里插入图片描述”。
往下走单步调试,R13(SP)寄存器变成 在这里插入图片描述。它是不是一次前进了16个字节


打开一个Memory的窗口。输入地址0x200005A8
在这里插入图片描述
这里的地址从大依次变小,里面存了一个数“12345678”。这个地方好像就把之前存在这里R4的这个是不是压进来了。


在这里插入图片描述

把R4到R6都给压进来了,然后还把LR给压进来了。

那么LR它压到哪里了呢?LR是什么?
LR其实就指向的是我们调用function a的,下一句话在这里插入图片描述

我们在往Memory的窗口看,他压栈的过程当中是先压这个LR,栈从右边往左写,地址逐渐减小。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

所以LR就是0x08001653。

如果我想看这个地址是哪条指令,我们怎么办呢?
在汇编窗随便点击右键,选择“show disassembly at address”

在这里插入图片描述
在这里插入图片描述
跳转到0x08001653处,但是呢?显示不出来是为什么呢?
因为LR
如果你想跳到准确的下一个执行的地址,汇编不会完整的显示。但是可以推断出来

在这里插入图片描述
然后我们再往下调用,调试进行下一步,跳到function b函数处了
在这里插入图片描述
在这里插入图片描述
进行压栈 。R13的地址变成“0x20000598”。原来的是“0x200005A8”。对比正好又压进了16字节
在这里插入图片描述
最后就是它的LR寄存器 “0x08001601”。
在这里插入图片描述跳转
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上下滚动一下鼠标发现就在这里。那是不是这一句话就是我们function a调用完function b会回到这里

这样就实现了我们通过栈来追溯回收信息

在这里插入图片描述
以这个为例子产生have fault的过程。

“0xA0000000”在STM3F4当中,我们访问的这里这个地址,你看我们让它指向了一个错误的地址。
在这里插入图片描述

它是不存在的,即使存在也是系统保留。如果它指向这里,直接会造成那个地址非法访问。

假如当我们不知道在哪个位置发生错误的时候,程序全速运行。程序突然进入have fault

在这里插入图片描述

通过LR寄存器,我们来反追查到是哪个指令调用完以后就产生了have fault。

但我在这一看这个LR寄存器是0xFFFFFFE9,它不像是一个有意义的地址

在这里插入图片描述
在这里插入图片描述
通过地址0xFFFFFFE9 跳转到这里,也是have fault函数的位置处

遇到这种情况我们该怎么办?这就需要用到要使用栈指针

现在我们看R13(SP)地址为0x20000548,在Memory的窗口处该地址会压入四个字就是16个字节

在这里插入图片描述
这个地方好像存在了一个地址,地址都是80开头的。

所以在这种进入错误的时候,进入这种have fault的时候,它不会给你压成压完整的栈,它这个地方会给你强行有一个主栈切换到从栈

按照我这个方法找,就从你最顶的站,最顶上面的站指针,你一直往后找,找到这里有一个疑似你地址段
在这里插入图片描述跳转
在这里插入图片描述
如果我能从have fault里面退出来,程序能从have fault里面退出来,应该是运下一条就要运行这个指令“while”。那我上一条指令是不是就这个指令往上找就行了,最终找到在这里插入图片描述

对比下地址0X08001611与0x08001608 是不是很靠近,疑似你地址段的, 所以我们完全有理由怀疑到这个位置,就怀疑这里已经出错了

http://www.dtcms.com/a/411845.html

相关文章:

  • 网站做的好坏主要看公司做网站好吗
  • 太原找工作网站网站怎么做显得简洁美观
  • 凤岗镇仿做网站做网站哪个语言好
  • Kanass入门到实战(4) - 如何快速导入Jira、Mantis数据
  • JavaScript 事件冒泡与事件捕获
  • 外贸网站源码怎么建wordpress使用百度分享插件下载
  • C语言基础【26】:结构体2
  • 项目计划书模板10篇win7优化大师
  • SQL Server提示:安装程序无法与下载服务器联系。请提供 Microsoft机器学习服务器安装文件的位置。。。。
  • 无人机表演行业二手设备市场与性价比分析
  • 快速建站公司怎么样wordpress读取父分类列表
  • 黄埔网站建设厦门网站排名
  • 好的ftp网站宁夏住房和城乡建设官方网站
  • Redis 7.0 新特性深度解读:迈向生产级的新纪元
  • wordpress网站实例网站怎么建设后台
  • JVM内存分配
  • 兴化网站建设网站开发用什么语言比较好
  • 四川网站建设找珊瑚云公司装修通知告示怎么写
  • 从 inode 角度深入分析软硬链接的内核实现与设计
  • 游戏开发中的状态管理与定时器
  • 上海网站开发外包分类信息网站
  • Apifox+DeepSeek接口测试实战
  • 7、幽络源微服务项目实战:SpringSecurity用户权限查询与校验的配置和测试
  • 海丰县建设局官方网站南县网站制作
  • 重庆企业建站模板佛山全网营销推广
  • 基于C#的停车场管理系统实现
  • html怎么做网站wordpress还能用
  • 有域名和空间怎么做网站简单网站设计网站
  • 操作系统之初识Linux
  • Transformers Dataset 完全指南:从基础到高级应用