历史上的今天
今天是:2025年05月27日(星期二)
2019年05月27日 | STM32学习笔记11——HardFault_Handler处理方法
2019-05-27 来源:eefocus
根据网络资料及自己调试经验总结如下:
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;
}
}12345678DEBUG 如下图
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();
}
史海拾趣
|
我的时钟周期为1/20uS,那么我的中断响应时间应该在5/20uS左右,但实际上测出来的响应时间在2.5uS左右,这个时间长了好多,不知道是什么原因造成的?那个高手有这方面经验的请指点一下。… 查看全部问答> |
|
由于MPEG-2压缩技术的采用,绝大多数市场都已接受数字电视(DTV),但情况并非如此简单。H.26?-AVC (MPEG-4 第10部分)和微软的VCI压缩标准承诺可为标准和高清(HD)电视带来更大幅度的进步。广播设备OEM将需要采用这些新兴的压缩编码标准,以有效地满足 ...… 查看全部问答> |
|
本人有丰富的WindowCE应用开发经验,现承接Windows CE/Mobile平台上的应用外包项目,质量保证。有意者请与我联系: QQ:17632892 MSN:kerlw@hotmail.com… 查看全部问答> |
|
本帖最后由 jameswangsynnex 于 2015-3-3 19:59 编辑 有7月初参加过茁壮和富士通的高清机顶盒推广活动的兄弟举举手,MB86H61+iPanel3.0大家都有用起来了吗?300块的整转成本实现了吗?话说今年的高清整体转移启动年来着,都快年底了,目前动静不是 ...… 查看全部问答> |
|
我在用QuartusII模拟I2C总线的时候,写了一个任务 task shift_in; output [7:0] shift; begin @(posedge scl) shift[7] = sda; @ (po ...… 查看全部问答> |




