手把手教你查找stm32 HardFault_Handler调试及问题方法

版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/u013184273/article/details/84440177

在编写STM32程序代码时由于自己的粗心会发现有时候程序跑着跑着就进入了HardFault_Handler中断,导致异常的原因很多,例如:直接使用未分配空间的指针、栈溢出等一场非法操作便会使程序进入HardFault异常状态。按照经验来说进入HardFault_Handler故障的原因主要有两个方面

 

1:内存溢出或则访问越界。

2:堆栈溢出。

发生异常后我们可以首先查看LR寄存器的值,确认当前使用的堆栈是MSP还是PSP,然后找到相对应的堆栈指针,并在内存中查看相对应堆栈的内容,内核将R0~R3,R12,LR,PC,XPRS寄存器依次入栈,其中LR即为发生异常前PC将要执行的下一条指令地址。

那么Cortex-M3 内核HardFault错误调试定位方法有:

方法1   如何精确定位出问题代码的所在位置:

以访问越界为例:(对STM32F103C8T6内部flash模拟EEPROM)

#define STM32_FLASH_SIZE 64                                         

#define STM32_FLASH_WREN 1           

#define FLASH_SAVE_ADDR  0X08078000            

#define FLASH_HIS_ADDR  0X08078002      

...

FLASH_SAVE_ADDR是开始存储的基地址,STM32F103C8T6内部flash大小是64K,在STM32的内部闪存(FLASH)地址起始于0x08000000,一般情况下,程序就从此地址开始写入。因此STM32F103C8T6的结束地址应该是64*1024转换成16进制后加上单片机flash的基地址得到的结果就是0x08010000,那么以上代码设置了FLASH_SAVE_ADDR为0X08078000已经超出了该单片机的范围,因此如果在用此单片机操作flash是如果对这个地址进行写和读的会发生错误。现在假设你在不知情的状况下对这个地址进行了操作,然后程序运行时进入

HardFault_Handler中断中。那么要找出错误代码在哪个地方,可以使用以下方法(调试软件MDK):

1:进入调试调试界面在HardFault_Handlerwhile(1)处打上断点。

3:等待代码运行到此,这时查看LR寄存器的

如果是正常运行那么显示的寄存器类似下图所示:

 

 

如果进入HardFault_Handler中断,那么显示的寄存器如下图所示:

发生异常之后可首先查看LR寄存器中的值,确定当前使用堆栈为MSP或PSP,然后找到相应堆栈的指针,并在内存中查看相应堆栈里的内容。

在Cortex_M3权威指南中可以看到如下图所示:

由这张图可见,这个按位或的作用是把R14寄存器的低4位设为D,在这个异常返回后进入线程模式,使用线程堆栈PSP,因为任务运行时要确保使用的是线程模式,只有发生中断或异常时,才让系统进入Handle模式并使用MSP。在xPortPendSVHandler里之所以没有这一行,是因为在进入这个异常前,系统正在跑任务,使用的就是线程模式和PSP,进入异常后变成Handle模式和MSP,但在异常返回时会自动回到这个异常发生前的模式也就是线程模式与PSP。在vPortSVCHandler这个函数被调用之前,系统一直是处于Handle模式并使用MSP的。(因为复位后就是Handle模式,因此大部分没用上系统的STM32的工程,都是让STM32处于Handle这个最高模式下运行的。)

看到LR寄存器中的值是0xFFFFFFF9,因此我应该去看MSP的地址,找到该地址的地址然后如下图所示打开内存,输入上面找到的寄存器地址,右键选择以long型查看地址如下所示:

然后查看这个地址向下数六个long地址,为什么是6个long地址呢,因为由于异常发生时,内核将R0~R3、R12、Returnaddress、PSR、LR寄存器依次入栈,其中Return address即为发生异常前PC将要执行的下一条指令地址;大概是0x08xxxxxx这样开始的即为出错的代码位置,然后可以反汇编查看,如下图所示:

可以看到是对应的C语言程序是在读FLASH函数中发生了错误,因此可以判断为访问越界的问题。

方法2:最简单,最明显

在调试状态下,当进入HardFault断点后,菜单栏Peripherals >Core Peripherals >FaultReports打开异常发生的报告,查看发生异常的原因。

跳出如下表格:

上面的报告发生了BUS FAULT,并将Fault的中断服务转向Hard Fault

相对于检测发生了什么异常,定位异常发生位置显得更重要。
(1)打开Call Stack窗口(如下图,断点停在Hard Fault服务程序中)

(2)在Call Stack的HardFault_Handler上右键Show CallerCode

这时将跳转到发生异常的源代码位置(如上图),即发生错误的地方在读FLASH处,可以想到应该是刚刚设置的FLASH地址越界问题

方法3:此方法和方法一大致相同

下面介绍怎么找出程序中的异常。

https://images2015.cnblogs.com/blog/917705/201610/917705-20161010101458539-1528104762.png

接下来在keil_MDK工程中,编译代码,并debug,之后全速运行,可以看到如下图所示程序进入HardFault异常。

https://images2015.cnblogs.com/blog/917705/201610/917705-20161010101745336-1054407022.png

