STM32单片机编程调试常见问题(一) HardFault_Handler故障分析与解决

news2024/11/17 7:41:54

文章目录

    • 一.概要
    • 二.什么是Hard fault
    • 三.Hard fault 产生的原因分析
    • 四.制作一个Hard fault程序并定位出问题原因
      • 1.查看堆栈指针SP的地址以及内容
      • 2.找到Return address地址
      • 3.查看汇编界面
      • 4.输入Return address地址,查找到问题代码
    • 小结

一.概要

在嵌入式开发中,偶尔会遇到单片机HardFault_Handler死机的异常,单片机无法正常运行,出现Hardfault错误时,问题比较难定位的原因在于此时代码无法像正常运行时一样,所以显得无从下手。通常情况下我们都是通过在某个区间打断点,然后通过单步执行去逐步缩小“包围圈”去找到产生Hard Fault的代码位置,接着再去推敲、猜测问题的原因。对于不是很复杂的程序,这种方法是有效的,但是当用户代码量进一步增大,再用这种单步+断点去逐步缩小包围圈的方式就很难查到问题点,效率也很低。尤其是在有操作系统的应用中,很多代码的跳转是由操作系统调度的,不是严格的顺序执行,所以很难依靠缩小包围圈的方式去有效找到问题产生的点,进一步增加了定位到Hard Fault触发原因的难度。
本文就介绍了出现HardFault_Handler出现的原因,以及发现异常之后,问题的排查分析与解决方法。

在这里插入图片描述

二.什么是Hard fault

对于Cortex-M内核,架构采用错误异常的机制来检测问题,当内核检测到一个错误时,异常中断会被触发,并且内核会跳转到相应的异常中断处理函数执行。
错误异常的中断分为以下四种:
HardFault
MemManage
BusFault
UsageFault
其中hardfault为最常见的错误类型,并且在没有开启其他异常处理的情况下,默认进入hardfault异常中断处理函数。
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 /
/
USER CODE END HardFault_IRQn 0 /
while (1)
{
/
USER CODE BEGIN W1_HardFault_IRQn 0 /
/
USER CODE END W1_HardFault_IRQn 0 */
}
}

三.Hard fault 产生的原因分析

硬件方面常见原因:
1.电源设计有错误,造成器件供电不稳;
2.电源质量不好,文波,噪声过大;
3.器件接地不良;
4.对于带有Vcap引脚的器件,管脚处理不当;
5.电路中有强干扰源,对器件造成干扰;

软件方面常见原因:
1.使用了空指针;
2.对地址偏移量的计算有误;
3.数组越界导致程序出错;
4.动态内存使用不当,导致访问了已释放的内存地址;
5.通过地址访问了已失效的局部变量;
一般因为硬件造成Hard Fault错误的可能性较低,大多数都是软件原因造成的。所以遇到硬件中断错误,基本就是通过软件来排查。

由于异常发生时,内核将R0~R3、R12、Returnaddress、PSR寄存器依次入栈,其中Return address即为发生异常前PC将要执行的下一条指令地址,所以我们可以通过找到Return address,从而排查出产生异常的指令。

四.制作一个Hard fault程序并定位出问题原因

硬件准备:
STLINK接STM32F103C8T6小系统板,STLINK接电脑USB口。
在这里插入图片描述
程序准备:
在普通的GPIO例程中修改代码

uint32_t Data2=100,Data3;
uint8_t Temp[100],*p;
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	HAL_Init();
	
	/* USER CODE BEGIN Init */
	
	/* USER CODE END Init */
	
	/* Configure the system clock */
	SystemClock_Config();
	
	/* USER CODE BEGIN SysInit */
	
	/* USER CODE END SysInit */
	
	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	/* USER CODE BEGIN 2 */
	Data3=Data2*100;
	memset(Temp,0x55,100);
	Data=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);
	Data3=100*(Data2-1);
	if(Data3>10)
	{
	Data=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);	
	
	}
	memset(p,0x55,1000);
	memset(Temp,0x55,100);
	Data=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

下载完程序调试运行效果:

程序进入HardFault_Handler
在这里插入图片描述

查找问题步骤:

1.查看堆栈指针SP的地址以及内容

堆栈指针SP地址为0x20000468
在这里插入图片描述

查看Memory,地址为0x20000468
在这里插入图片描述

2.找到Return address地址

内核是将R0~R3、R12、Returnaddress、PSR等寄存器依次入栈,所以找到Return address是0x08000FE7
在这里插入图片描述

3.查看汇编界面

在这里插入图片描述

