STM32F103 HardFault_Handler 分析汇总

STM32进入HardFault_Handler的调试方法
http://blog.sina.com.cn/s/blog_9d9054cb0102x9t8.html

https://blog.csdn.net/electrocrazy/article/details/78173558
在用Keil对STM32的程序进行仿真时程序有时会跑飞,停止仿真程序会停在HardFault_Handler函数里的死循环while(1)中。这说明STM32出现了硬件错误。

    STM32出现硬件错误可能有以下原因:
    (1)数组越界操作;
    (2)内存溢出,访问越界;
    (3)堆栈溢出,程序跑飞;
    (4)中断处理错误;
    遇到这种情况,可以通过以下2种方式来定位到出错代码段。

方法1:
1.1在硬件中断函数HardFault_Handler里的while(1)处打调试断点,程序执行到断点处时点击“STOP”停止仿真。

  1.2

在Keil菜单栏点击“View”——“Registers Window”,在寄存器查看窗口查找R14(LR)的值。如果R14(LR)
= 0xFFFFFFE9,继续查看MSP(主堆栈指针)的值,如果R14(LR) = 0xFFFFFFFD,继续查看PSP(进程栈指针)的值。我的程序R14(LR)
= 0xFFFFFFF9,接下来以此为例。

  1.3

在Keil菜单栏点击“View”——“Memory Windows”——“Memory1”,在“Address”地址栏中输入MSP的值:0x20001288,然后在对应的行里找到地址。地址一般以0x08开头的32位数。本例中,地址为0x08003CB9。

  1.4

在Keil菜单栏点击“View”——“Disassembly Window”,在“Disassembly”窗口中右击,在下拉菜单中选择“Show
Disassemblyat Address…”。在弹出框“Show Code atAdress”的地址框中输入地址0x08003CB9进行搜索,然后就会找到相对应的代码。这里的代码就是进入循环中断之前的情况。仔细查看附近区域的相关代码来排查错误具体原因。

方法2:
2.1在硬件中断函数HardFault_Handler里的while(1)处打调试断点,程序执行到断点处时点击“STOP”停止仿真。

  2.2

在Keil菜单栏点击“View”——“Call Stack Window”弹出“Call
Stack + Locals”对话框。然后在对话框中右键选择“Show Caller Code”,就会跳转到出错之前的函数处,仔细查看这部分函数被调用或者数组内存使用情况。
————————————————
版权声明:本文为CSDN博主「electrocrazy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/electrocrazy/java/article/details/78173558

https://blog.csdn.net/ma57457/article/details/51420313
我所知道的内存溢出分为两种,一种是数组溢出,一种是堆栈溢出。
一种内存溢出的定位方法:一般内存溢出多为数组,先查找到内存溢出的变量,然后查看mp1地址映射文件,按照序列,以溢出的变量为基地址,向上查找,找数组,然后在代码中查到该数组的序列填充,大约查找3至5个数组,如果均没有发现溢出,使用下面的方法。

另一种内存溢出的定位方法:类似于pcb板的割线,利用while死循环进行定位,这种方法的大前提是需要知道内存溢出的变量。
语句如下:
While(A);
A在这里必须是全局变量,A可以是某一变量,也可以是某一语句,比如A<10。当A条件满足时,程序会在这里死循环。
while(A);的放置,该语句使用时最好大于2句,放置位置尽可能的囊括多的代码,若果没有大致思路可以试试将函数放置在主程序中,随便放置3个以上的语句。

举个栗子:
uint8 B(void)
{
uint8 ret;
while(A<10000)
/*********************************
This is your Code。
************************************/
while(A<10000);
return ;
}

当程序死在第一条语句是,可以认为溢出不是该函数造成的,那么可以去别的地方继续尝试,通常第一次会把两个语句放置的范围大一点,然后一点一点的缩小距离,类似于PCB 中的割板、或者数学中的二分法。
当程序死在第二条语句是,可以暂时猜测是该函数造成的内存溢出,然后根据函数的代码长度,将范围继续缩短,重点放在有数组地址写的地方,该地方溢出的可能性最大。

如果查找后发现代码没有问题,可以考虑是否是堆栈过小引起的内存溢出。将堆栈的地址范围放大,再看看是否存在溢出。

如果溢出的变量为静态局部变量,可以在mp1文件中找到溢出的变量的绝对地址,然后取该地址的值,进行判断。

例:static uint8 A;
在mp1中A的绝对地址为0x0a45;
A变量的判别条件就变为 (uint8)0X0a45<10000;

上面的例子就变为
uint8 B(void)
{
uint8 ret;
while((uint8)0X0a45<10000);
/*********************************
This is your Code。
**********************************/
while(
(uint8
)0X0a45<10000);
return ;
}

    如果都到这了,还没有找到溢出的语句,可以猜测是栈溢出,试试将栈放大,然后看看效果,关于栈溢出,请看我的另一篇博文,这里就不做过多的解释了。                         

————————————————
版权声明:本文为CSDN博主「木十化」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ma57457/java/article/details/51420313

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值