一则Keil运行时跳转到HardFault_Handler错误处理中断的问题与解决

📅 2026/7/3 10:41:38 👁️ 阅读次数 📝 编程学习
一则Keil运行时跳转到HardFault_Handler错误处理中断的问题与解决

这两天在调试Keil时,发现前两天跑得好好的代码突然不能运行的。一运行就会跑到HardFault_Handler错误处理中断中去。

程序代码比较简单,就是向Uart口发送一串数据。按道理来说,即使这些数据是乱码,也不应该跳转到错误处理呀。

在HardFault_Handler中加入断点,运行到此,打开CallStack+Local监测窗口,在HardFault_Handler项上点击右键,选择“Show Caller code”。发现在Disassembly界面最终的跳转的不是正常的函数,而是“0x3030302C 0000 MOVS r0,r0"这段代码。这就有点奇怪了,按说正常的函数调用入栈出栈不会出现这种无函数的入口错误的。难道是分配的堆栈长度不够了?

打开starup_stm32f10x_md.s,最上面Stack_Size 值为0x400,Heap_Size为0x200,调大堆栈长度,将Stack_Size 值修改为0x800,Heap_Size修改为0x400。再次运行,仍然是同样的问题。

逐一在主函数中加断点,找到运行就会出错的主要函数,再在这个函数内部逐行加断点,一步步调试寻找子函数,最终发现是一个向串口写数据的子函数运行后就会跳转到错误中断处理函数。

在此函数中,乍一看并未发现错误:

uint16_t ShowMainPage(){ uint8_t *ToSendBuf=&TmpBuf[0]; uint8_t *OldPtr=ToSendBuf; uint8_t *LenPtr; char aStr[50]; uint16_t FrameLen; sprintf(aStr,"%f",DistFlux); ToSendBuf+=ShowLcd_Str(lcdvarFlux ,ToSendBuf,aStr); sprintf(aStr,"%d",RunTime) ; ToSendBuf+=ShowLcd_Str(lcdvarRunTime ,ToSendBuf,aStr); sprintf(aStr,"%d",RevAngle); ToSendBuf+=ShowLcd_Str(lcdvarRevAngle,ToSendBuf,aStr); sprintf(aStr,"%d",StopTime); ToSendBuf+=ShowLcd_Str(lcdvarStopTime,ToSendBuf,aStr); FrameLen=ToSendBuf-OldPtr; SendOut(&TmpBuf[0],FrameLen); return(FrameLen);//返回字节数 }

这个函数也可以运行到函数末尾,而不是在中间就跳转到错误中断处。

仔细检查发现,第一个sprintf函数中,使用的是”%f"格式化字符,但实际上DistFlux是个整数,将%f改为%d后,运行恢复正常。

结论:sprintf函数不匹配的格式化字符和数据,会导致系统堆栈在返回函数时错误。推测与此相关的函数,比如printf函数也可能会出现此类问题。