一、导致异常的原因很多,例如:直接使用未分配空间的指针、栈溢出等一场非法操作便会使程序进入HardFault异常状态。下面介绍怎么找出程序中的异常。
接下来在keil_MDK工程中,编译代码,并debug,之后全速运行,可以看到如下图所示程序进入HardFault异常。
如下所示我们找到SP寄存器,0x200045B8即为栈地址,栈里面的值依次为R0~R3、R12、PC(Return address)、xPSR(CPSR或SPSR)、LR。如图我们看到划红线的地方,注意从右往左看。分别为0x0800427D和0x08004BFA。
在show code at address中输入0x08004BFA,点击go to即找到出现异常的代码段附近下面要执行的程序。
我们用同样的方法在show code at address中输入0x0800427D,找到如下代码段
可以发现异常代码就在uart_send_noackdata这个函数里,这个函数里我们定义了一个指针,没有给他分配空间便开始使用了。由此我们掌握了第一种查找异常的方法。只要记录栈里面第21~24以及25到28字节的内容即可方便的找到异常代码。下面介绍使用.map文件查找异常。.map文件在keil工程里面随着程序的编译会自动生成。
、
在.map文件里我们查找0x08004BFA,找到了0x08004bd8指示是uart_send_noackdata函数,到此我们找到了异常代码所在的位置。
由此我们知道我们只要找到栈里面PC(Return address)、xPSR(CPSR或SPSR)寄存器里的内存地址便可以找到异常代码。
CPSR
当前程序状态寄存器 (Current Program State Register)
SPSR
保存的程序状态寄存器 (Saved Program State Register), 有6个,主要是在处理异常的时候使用.
每一种处理器模式下都有一个专用的物理寄存器作为备份的程序状态寄存器SPSR , 当特定的异常发生时,这个物理寄存器负责保存CPSR当前程序状态寄存器的内容, 当异常处理程序返回时,再将内容恢复到当前程序状态器中,继续向下执行原来程序.
PC
程序计数器,是用来计数的,指示指令在存储器的存放位置,也就是个地址信息
关键字:stm32 工程代码 HardFault 异常查错 调试方法
引用地址:
(五)stm32工程代码HardFault异常查错调试方法
推荐阅读最新更新时间:2024-03-16 15:32
Stm32 基于蓝牙的串口通信 详细篇
1. HC-05蓝牙 1.1蓝牙模块使用介绍 蓝牙HC05是主从一体的蓝牙串口模块,简单的说,当蓝牙设备与蓝牙设备配对连接成功后,我们可以忽视蓝牙内部的通信协议,直接将将蓝牙当做串口用。当建立连接,两设备共同使用一通道也就是同一个串口,一个设备发送数据到通道中,另外一个设备便可以接收通道中的数据。 1.2蓝牙模块使用注意 hc-05支持从4800bps~1382400bps间的标准波特率,使用时波特率一定要匹配,vcc接3.3 或者 5V GND 接GND TX接单片机上的RX RX接TX。 2.Stm32F1串口通信 2.1串口通信介绍 STM32F103ZET6 最多可提供 5 路串口, 2.2串口通信算法思路
[单片机]
stm32之CAN总线基础
can总线协议概述: CAN是Controller Area Network的缩写,由德国博世公司开发;CAN通过ISO11891以及ISO11519进行了标准化; CAN总线的特点: 1、多主控制 在总线空闲时,所有单元都可以开始发送消息(多主控制); 最先访问总线的单元获得发送权(辨别方式: CSMA/CA方式 ); 多个单元同时开始发送时,发送高优先级ID消息的单元可获得发送权; 2、消息的发送 在can协议中,所有消息都是以固定格式发送。总线空闲时,所有与总线相连的单元都可以开始发送新消息。两个以上的单元同时开始发送消息时,根据
[单片机]
基于STM32在喷绘机喷头控制系统的设计与实现
0 引言 由于喷绘机喷绘过程中采用的是压电喷头工作原理,为保证喷绘出图像清晰细腻,喷绘机需要在同一温度下提供稳定的驱动电压对压电晶体进行控制。如何在精准的条件下根据室内温度实时、快速、方便地更改驱动电压和配置数据值得研究。 1 系统设计理念 喷头的驱动电压VDD2(t)取决于喷头容积电压Vrank、基于不同厂家不同颜色的油墨粘滞度而提供每色油墨与标准油墨的修正值Voffset电压、不同颜色的油墨在不同温度下需要的驱动电压补偿值Vdiff(t),即VDD2(t)=Vrank+Voffset+Vdiff(t)。不同颜色的油墨在不同的温度下驱动电压的补偿值Vdiff(t),称之为T-V数据。 不同厂家油墨温压数据不同,厂家会根据
[单片机]
STM32 实现 IAP与APP文件合并
;以下为合并程序的配置文件,请注意APP的偏移地址为0x2000...全部文件夹请参考我的资源贴。 ;只针对小于64K的FLASH,需要更大容量的将在后续推出。 ;--------------------------------------------------------------------------------------------------------------------- ;CONSOLEBIN 2015.12.25 ;Info2.ini 文件与ConsoleBin.exe 放置在同级目录 ;引导程序文件,命名规则为 引导+文件+pre.bin leadFile=STM32F10XX6_
[单片机]
stm32 4*4矩阵键盘
stm32f030开发板。 使用HAL库。 状态机做debounce消抖。 col列,Pin配置为PP推挽输出模式; row行,Pin配置为Input模式,启用内部上拉电阻。 代码如下: .h文件 /* * * Name: keypad.h * Faq: www.mazclub.com */ #ifndef KEYPAD_H #define KEYPAD_H #include stm32f0xx_hal.h //#include pinname.h #define COLS (GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|G
[单片机]
STM32开发笔记71: 解决FreeRTOS任务的内存分配问题
单片机型号:STM32F091RCT6 在使用FreeRTOS进行程序设计时,遇到任务不能运行的问题,具体程序如下: DebugOutput( 启动USB通讯线程...rnrn ); osThreadDef(usbTask, StartUsbTask, osPriorityNormal, 0, 128); usbTaskHandle = osThreadCreate(osThread(usbTask), NULL); DebugOutput( 启动雷达红外通讯线程...rnrn ); osThreadDef(irdaTask, StartIrdaTask, osPriorityNormal, 0, 128);
[单片机]
STM32标准库、HAL库特点与应用
新手在入门STM32的时候,一般大多数都会选用标准库和HAL库,而极少部分人会通过直接配置寄存器进行开发。 对于刚入门的朋友可能没法直观了解这些不同开发发方式彼此之间的区别,本文试图以一种非常直白的方式,用自己的理解去将这些东西表述出来。 配置寄存器 不少先学了51的朋友可能会知道,会有一小部分人或是教程是通过汇编语言直接操作寄存器实现功能的,这种方法到了STM32就变得不太容易行得通了。 因为STM32的寄存器数量是51单片机的十数倍,如此多的寄存器根本无法全部记忆,开发时需要经常的翻查芯片的数据手册,此时直接操作寄存器就变得非常的费力了。也有人喜欢去直接操作寄存器,因为这样更接近原理,代码更少,知其然也知其所以然。
[单片机]
STM32系列里RTC的亚秒特性及功能(下)
我们回到前面提到的需求,每隔50±20ms做唤醒,即30ms~70ms范围内实现唤醒都可以接受。如果说使用ALARM中断,相信很多人自然会想到,先设定一个ALARM点,等唤醒后再修改新的ALARM值,就这样延续下去。 这样操作也是可以的,即每次在ALARM中断里修改新的ALARM时间点。下图是对ALARM值进行编程的流程【设置时先要关闭ALARM,修改ALARM值后再手动开启ALARM单元】: 不过,结合眼前的应用需求,我们可以不使用上面的做法,而是巧妙地使用RTC亚秒特性来实现周期性的ALARM以满足需求。怎么个巧法呢?一起来看看。 先假定RTCCLK为32768Hz,RTC同步分频系数和异步分频系数分别为如下参数:
[单片机]