4.输入Return address地址,查找到问题代码

在这里插入图片描述
输入地址0x08000FE7
在这里插入图片描述
找到Return address的指令,以及上一条指令,发现上一条指令指针是空指针,问题找到
在这里插入图片描述

再举一个例子

uint32_t Data2=100,Data3;
uint8_t Databuff[10000];
uint8_t Temp[100];
void Datacpy(void)
{
		memcpy(Temp,Databuff,10000);
	
}
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
	MX_GPIO_Init();
	 /* USER CODE BEGIN 2 */
	memset(Temp,0x55,100);
	Data=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);
	Data3=100*(Data2-1);
	if(Data3>10)
	{
	Data=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);	
	
	}
	Datacpy();
	Data=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

根据上述方法,查出有问题的函数是void Datacpy(void),Return Address是0x080001A3,发现是操作数组的时候越界了。
在这里插入图片描述

小结

使用调试工具和技术来定位HardFault的根源在单片机开发和调试中是必不可少的,可以帮助我们快速地排查问题所在,提供产品开发效率。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AR传送门+特定区域显示内容+放大镜 效果着色器使用

AR传送门特定区域显示内容放大镜 效果 关键词:Portal Mask 1、教程链接: AR 传送门教程 Unity - Portal Mask Implementation - Part 4_哔哩哔哩_bilibili 应用案例效果: 2、案例下载地址:使用unity 2021.3.33f1 obi 工具…

三分钟让你掌握PDF转音频:PDF2Audio背后的秘密

你有没有过这样的经历?工作繁忙,眼睛被一份又一份的PDF文件轰炸,盯得头昏眼花,却还得继续阅读。如果我告诉你,有一个简单的工具,可以把那些厚厚的PDF文档变成语音,让你在通勤、做家务时“听”文件,而不是“看”文件,你会不会心动? 今天,我们就来聊聊一个叫做PDF…

**CentOS7安装redis**

CentOS7安装redis 首先解压压缩包 redis-7.0.0.tar.gz tar -xvf redis-7.0.0.tar.gz接着进入到redis中 cd redis-7.0.0.tar.gz执行make命令编译 make接着执行安装命令 make install之后编译安装完后 程序都会在/usr/local/bin目录下 这里需要将在redis目录中redis.conf配置…

交通 | ACM SIGSPATIAL 24 深度强化学习求解多周期设施选址问题

论文作者信息:Changhao Miao, Yuntian Zhang, Tongyu Wu, Fang Deng, and Chen Chen. 2024. Deep Reinforcement Learning for Multi-Period Facility Location: p k p_{k} pk​-median Dynamic Location Problem. In The 32nd ACM International Conference on Ad…

如何评估和观测 IoTDB 所需的网络带宽?

IoTDB 推荐网络配置监控网络 I/O 一网打尽! 网络数据传输速度太慢?延迟太高? 网络的硬件配置如何确定? 网络流量过大导致拥塞? 在现代计算机系统和应用程序中,网络 I/O 性能是决定整体系统表现的关键因素之…

微服务 OpenFeign 解析部署使用全流程

目录 1、什么是OpenFeign 1、Feign是什么??http请求 2、OpenFeign是什么 3、Feign和openFeign有什么区别 2、应用 1、 需要开启nacos 和redis 2、准备工作 【1.对springsession做改动】 【2.对springsession-1做改动】 3、实现http请求管理 4、…

借助spring的IOC能力消除条件判断

shigen坚持更新文章的博客写手,记录成长,分享认知,留住感动。个人IP:shigen 在前边讲到了如何借助HashMap、枚举类、switch-case消除条件判断,这里讲到我们最常见的用spring的IOC能力来消除代码中的逻辑判断。其实大部…

精准测试在基金团队应用实践

以下为作者观点: 一、引言 精准测试是一套计算机测试辅助分析系统,精准测试的核心组件包含,软件覆盖率分析、用例和代码的双向追踪、智能回归测试用例选取、缺陷定位、测试用例聚类分析、测试用例自动生成系统,这些功能完整的构…

3-2 AUTOSAR RTE对Runnable的作用

返回总目录->返回总目录<- 一、前言 通过RTE给runnable提供触发事件。 runnable是可以被触发的,但是需要通过RTE来实现这个触发和调用runnable通过RTE给runnable提供所需资源。 RTE将runnable需要的一些资源通过接口传输给它(Port的实现)将BSW和SWC做隔绝。 因此OS和r…

前端大模型入门:使用Transformers.js手搓纯网页版RAG(二)- qwen1.5-0.5B - 纯前端不调接口

