单片机stm32 hard fault.docx
《单片机stm32 hard fault.docx》由会员分享,可在线阅读,更多相关《单片机stm32 hard fault.docx(9页珍藏版)》请在冰豆网上搜索。
单片机stm32hardfault
stm32hardfault
发布:
2009-8-0511:
12|作者:
learning|来源:
STM32技术社区
Hardfault(硬错误,也有译为硬件错误的)是在STM32上编写程序中所产生的错误中原因最为纷繁复杂的一种错误.由于能导致该错误的原因很多,所以一但出现,比较难找到其原因.
今天就个人的一些收集整理一下,写出以备各位查找利用.
硬fault是总线fault、存储器管理fault以及用法fault上访的结果。
如果这些fault的服务例程无法执行,它们就会成为“硬伤”——上访(escalation)成硬fault。
另外,在取向量(异常处理是对异常向量表的读取)时产生的总线fault也按硬fault处理。
在NVIC中有一个硬fault状态寄存器(HFSR),它指出产生硬fault的原因。
如果不是由于取向量造成的,则硬fault服务例程必须检查其它的fault状态寄存器,以最终决定是谁上访的。
硬fault状态寄存器(地址:
0xE000ED2C):
h_1.JPG
当发生硬错误后,而你又具有在线调试器的话,你可以直接在你的编译器的调试介面去查看0xE000ED2C处的值(如在IAR+JLINK的调试环境下,可通过点View→SymbolicMemory,在Goto处输出地址,回车即可跳到该地址)以缩小查找错误的范围.
DEBUGEVF:
因调试事件导致的fault:
1.断点/观察点事件
2.如果在硬fault服务例程的执行过程中,没有使能监视器异常(MON_EN=0)也没有使能停机调试(C_DEBUGEN=0),却执行了BKPT指令。
缺省时,有些C编译器可能会在半主机代码中使用BKPT指令。
也可以用上面的方法去查看调试fault状态寄存器(DFSR)0xE000ED30的值来进一步缩小范围:
h_2.JPG
一般情况下这一类错误可以给芯片重新上电来解决.
learning(2009-8-0511:
14:
32)
VECTBL:
取向量失败,
1.在取向量过程中发生总线fault
2.向量表偏移量设置有误
考虑地址对齐,Flash保护等原因.
FORCED:
总线fault、存储器管理fault以及用法fault上访的结果,因此要重新回头找一下各对应fault来确定到底是哪个出错.
总线fault状态寄存器(BFSR),地址:
0xE000_ED29:
h_3.JPG
各对应位出错可能原因见下表所示:
h_4.JPG
存储器管理fault状态寄存器(MFSR)0xE000_ED28:
h_5.JPG
MemManagefaults的常见诱因如下所示:
1、访问了MPU设置区域覆盖范围之外的地址
2、往只读region写数据
3、
用户级下访问了只允许在特权级下访问的地址
yqin(2009-8-0511:
22:
02)
终于来解决这个问题的人了,顶啊,,,是不是好像也碰到过这个问题
learning(2009-8-0511:
24:
33)
[i=s]本帖最后由learning于2009-8-511:
27编辑
对就各位的错误的原因可见下表:
h_6.JPG
用法fault状态寄存器(UFSR),地址:
0xE000_ED2A:
h_7.JPG
learning(2009-8-0511:
29:
12)
各对应位错误产生的原因对照下表:
h_8.JPG
learning(2009-8-0511:
30:
20)
假如你没有在线调试器的话也不妨尝试使用串口来打印出各种数据:
下面的代码出于一个名为joseph.yiu的人之手。
具体出处为:
//hardfaulthandlerwrapperinassembly
//itextractthelocationofstackframeandpassit
//tohandlerinCaspointer.
__asmvoidhard_fault_handler_asm(void)
{
IMPORThard_fault_handler_c
TSTLR,#4
ITEEQ
MRSEQR0,MSP
MRSNER0,PSP
Bhard_fault_handler_c
}
//AndthenyoucanextractthestackedregistersinC:
//hardfaulthandlerinC,
//withstackframelocationasinputparameter
voidhard_fault_handler_c(unsignedint*hardfault_args)
{
unsignedintstacked_r0;
unsignedintstacked_r1;
unsignedintstacked_r2;
unsignedintstacked_r3;
unsignedintstacked_r12;
unsignedintstacked_lr;
unsignedintstacked_pc;
unsignedintstacked_psr;
stacked_r0=((unsignedlong)hardfault_args[0]);
stacked_r1=((unsignedlong)hardfault_args[1]);
stacked_r2=((unsignedlong)hardfault_args[2]);
stacked_r3=((unsignedlong)hardfault_args[3]);
stacked_r12=((unsignedlong)hardfault_args[4]);
stacked_lr=((unsignedlong)hardfault_args[5]);
stacked_pc=((unsignedlong)hardfault_args[6]);
stacked_psr=((unsignedlong)hardfault_args[7]);
printf("[Hardfaulthandler]\n");
printf("R0=%x\n",stacked_r0);
printf("R1=%x\n",stacked_r1);
printf("R2=%x\n",stacked_r2);
printf("R3=%x\n",stacked_r3);
printf("R12=%x\n",stacked_r12);
printf("LR=%x\n",stacked_lr);
printf("PC=%x\n",stacked_pc);
printf("PSR=%x\n",stacked_psr);
printf("BFAR=%x\n",(*((volatileunsignedlong*)(0xE000ED38))));
printf("CFSR=%x\n",(*((volatileunsignedlong*)(0xE000ED28))));
printf("HFSR=%x\n",(*((volatileunsignedlong*)(0xE000ED2C))));
printf("DFSR=%x\n",(*((volatileunsignedlong*)(0xE000ED30))));
printf("AFSR=%x\n",(*((volatileunsignedlong*)(0xE000ED3C))));
exit(0);//terminate
return;
}
learning(2009-8-0511:
33:
53)
你可以通过写入如下代码进行测试:
__asmUndefinedInstruction(void)
{
DCI0xf123;
DCI0x4567;
BXLR;
}
Orcreateunalignedmultipleload/store
__asmBadAlignedLDM(void)
{
MOVSr0,#1
LDMr0,{r1-r2}
BXLR;
}
想更深入的了解该问题可以参考:
<>