如下所示我们找到SP寄存器,0x200045B8即为栈地址,栈里面的值依次为R0~R3R12PC(Return address)xPSR(CPSRSPSR)LR。如图我们看到划红线的地方,注意从右往左看。分别为0x0800427D0x08004BFA

https://images2015.cnblogs.com/blog/917705/201610/917705-20161010101933430-173904825.png

show code at address中输入0x08004BFA,点击go to即找到出现异常的代码段附近下面要执行的程序。

https://images2015.cnblogs.com/blog/917705/201610/917705-20161010102531227-1035806375.png

我们用同样的方法在show code at address中输入0x0800427D,找到如下代码段

https://images2015.cnblogs.com/blog/917705/201610/917705-20161010102949180-211320752.png

可以发现异常代码就在uart_send_noackdata这个函数里,这个函数里我们定义了一个指针,没有给他分配空间便开始使用了。由此我们掌握了第一种查找异常的方法。只要记录栈里面第21~24以及2528字节的内容即可方便的找到异常代码。下面介绍使用.map文件查找异常。.map文件在keil工程里面随着程序的编译会自动生成。

https://images2015.cnblogs.com/blog/917705/201610/917705-20161010103413743-1934954010.png

.map文件里我们查找0x08004BFA,找到了0x08004bd8指示是uart_send_noackdata函数,到此我们找到了异常代码所在的位置。

https://images2015.cnblogs.com/blog/917705/201610/917705-20161010103633758-700474568.png

 由此我们知道我们只要找到栈里面PC(Return address)xPSR(CPSRSPSR)寄存器里的内存地址便可以找到异常代码。

CPSR

当前程序状态寄存器 (Current Program State Register)

SPSR

保存的程序状态寄存器 (Saved Program State Register), 6,主要是在处理异常的时候使用.

每一种处理器模式下都有一个专用的物理寄存器作为备份的程序状态寄存器SPSR , 当特定的异常发生时,这个物理寄存器负责保存CPSR当前程序状态寄存器的内容, 当异常处理程序返回时,再将内容恢复到当前程序状态器中,继续向下执行原来程序.

PC

程序计数器,是用来计数的,指示指令在存储器的存放位置,也就是个地址信息.

 

  • 53
    点赞
  • 269
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: STM32hardfault_handler是一个用于处理硬件故障的函数。当STM32芯片发生硬件故障时,系统会自动调用这个函数来处理故障。这个函数可以帮助我们快速定位和解决硬件故障问题,提高系统的稳定性和可靠性。 ### 回答2: STM32是一款由STMicroelectronics公司设计的微控制器系列,具有高效、高速、灵活等特点,广泛应用于嵌入式系统中。在使用STM32时,程序出现错误时,也会出现hardfault_handler异常。 hardfault_handlerSTM32芯片处理器的一种错误状态,指处理器在执行运算时出现错误,无法处理的情况。例如,操作码错误,内存读写错误,栈溢出等都会导致hardfault_handler异常。当程序出现hardfault_handler异常时,CPU会进入fault状态,系统将停止响应。 为了解决该问题,开发者需要了解和处理hardfault_handler异常。事实上,解决该问题并不难,一般以以下几个步骤为主。 1.理解hardfault_handler:首先,需要了解hardfault_handler的产生原因。这有助于开发者更快地发现和解决问题。 2.分析异常产生的原因:通过芯片提供的日志或调试工具,确定异常发生的地点、原因等相关信息,手动分析栈的状态以及内存读写等情况,以便发现问题。 3.修改代码:一旦发现异常的原因,就需要修改、调整程序代码以消除异常状态。 4.测试和验证:在修复程序后,需要进行测试和验证,确保系统正常运行,不再出现异常状态。 总之,hardfault_handler异常是STM32芯片处理器中的错误状态,它可能由各种原因引发。解决该问题需要通过深入分析、代码调试和测试验证来实现。只有掌握了hardfault_handler的产生和处理方法,才能更好地利用STM32的优势特点。 ### 回答3: STM32是一种微控制器,其可以用于嵌入式应用程序的开发。在STM32处理器中,可能会发生一些硬件错误,这些硬件错误也称为硬故障。当STM32处理器发生硬故障时,程序将停止运行,并且必须通过硬故障处理器进行诊断和修复。硬故障处理器的功能是监视STM32处理器中的硬件错误,并生成相关的调试信息。 当一个STM32处理器发生硬故障时,硬故障处理器会从存储器中读取硬故障向量表,并跳转到硬故障向量表中指定的硬故障处理程序。这个程序称为hardfault_handlerhardfault_handler的主要作用是记录发生硬故障时的错误原因,并生成一个硬故障日志文件,以便开发人员进行故障分析和修复。 硬故障处理器可以根据集成硬件中硬故障发生的情况识别出硬故障的类型,并将其记录在日志文件中。日志文件包括硬故障类型、触发原因、处理程序的代码位置等信息。这些信息可帮助开发人员快速定位导致硬故障的问题,并进行修复。 在进行STM32处理器的开发时,应该考虑到可能出现硬故障的情况,并编写硬故障处理程序的代码。硬故障处理程序应该能够识别硬故障的类型,并在发生硬故障时生成相应的调试信息。这样可以保证在硬故障发生时,能够及时进行故障诊断和修复,提高应用程序的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值