书接上文&#xff0c;本文完了RAG的后半部分&#xff0c;在浏览器运行qwen1.5-0.5B实现了增强搜索全流程。但受限于浏览器和模型性能&#xff0c;仅适合于研究、离线和高隐私场景&#xff0c;但对前端小伙伴来说大模型也不是那么遥不可及了&#xff0c;附带全部代码&#xff0c…

干货 | 2024大模型十大趋势(免费下载)

导读&#xff1a;近日&#xff0c;在2024世界人工智能大会上&#xff0c;腾讯正式发布了《2024大模型十大趋势——走进“机器外脑”时代》报告。目前&#xff0c;这一报告正在AI产业界各大社群快速传播。报告中&#xff0c;腾讯研究院试图通过10个关键性的趋势&#xff0c;去理…

c++(AVL树及其实现)

一、AVL树的概念 AVL树是最先发明的自平衡⼆叉查找树&#xff0c;AVL是⼀颗空树&#xff0c;或者具备下列性质的⼆叉搜索树&#xff1a;它的 左右子树都是AV树&#xff0c;且左右子树的高度差的绝对值不超过1。AVL树是⼀颗高度平衡搜索⼆叉树&#xff0c; 通过控制高度差去控…

python开源代码自学问题解决(requests+openpyxl+pymysql)

目的 解决一下在一个开源代码中遇到的问题&#xff0c;作者已经学完了python的基础内容&#xff0c;因此找了一份开源的python代码进行学习&#xff0c;下面这份开源代码主要作用就是在拉勾网上获取与Python相关的职位信息&#xff0c;并将这些信息保存到本地的MySQL数据库中&…

【Linux】初始进程

目录 基本概念 PCB task_struct task_struct内容分类 组织进程 查看进程 查看正在运行的进程信息 获取pid和ppid 创建子进程 基本概念 一个已经加载到内存中的程序&#xff0c;叫做进程&#xff0c;正在运行的程序&#xff0c;叫做进程&#xff0c;进程是担当分配系统…

如果你不愿意冒一切风险,就不要成为创业者:如何建立一个年收入 1800 万美元的支付业务

作者&#xff1a;Austin Mac Nab&#xff0c;VizyPay 的 CEO 兼创始人 在创业初期&#xff0c;如果有人告诉我&#xff0c;我需要冒一切风险才能成功&#xff0c;我大概会吓得绕道而行。但事实是&#xff0c;如果你不愿意冒一切风险&#xff0c;就不要成为创业者。本着这个信念…

「JavaScript深入」彻底搞懂JS原型与原型链

JavaScript深入 — 原型与原型链 一、原因二、使用class实现继承普通的类实现继承 三、原型四、原型链小结原型原型链prototype和proto 引申 一、原因 JavaScript中除了基础类型外的数据类型&#xff0c;都是对象&#xff08;引用类型&#xff09;。但是由于其没有类&#xff…

央行放大招!潘行长发话了,现在能“贷款炒股“,这是真的吗?

9月&#xff0c;央行掌门人潘行长最新放话了&#xff0c;二套房贷款利率也得下调。这降准的利好一出&#xff0c;股市小涨了一波后又回到了原位&#xff0c;给全球金融市场带来了一股不同寻常的暖流。而非常有意思的是&#xff0c;在这次众多的金融政策大礼包当中&#xff0c;有…

CentOS8.5.2111(3)实验之DHCP服务器架设

一、实验目标 1&#xff0e;掌握DHCP服务器的主配置文件各项申明参数及操作及其含义 2. 具备DHCP 服务器、中继服务器的配置能力 3. 具备测试客户端正常获取服务器分配地址的能力 4. 具备DHCP服务器故障排除能力 二、实训原理/流程 &#xff08;一&#xff09;项目背景 …

媒界:助力民生保障 长城“消防炮”即将批量交付硬核守护万家灯火

一大波“消防炮”即将列装&#xff01; 日前&#xff0c;长城炮官方账号发布一条“‘消防炮’来了”的视频&#xff0c;引发广泛关注。视频显示一批长城炮车型已完成消防装备加装&#xff0c;华丽变身“消防炮”&#xff0c;整装待发&#xff0c;即将交付全国消防&#xff0c;…

创建型模式-简单工厂-工厂方法-抽象工厂

简单工厂模式 例题 uml 代码 package simpleFactory; import java.lang.management.OperatingSystemMXBean; import java.util.Scanner; //定义Person class Person{ public void say(){} } class Man extends Person{ public void say() { System.out.…