【STM32】HardFault问题详细分析及调试笔记

这篇具有很好参考价值的文章主要介绍了【STM32】HardFault问题详细分析及调试笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. 概述

2. 问题描述

3. 问题分析

4. 相关知识

4.1异常和中断

4.2 中断输入与挂起行为

4.3 Cortex-M4处理器的寄存器简介

4.4  C实现的异常处理

4.5 栈帧

4.6 异常返回值

4.7 异常流程

5. 问题定位

5.1 确定栈指针

5.2 确定LR的值

5.3 查询C代码位置

5.4 确定PSP栈

5.5 处理方法

6. 总结


1. 概述

        最近做的项目中出现了HardFault故障现象,查阅了网上关于HardFault的排故思路,详尽程度不同,均有所帮助,但深入分析时,又觉得指导的不够到位,本文参考了《ARM Cortex-M3Cortex-M4权威指南》,借鉴了网友的经验,结合了map文件加以分析,准确定位了故障原因,解决了实际问题,希望能帮助到广大网友。

2. 问题描述

        接入以太网运行几个小时后,偶发单片机程序卡死现象。

3. 问题分析

        采用一贯的解决嵌入式单片机问题的思路。从软件和硬件两个方面切入分析。(本人长期坚持这一原则,避免硬件问题被忽略

        该工程应用了CAN、串口、网络、AD等外设,在前期测试中,单独应用CAN、串口、网络均未出现问题,尤其是网络,进行过长时间压力测试(间隔1mS PING测试)均未出现问题,可初步排除硬件问题。

        分析当时的应用场景,网络接入后引起的单片机程序卡死,复现时间较短。首先想到的方案是进行CAN、网络同时压力测试,并用仿真器在线调试。考虑程序大概率会卡死在HardFault处,因此在HardFault中断服务程序的while ( 1 )设置断点,在故障复现时,程序停在了HardFault_Handler的while循环处,代码如下

void HardFault_Handler ( void )
{
    /* Go to infinite loop when Hard Fault exception occurs */
    while ( 1 )
    {
    }
}

        要分析这个问题,我们需对STM32的中断及异常处理有一定的了解,才能更好的分析故障产生的原因,参考《ARM Cortex-M3Cortex-M4权威指南》,整理了相关知识。

4. 相关知识

4.1异常和中断

        要了解HardFault中断,先要了解中断。几乎所有的微控制器,中断是一种常见的特性。中断一般是由硬件(如外设和外部输入引脚)产生的事件,它会引起程序流偏离正常的流程(如给外设提供服务)。当外设或硬件需要处理器的服务时,执行的流程如图 1所示。

【STM32】HardFault问题详细分析及调试笔记

 图 1外设中断处理流程

        所有的Cortex-M处理器都会提供一个用于中断处理的嵌套向量中断控制器(NVIC)。除了中断请求,还有其他需要服务的事件,将其称为“异常”,按照ARM的说法,中断也是一种异常。典型的Cortex-M4微控制器中,NVIC接收多个中断源产生的中断请求,如图 2所示。

【STM32】HardFault问题详细分析及调试笔记

图 2 典型微控制器中的各种异常源

        Cortex-M4的NVIC支持最多240个IRQ(中断请求)、1个不可屏蔽中断(NMI)、1个SysTick(系统节拍)定时中断及多个系统异常。具体如表 1所示。

表 1 Cortex-M4异常源

异常源

异常源说明

备注

IRQ

多数IRQ由定时器、I/O端口和通信接口(如UART、SPI、CAN和I2C)等外设产生

NMI

由看门狗定时器或掉电检测器等外设产生

SysTick定时器

系统节拍

系统异常

硬件错误、总线错误、存储管理错误、使用错误、PendSV等。

        微控制器复位后,所有中断都处于禁止状态,且默认的优先级为0,在使用任何一个中断之前,需要:

  • 设置所需中断的优先级。
  • 使能外设中的可以触发中断的中断产生控制。
  • 使能NVIC中的中断。

4.2 中断输入与挂起行为

        每个中断源都有多个属性:

  • 每个中断都可被禁止(默认)或使能。(这里不包含NMI)
  • 每个中断都可被挂起(等待服务的请求)或解除挂起。
  • 每个中断都可处于活跃(正在处理)或非活跃状态。

        挂起状态的意思是,中断被置于一种等待处理器处理的状态。有些情况下,处理器在中断挂起时就会进行处理。不过,若处理器已经在处理另外一个更高或同等优先级的中断,或者中断被某个中断屏蔽寄存器给屏蔽掉了,那么在其他的中断处理结束前或中断屏蔽被清楚前,挂起请求会一直保持。

        中断挂起和激活行为的简单情况如图 3所示。当中断请求产生时,中断进入挂起状态,处理器暂停当前处理的线程并完成压栈和取向量后,处理中断,中断挂起状态清除,进入活跃状态。处理器处理完中断后出栈,继续处理之前的线程,同时中断活跃状态结束。

【STM32】HardFault问题详细分析及调试笔记

图 3 中断挂起和激活行为的简单情况

4.3 Cortex-M4处理器的寄存器简介

        在介绍异常处理前,需要先了解一下Cortex-M4处理器的寄存器。Cortex-M4处理器在处理器内核中都有多个执行数据处理核控制的寄存器,并以寄存器组的形式进行分组。Cortex-M4处理器的寄存器组中有16个寄存器,其中13个位32位通用寄存器,其他3个为特殊用途,如图 4所示。

【STM32】HardFault问题详细分析及调试笔记

图 4 Cortex-M处理器寄存器组中的寄存器

  • R0~R12为通用目的寄存器,
  • R13为栈指针,物理上存在两个栈指针:主栈指针(MSP)为默认的栈指针,在复位后和处理器处于处理模式时,会被选择使用;另一个栈指针为进程栈指针(PSP),只能用于线程模式(有RTOS时)。
  • R14为链接寄存器(LR),用于函数或子程序调用时返回地址的保存。在函数或子程序结束时,程序控制可以通过将LR的数值加载程序计数器(PC)中返回调用程序处并继续执行,在异常处理期间,LR会自动更新为特殊的EXC_RETURN(异常返回)数值。
  • R15为程序计数器(PC)。

4.4  C实现的异常处理

        对于Cortex-M处理器,可以将异常处理或中断服务程序(ISR)实现为普通的C程序/函数。用于ARM架构的C编译器遵循ARM的一个名为AAPCS(ARM架构过程调用标准)的规范。根据这份标准,C函数可以修改R0~R3、R12、R14(LR)、以及PSR,若C函数需要使用R4~R11,应该将这些寄存器保存在栈空间中,并且在函数结束前将它们恢复,如图 5所示。

【STM32】HardFault问题详细分析及调试笔记

图 5 AAPCS规定的函数调用中的寄存器使用

        C函数可以用作异常处理,异常机制需要再异常入口处自动保存R0~R3、R12、LR和PSR,并在异常退出时将它们恢复,这些都是由处理器硬件控制。具有浮点单元的处理器,如果用到了浮点单元,则异常机制还需要保存S0~S15和FPSCR。

4.5 栈帧

        在异常入口处被压入占空间的数据块为栈帧。对于有浮点单元的处理器,栈帧可能是8或26个字。栈指针的数值在函数入口和出口处应该是双字对齐的。无浮点单元的栈帧格式如图 6所示,有浮点上下文的异常栈帧格式如图 7所示。

【STM32】HardFault问题详细分析及调试笔记

 图 6 未启用浮点单元的异常栈帧

【STM32】HardFault问题详细分析及调试笔记

图 7 具有浮点上下文的异常栈帧

4.6 异常返回值

        处理器进入异常处理或中断服务程序(ISR)时,链接寄存器(LR)的数值会被更新为EXC_RETURN数值。其合法值如表 2所示。

表 2 异常返回(EXC_RETURN)合法值

浮点单元在中断前使用(FPCA=1)

浮点单元未在中断前使用(FPCA=0)

返回处理模式(总是使用主栈)

0xFFFFFFE1

0xFFFFFFF1

返回线程模式并在返回后使用主栈

0xFFFFFFE9

0xFFFFFFF9

返回处理模式并在返回后使用进程栈

0xFFFFFFED

0xFFFFFFFD

4.7 异常流程

        当异常产生且被处理器接受时,压栈流程会将寄存器压入栈中并组织栈帧,如图 8所示。

【STM32】HardFault问题详细分析及调试笔记

图 8 异常流程

5. 问题定位

工程开发环境为MDK5.25,定位过程如下。

5.1 确定栈指针

     在HardFault_Handler的while循环处设置断电,故障复现时R14(LR)寄存器值为0xFFFFFFFD

        查询“异常返回(EXC_RETURN)合法值”表格可知,返回后将使用进程栈,查看进程栈指针PSP的值为0x2000B278。具体如图 9所示。

【STM32】HardFault问题详细分析及调试笔记

图 9 故障复现调试示意图

5.2 确定LR的值

        打开Memory的监视窗口,输入PSP的值为0x2000B278则显示进程栈的内容如图 10所示,可知LR的值为0x080290E9

【STM32】HardFault问题详细分析及调试笔记

图 10 查找LR值示意图

5.3 查询C代码位置

     在Disassembly窗口单击右键—>选择Show Didassembly at Address>输入地址0x080290E9—>定位到os_int.c文件的void  OS_IntQPost ()函数,如图 11、图 12所示。该函数用于中断中延迟发布消息,分析问题可能和中断有关,和实际故障现象吻合。

【STM32】HardFault问题详细分析及调试笔记

图 11 定位C代码位置方法示意图

 【STM32】HardFault问题详细分析及调试笔记

图 12 定位C代码位置示意图

5.4 确定PSP栈

        根据前面的分析,PSP的值为0x2000B278打开工程的map文件,找到0x2000B278附近的变量为OSCfg_IntQTaskStk(栈地址为0x2000b114~0x2000b2a3)和OSCfg_ISRStk(0x2000b2a4~0x2000b433),均为任务栈(线程栈),如图 13所示。

【STM32】HardFault问题详细分析及调试笔记

图 13 MAP文件示意图

5.5 处理方法

        用watch窗口分别观察2个栈空间,发现OSCfg_ISRStk栈溢出,经分析可定位问题。接入网线后,由于网络优先级较高,更容易出现中断嵌套,导致OSCfg_ISRStk栈溢出,出现卡死在HardFault现象。

        在os_cfg_app.h中定义了OSCfg_ISRStk的大小,如下:

                                                            /* --------------------- MISCELLANEOUS ------------------ */
#define  OS_CFG_MSG_POOL_SIZE            100u               /* Maximum number of messages                             */

#define  OS_CFG_ISR_STK_SIZE             100u               /* Stack size of ISR stack (number of CPU_STK elements)   */

#define  OS_CFG_TASK_STK_LIMIT_PCT_EMPTY  10u               /* Stack limit position in percentage to empty            */


                                                            /* ---------------------- IDLE TASK --------------------- */
#define  OS_CFG_IDLE_TASK_STK_SIZE       128u               /* Stack size (number of CPU_STK elements)                */


                                                            /* ------------------ ISR HANDLER TASK ------------------ */
#define  OS_CFG_INT_Q_SIZE                10u               /* Size of ISR handler task queue                         */
#define  OS_CFG_INT_Q_TASK_STK_SIZE      100u               /* Stack size (number of CPU_STK elements)                */


                                                            /* ------------------- STATISTIC TASK ------------------- */
#define  OS_CFG_STAT_TASK_PRIO     (OS_CFG_PRIO_MAX - 2u)   /* Priority                                               */
#define  OS_CFG_STAT_TASK_RATE_HZ         10u               /* Rate of execution (1 to 10 Hz)                         */
#define  OS_CFG_STAT_TASK_STK_SIZE       100u               /* Stack size (number of CPU_STK elements)                */


                                                           /* ------------------------ TICKS ----------------------- */
#define  OS_CFG_TICK_RATE_HZ            1000u               /* Tick rate in Hertz (10 to 1000 Hz)                     */
#define  OS_CFG_TICK_TASK_PRIO             1u               /* Priority                                               */
#define  OS_CFG_TICK_TASK_STK_SIZE       128u               /* Stack size (number of CPU_STK elements)                */


                                                            /* ----------------------- TIMERS ----------------------- */
#define  OS_CFG_TMR_TASK_PRIO             2u               /* Priority of 'Timer Task'                               */
#define  OS_CFG_TMR_TASK_RATE_HZ         100u               /* Rate for timers (100 Hz Typ.)                           */
#define  OS_CFG_TMR_TASK_STK_SIZE        128u               /* Stack size (number of CPU_STK elements)                */

        将OSCfg_ISRStk大小修改为200,代码如下:

#define  OS_CFG_ISR_STK_SIZE             200u

        更改后观察OSCfg_ISRStk的空间,在压力测试下使用约60%,系统正常工作。

6. 总结

        HardFault问题涉及的原因比较复杂,有的简单、有的难,均和ARM底层相关,碰到该类问题让人头疼,对于初学者来说更容易发懵。本文通过实际案例分析,提供了解决问题的方法,旨在给读者提供软硬件问题的解决思路,未必能解决所有的问题。但请读者切记,碰到问题时一定要静下心来,认真分析,找到问题的根本原因才是终极目的,排故过程也是知识积累的过程,也是提高个人能力的过程。文章来源地址https://www.toymoban.com/news/detail-413683.html

到了这里,关于【STM32】HardFault问题详细分析及调试笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32调试】寄存器调试不良问题记录持续版

    记录一些stm32调试过程中:不易被理解、存在使用误区、不清不楚、是坑、使用常识等方面的一些记录。本记录只包含stm32的内核以及外设等寄存器的调试,不包含业务方面。 使用低功耗功能前是否需要打开PWR时钟? 是需要先打开PWR时钟的,否则无法唤醒。 睡眠模式、停机模

    2024年01月18日
    浏览(44)
  • 野火霸天虎 STM32F407 学习笔记_1 stm32介绍;调试方法介绍

    博主开始探索嵌入式以来,其实很早就开始玩 stm32 了。但是学了一段时间之后总是感觉还是很没有头绪,不知道在学什么。前前后后分别尝试了江协科技、正点原子、野火霸天虎三次 stm32 的课程学习。江协科技的 stm32f103c8t6 课程看了一段时间,感觉对一些外设的调用方法有

    2024年02月06日
    浏览(31)
  • 调试笔记-stm32的OTA/IAP 通过485升级固件

    背景:最近需要在stm32上实现通过rs485升级固件功能。经过几天搜索和调试,实现了功能。 目标:使用cubeIDE实现stm32F407VGT6,通过RS485升级固件 调试记录: 步骤1. 在keil环境下的rs485升级固件(含源码):STM32 OTA应用开发——通过串口/RS485实现OTA升级(方式2)_stm32串口升级_柒壹漆

    2024年02月11日
    浏览(36)
  • GD32F470 移植STM32F429工程 Keil调试笔记

    keil版本:5.25 安装 GigaDevice.GD32F4xx_DFP.3.0.4.pack Keil.STM32F4xx_DFP.2.15.0.pack 1、原项目为STM32F429 工程,切换到GD32F470 只需在 Options for Target\\\"“对话框的Device菜单中选中“GD32F470II”,重新编译即可,一般不会有编译错误。 2、将项目工程在切换回STM32F429,在 Options for Target”\\\"对话框的D

    2024年02月09日
    浏览(37)
  • STM32启动详细流程分析(一)

      大家不妨设想一下,cpu 的工作是什么,cpu 是没有主观意识的,它只会按照特定的指令执行相应的操作,用专业术语来说就是: 取指 - 译码 - 执行 ,译码和执行肯定是在 cpu 内部进行操作的,并且前提是已经取到了指令。那现在问题来了,指令在哪? cpu上电复位后执行的第

    2024年02月12日
    浏览(31)
  • 0503-stm32的调试工具:st-link详细解析 (命令行/ st utility/ cubePorbrammer)

    从事stm32开发的话,肯定绕不开stlink,使用stlink开发stm32时用到的知识点。对于常规开发而言,80%时候会使用keil或vscode对目标芯片进行下载与在线调试,简单的bug我们一般反复下载就行了,复杂的bug需要进行单步调试、查看寄存器、输出swo信息等。本文简单介绍stlink的两个工

    2024年02月05日
    浏览(40)
  • Stm32学习笔记,3万字超详细

    文章的原标题是【Stm32学习笔记】,但是在这个浮躁的时代,不当个标题狗是不会有人点进来的。而既然是发布出来了,那肯定是想要别人点个赞,点个收藏关注一下的,所以在发布的时候还是换了一个浮夸点的标题了。 本文章主要记录本人在学习stm32过程中的笔记,也插入

    2024年02月16日
    浏览(30)
  • 江科大STM32学习笔记(详细版)——2023持续更新

    基础篇 是到时候我自己找其它视频补充(就比如寄存器影射,时钟树),到时候写在其它文章里。 主篇(外设篇)目前是跟着@江协科技的STM32入门教程-2023版 细致讲解 中文字幕视频来学习的,大家可以边看视频边根据我的笔记做适合自己的笔记; 另外,因为篇幅太长了,我将

    2024年02月06日
    浏览(29)
  • 【【STM32分析IO该设置什么模式的问题】】

    我们分析而言 我们对于PA0 的设计就从此而来 对于边沿触发的选择我们已经有所了解了 我们下拉,但是当我们摁下开关的时候 从0到1 导通了 所以这个是下拉 上升沿触发 而对于KEY0 我们摁下是使得电路从原来悬空高阻态到地就是0 所以是下降沿触发 那么对于何种模式有很多人

    2024年02月10日
    浏览(21)
  • keysking 【stm32】hal库学习笔记--定时器(超详细!)

    任务一:串口发送计数器的值 1.打开串口2及其中断,用于发送数据 2.将高速外部时钟源设置为晶振,提高定时精度 3.将HCLK改为72MHz 4.开启定时器 TIM4–勾选 Internal Clock(内部时钟)/ TIM2–将Clock Source选择为Internal Clock 5.设置预分频器 Prescaler–n(想要实现的分频)-1 Counter Perio

    2024年02月02日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包