STM32 HardFault 調試定位

Cortex-M3/M4/M7 Fault Exceptions

問題的產生

無論是在什麼平臺,什麼環境下寫代碼,都免不了利用一些工具去調試Bug。諸如在Windows下利用vs開發,會使用IDE集成的調試器,或者在linux下進行C開發,使用gdb打印段錯誤的棧信息。而使用Keil進行嵌入式編程的時候,我們也會遇到很多諸如‘段錯誤’的情況,這個時候我們就需要利用環境的工具去了解發生了什麼樣的問題,然後定位問題發生的位置,並解決問題。

理論背景

大部分嵌入式設備使用的STM32芯片採用的都是Cortex-M3核,架構採用錯誤異常的機制來檢測問題,當核心檢測到一個錯誤時,異常中斷會被觸發,並且核心會跳轉到相應的異常終端處理函數執行,錯誤異常的終端分爲以下四種:

  1. HardFault
  2. MemManage
  3. BusFault
  4. UsageFault

鎖定問題的位置

區分這些錯誤對問題的解決意義不大(一般的情況下默認的配置只會開啓HardFault錯誤)。舉個例子,當你手寫了一個雙向鏈表去動態申請空間存儲你的業務信息,結果你發現程序剛在板子上在線仿真就死了的時候,你心裏清楚肯定是你的代碼哪裏有了問題,只是你想知道代碼是死了在哪裏。你暫停程序執行之後,你會發現程序進入了下邊的中斷處理程序:

>void HardFault_Handler(void)
>{
>  /* Go to infinite loop when Hard Fault exception occurs */
>       while (1)
  		{
  		}
>}

這個時候我們按照正常的調試步驟,去菜單欄View中找到Call Stack Window,打算看看自己bug的位置的時候,卻赫然發現Call Stack中只有HardFault_Handler一個函數的棧信息。從View中打開Registers Window,可以看到LR的值爲0xFFFFFFF9,顯然這是一個非法的值,IDE無法通過這個地址還原到上一級的代碼段,所以顯示的只有當前函數的信息,因爲Cortex-M3的堆棧寄存器是banked,所以觀察LR的Bit[2]位,其爲0,所以當前的堆棧指針用的是MSP,點開View中的Memory Windows,將MSP的地址輸入Address文本框,根據下圖中找到在異常之前壓入棧的信息:
在這裏插入圖片描述
找到LR,在彙編的視圖右鍵打開Show Disassembly at Address,輸入從堆棧中找到了LR寄存器內的地址信息,往上退一個指令,或者就是這個指令導致了程序進入了異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章