根据网络资料及自己调试经验总结如下:
STM32 出现 HardFault_Handler 故障的原因主要有两个方面:
1、内存溢出或者访问越界。这个需要自己写程序的时候规范代码,遇到了需要慢慢排查。
2、堆栈溢出。增加堆栈的大小。
排查方法:
发生异常之后可首先查看 LR 寄存器中的值,确定进入异常前一刻使用的堆栈为 MSP 或 PSP,然后找到相应堆栈的指针?
注:在 HardFault_Handler(void)中断里第一条语句打断点,进入中断后,查看 LR 寄存器的值,如果是 0XFFFFFFF9,那么中断前使用的是 MSP,如果是 0XFFFFFFFD,那么中断前使用的是 PSP;
根据找到的堆栈指针, 在内存中查看相应堆栈里的内容。由于异常发生时,内核将 R0~R3、 R12、 LR、 PC、 XPRS 寄存器依次入栈,其中 LR 即为发生异常前 PC 将要执行的下一条指令地址。
中断/异常的响应序列
**当 CM3 开始响应一个中断时,会在它看不见的体内奔涌起三股暗流:
入栈: 把 8 个寄存器的值压入栈。
取向量:从向量表中找出对应的服务程序入口地址。
选择堆栈指针 MSP/PSP,更新堆栈指针 SP,更新连接寄存器 LR,更新程序计数器 PC。**
入栈
响应异常的第一个行动,就是自动保存现场的必要部分:依次把 xPSR, PC, LR, R12 以及 R3‐R0 由硬件自动压入适当的堆栈中:如果当响应异常时,
当前的代码正在使用 PSP,则压入 PSP,即使用线程堆栈;否则压入 MSP,使用主堆栈。一旦进入了服务例程,就将一直使用主堆栈。
假设入栈开始时, SP 的值为 N,则在入栈后,堆栈内部的变化如表 9.1 表示。又因为 AHB 接口上的流水线操作本质,地址和数据都在经过一个流水线周
期之后才进入。另外,这种入栈在机器的内部, 并不是严格按堆栈操作的顺序的——但是机器会保证: 正确的寄存器将被保存到正确的位置, 如表 9.1所示。
测试: 在程序中调用如下函数,会进入异常故障中断。
void StackFlow(void)
{
int a[3],i;
for(i=0; i<10000; i++)
{
a[i]=1;
}
}12345678
DEBUG 如下图
SP 值为 0x20008d88,查看堆栈里面的值依次为 R0~R3、 R12、 LR、 PC、 XPRS, 例如 R0(00001C97), 根据表 9.1 里 LR 的位置, 得到地址 0x0800087D 即为异
常前 PC 将要执行的下一条指令地址(即 StackFlow()后面的语句处 RTC_Init().
另一种方法:
默认的 HardFault_Handler 处理方法不是死循环么? 将它改成 BX LR 直接返回的形式。然后在这条语句打个断点,一旦在断点中停下来,说明出错了,然后再返回,就可以返回到出错的位置的下一条语句那儿。
__asm void wait()
{
BX lr //BX 无条件转移指令,返回到发生错误的后面代码中
}
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
wait();
}
关键字:STM32 HardFault_Handler 处理方法
引用地址:
STM32学习笔记11——HardFault_Handler处理方法
推荐阅读最新更新时间:2024-11-06 20:48
基准源的选择
tl431 lm285 385 之类的,1.2V的 stm32的ad参考电压要求 2.4v REF2930-3V要二十多块,价格过高,查力源报价也就几块钱,是不是TI的供货出现了问题。既然3.0V基准少而不好找,我想使用2.5V基准。 3V的电压基准,除了TI还可以考虑其它公司,比如MAXIM的:MAX6003。MAX6003的初始精度 1%,比REF2930来得好。 又找了一下,MAX6010B更好: 超低电源电流:5 A (最大值) 3.2V输入下输出3V 小尺寸、3引脚SOT23封装 初始精度: 0.4% (最大值) 低温漂:50ppm/ C (最大值) 200mV低压差 负载调节(7mA源出电流):200 V/m
[单片机]
STM32 CAN学习
最近在搞stm32实验板的can现场总线实验,之前只是搞过STC51的串口通信,相比之下,发觉can总线都挺复杂的。开始时,知道自己是新手,只知道can总线跟串行通信,485通信,I2C通信一样都是用来传输数据通信的,对其工作原理一窍不通,还是从基础开始看书看资料,先了解它的基本原理吧。 原来can总线有以下特点: 主要特点 ? 支持CAN协议2.0A和2.0B主动模式 ? 波特率最高可达1兆位/秒 ? 支持时间触发通信功能 发送 ? 3个发送邮箱 ? 发送报文的优先级特性可软件配置 ? 记录发送SOF时刻的时间戳 接收 ? 3级深度的2个接收FIFO ? 14个位宽可变的过滤器组-由整个CAN共享 ? 标
[单片机]
STM32单片机开发环境的安装与使用
1.1 概述 学习 STM32 单片机的第一步便是开发环境的搭建了。开发环境的作用是什么呢?自然是用来敲代码,编译代码,调试代码和下载代码了。业界两款最常用的软件集成了上述功能,分别是 keil5 和 IAR,本系列教程以 keil5 为基础的,因此,下面详细讲解软件 keil5 的安装以及使用。 1.2 keil 软件安装包获取 最先能想到的当然是直接从 KEIL 的官方网站下载,官方下载页面如下图所示,从官方网站下载需要一定时间。我们提供的资料中已经提前下载好了,双击启动安装即可。 1.3 keil5 软件安装 Keil 一直在不断的发展,因此版本不断的在更新,截至到目前已经更新到了版本 5.29,各版本都是向下兼
[单片机]
如何创建硬件在环工程
我们很多时候使用的STM32单片机型号无法与官方硬件支持包自带的型号一一对应上,而matlab 2021b版至最新版本可以支持 F4xx系列单片机+CubeMX自定义型号配置使用,本篇以“STM32F407VGT6”型号为例如何创建硬件在环工程 温馨提示 :2021b版本Matlab只支持F4xx以上型号使用CubeMx自定义配置功能,而F4xx以下(F1x、F0x等)则只能使用官方开发板支持包方式开发。 CubeMX版本 :6.2.0 Matlab版本 :2021b STM32CubeProgrammer版本 :2.6.0 3.0 软件版本验证 创建simulink模型前需要先检查下硬件支持包和相关软件是否安装正确,
[单片机]
stm32 在线升级之跳转函数
一、功能: 用于在程序间进行相互跳转; 二、示例 typedef void(*pFunction)(void); u32 JumpAddress; pFunction Jump_To_Application; void GotoAPPMain(void) { JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); Jump_To_Application = (pFunction) JumpAddress; __set_MSP(*(__IO uint32_t*) ApplicationAddress); Jump_To_Application(); }
[单片机]
基于STM32的触摸屏学习笔记
本文共有三个内容:一、电阻触摸屏的原理;二、XPT2046的控制字与数字接口;三、程序源码讲解(参考正点原子的代码) 一、电阻触摸屏的原理,上图: 图上的文字介绍了触摸的原理,下面总结一下触摸的原理: 触摸屏工作主要是两个电阻屏(上下两层)在工作,如上图,当某一层电级加上电压时,会在该网络上形成电压梯度。如果有外力使得上下两层在某一点接触,则在未加电压的那一层可以测得接触点的电压,从而得出接触点的坐标(X或Y)。举个例子:当我们在上层的电极间(Y+和Y-)加上电压,则会在上层形成电压梯度(这里读者可以想想AD转换的原理),当有外力使得上下两层在某一点接触时,在底层X层就可以测得接触点处的电压(每个点电压都不同),再根据测得电
[单片机]
意法与厦门大学合作研发32位嵌入式系统
微控制器设计开发的厂商意法半导体协同其增值服务商深圳市博巨兴,宣布与厦门大学签订合作协议,成立“ST嵌入式系统联合实验室”,并举行实验室揭牌仪式。意法半导体持续推动校园合作计划,与中国的大学携手开发嵌入式应用技术和培训电子工程专业学生,再迈出重要的一步。
作为32位微控制器的主导厂商之一,意法半导体将向厦门大学提供先进的基于32位ARM CORTEX-M3的STM32微控制器及其开发工具,信息科学与技术学院(通信工程系、电子工程系、自动化系、计算机系及智能科学与技术系)的本科生及研究生将参与意法半导体的实际项目的开发。此外,意法半导体将提供所需的全部培训和技术支持,从事教学和学术研究,协助大学院校及产业
[单片机]
关于STM32 ADC时采用DMA的一点疑问
手册上有这样的话:只有ADC1能够产生DMA请求,似乎是只有ADC通道1能采用DMA方式传输数据。 但是万利的开发板上的ADC例子,用的是ADC通道10,还用了DMA 方式传数据。 所以我猜测 “只有ADC1能够产生DMA请求”中提到的ADC1 并不是指ADC 通道1, 而是软件可配置的 ADC 通道的分类形式,可分为ADC1和ADC2. 我们可将 通道10(或其他)配置成ADC1 “模式”。通过函数 /* ADC1 regular channel10 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_5
[单片机]