首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

stm32 hard fault及堆栈探究

stm32 hard fault及堆栈探究

hard fault
在调试RTC过程中,程序在主循环中执行两次后就进入hard fault的while(1)中断,keil显示调试窗口显示imprecise data bus error。完善RTC配置的时序也无济于事。网上查到一些hard fault的资料:
<STM32F10xxx Cortex-M3 programming manual>2.3.2对hard fault, bus fault等有具体的解释。keil的网站上http://www.keil.com/appnotes/files/apnt209.pdf也有概括性的解释:hard fault由bus fault, memory management fault或usage fault引起,前者有固定的仅次于NMI的高优先级;调试过程中出现的bus error属于bus fault,是取指或取值时的内存错误。ST论坛上对于hard fault的讨论,大牛们说:
是由于读写了一个非法位置,
“100% of the hard faults I've had are caused by variables accessing out of bounds. ”,
"The Cortex-M3 pushes fault context on to the stack (some 8 dwords as I recall), I think Joseph Yiu has some example of instrumenting this. This could should permit you to determine the faulting PC. With this and the register info, and a map file you should be able to zero in on what is going on.
                MRS     R0, PSP         ; Read PSP
                LDR     R1, [R0, #24]    ; Read Saved PC from Stack" 能看到出错的PC值倒是一个很方便的事情,不过还没试过。
还有若干链接,未及一一详看,先备着:https://my.st.com/public/STe2ecommunities/mcu/Lists/ARM%20CortexM3%20STM32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fARM%20CortexM3%20STM32%2fHard%20Fault%20error&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000626BE2B829C32145B9EB5739142DC17E&currentviews=1147http://forums.arm.com/lofiversion/index.php?t13632.htmlhttps://my.st.com/public/STe2ecommunities/mcu/Lists/ARM%20CortexM3%20STM32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FARM%20CortexM3%20STM32%2FHardFault%20Exception%20Why%20oh%20why%21http://www.google.com/search?hl=en&q=Joseph+Yiu+hard+fault+exception+handler
论坛里大家都说到了Joseph Yiu,哪天要好好拜读一下他的CortexM3权威指南。

回头看自己的程序,从最简逻辑开始烧写运行,发现当增加到在Time_Display()时进入了hard fault。检查代码,函数中定义了一个char类型数组,用于存放需要显示到LCD上的时间字符串,但数组长度小于字符串长度。增大长度,就解决了问题。果然如大牛们所说,问题存在于数组越界。

之前我也犯过类似错误,可当时的现象是,串口实际发出的数据和数组中的数据相比,后半部分时对时错。当时的变量为全局变量,此处变量为局部变量。查到如下说明:“一个由c/C++编译的程序占用的内存分为以下几个部分: 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放. 4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放. 5、程序代码区—存放函数体的二进制代码。”全局变量储存在全局区,它的越界将影响其他变量的值,对程序运行不会有致命影响。局部变量在栈中,同时入栈的还有函数的回退地址,函数参数等。本次出现问题的代码段为:
[cpp] view plaincopy

  • void Time_Show(void)  
  • {  
  •     while (1)  
  •     {  
  •         /* If 1s has been elapased */
  •         if (TimeDisplay == 1)  
  •         {  
  •             uint32_t Counter = 0;  
  •             Counter = RTC_GetCounter();  
  •             Time_Display(Counter);  
  •             TimeDisplay = 0;  
  •         }  
  •     }  
  • }  

  • void Time_Display(uint32_t TimeVar)  
  • {  
  •     uint32_t THH = 0, TMM = 0, TSS = 0;  
  •     char buf[10];  
  •     /* Reset RTC Counter when Time is 23:59:59 */
  •     if (TimeVar == 0x0001517F)  
  •     {  
  •         RTC_WaitForLastTask();  
  •         RTC_SetCounter(0x0);  
  •         /* Wait until last write operation on RTC registers has finished */
  •         RTC_WaitForLastTask();  
  •     }  

  •     /* Compute  hours */
  •     THH = TimeVar / 3600;  
  •     /* Compute minutes */
  •     TMM = (TimeVar % 3600) / 60;  
  •     /* Compute seconds */
  •     TSS = (TimeVar % 3600) % 60;  

  •     /*  sprintf(buf, "0x%08x", buf);     
  •     sprintf(buf, "0x%08x", &TimeVar);   
  •     sprintf(buf, "0x%08x", &THH);   
  •     sprintf(buf, "0x%08x", &TMM);   
  •     sprintf(buf, "0x%08x", &TSS);
  •     */
  •     sprintf(buf, "%0.2d:%0.2d:%0.2d", THH, TMM, TSS);  
  •     LCD_DisplayStringLine(LCD_LINE_1, buf);  
  • }  
继承事业,薪火相传
返回列表