【STM32H7教程】第11章 STM32H7移植SEGGER的硬件異常分析


完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第11章       STM32H7移植SEGGER的硬件異常分析

本章節為大家介紹SEGGER的硬件異常分析代碼在MDK和IAR中的使用方法,在實際項目中比較有實用價值,因為我們經常會遇到進入硬件異常的情況。

11.1 初學者重要提示

11.2 移植方法

11.3 MDK鎖定硬件異常位置方法

11.4 IAR鎖定硬件異常位置方法

11.5 硬件異常原因分析

11.6 IAR注釋自帶的硬件異常

11.7 實驗例程

11.8 總結

 

 

11.1 初學者重要提示

  •   MDK本身也是支持硬件異常分析的,就是不夠直觀,此貼是MDK的硬件異常分析文檔:

http://www.armbbs.cn/forum.php?mod=viewthread&tid=21940

  •   IAR8帶的硬件異常分析比較好用,在本章11.6小節有說明。

11.2 移植方法

直接移植SEGGER的硬件異常代碼會有錯誤警告,這里針對IAR和MDK版本做了些簡單修改,方便大家移植到自己的工程里面。

  •   MDK版本移植

源文件位於本章配套例子的\User\segger\HardFaultHandlerMDK文件夾,添加如下兩個文件到工程里面即可。

 

  •   IAR版本移植

源文件位於本章配套例子的\User\segger\HardFaultHandlerIAR文件夾,添加如下兩個文件到工程里面即可。

 

在文件SEGGER_HardFaultHandler.c里面都添加了串口打印功能,方便不用編譯器的調試功能時,通過串口打印提示是否進入硬件異常。

#define ERR_INFO "\r\nEnter HardFault_Handler, System Halt.\r\n"

#if 1
{
    const char *pError = ERR_INFO;
    uint8_t i;

    for (i = 0; i < strlen(ERR_INFO); i++)
    {
        USART1->TDR = pError[i];
        /* 等待發送結束 */
        while((USART1->ISR & USART_ISR_TC) == 0);
    }    
}
#endif 

 

11.3 MDK鎖定硬件異常位置方法

以本章配套的例子為大家做個說明。

1、測試方法比較簡單,進入調試狀態,全速運行,然后按下K1按鍵,就會進入硬件異常中斷,此時停止調試,程序就會自動定位到如下位置:

 

2、在Watch1窗口添加變量_Continue

 

3、修改為任何非0數值,就可以繼續單步調試。這個代碼后面還有一個第1步中的while循環,也可以繼續采用第2步的方法修改。退出硬件異常后就是大家進入硬件異常前下一條要執行的指令(可能還是這個函數本身,因為一個函數由多個指令完成)。定位到出問題的位置:

 

11.4 IAR鎖定硬件異常位置方法

以本章配套的例子為大家做個說明。

1、測試方法比較簡單,進入調試狀態,全速運行,然后按下K1按鍵,就會進入硬件異常中斷,此時停止調試,程序就會自動定位到如下位置:

 

2、在Watch1窗口添加變量_Continue

 

3、修改為任何非0數值,就可以繼續單步調試。這個代碼后面還有一個第1步中的while循環,也可以繼續采用第2步的方法修改。退出硬件異常后就是大家進入硬件異常前下一條要執行的指令(可能還是這個函數本身,因為一個函數由多個指令完成)。定位到出問題的位置:

 

11.5 硬件異常原因分析

SEGGER提供的這個機制查找出問題的位置比較方便,具體原因需要繼續在調試界面里面添加HardFaultRegs結構變量,這個結構體變量添加了所有大家想看的東西。下面是MDK調試狀態查看部分結構體數值:

 

具體上面的變量代表什么含義呢,代碼里面有注釋,查閱起來沒有IAR自帶的硬件異常提示方便(注意,下面的代碼用到了位域)。

#if DEBUG
static volatile unsigned int _Continue;  // Set this variable to 1 to run further

static struct {
  struct {
    volatile unsigned int r0;            // Register R0
    volatile unsigned int r1;            // Register R1
    volatile unsigned int r2;            // Register R2
    volatile unsigned int r3;            // Register R3
    volatile unsigned int r12;           // Register R12
    volatile unsigned int lr;            // Link register
    volatile unsigned int pc;            // Program counter
    union {
      volatile unsigned int byte;
      struct {
        unsigned int IPSR : 8;           // Interrupt Program Status register (IPSR)
        unsigned int EPSR : 19;          // Execution Program Status register (EPSR)
        unsigned int APSR : 5;           // Application Program Status register (APSR)
      } bits;
    } psr;                               // Program status register.
  } SavedRegs;

  union {
    volatile unsigned int byte;
    struct {
      unsigned int MEMFAULTACT    : 1;   // Read as 1 if memory management fault is active
      unsigned int BUSFAULTACT    : 1;   // Read as 1 if bus fault exception is active
      unsigned int UnusedBits1    : 1;
      unsigned int USGFAULTACT    : 1;   // Read as 1 if usage fault exception is active
      unsigned int UnusedBits2    : 3;
      unsigned int SVCALLACT      : 1;   // Read as 1 if SVC exception is active
      unsigned int MONITORACT     : 1;   // Read as 1 if debug monitor exception is active
      unsigned int UnusedBits3    : 1;
      unsigned int PENDSVACT      : 1;   // Read as 1 if PendSV exception is active
      unsigned int SYSTICKACT     : 1;   // Read as 1 if SYSTICK exception is active
      unsigned int USGFAULTPENDED : 1;   // Usage fault pended; usage fault started but was replaced by a
 higher-priority exception
      unsigned int MEMFAULTPENDED : 1;   //  Memory management fault pended; memory management fault started
 but was replaced by a higher-priority exception
      unsigned int BUSFAULTPENDED : 1;   // Bus fault pended; bus fault handler was started but was replaced
 by a higher-priority exception
      unsigned int SVCALLPENDED   : 1;   // SVC pended; SVC was started but was replaced by a higher-priority
 exception
      unsigned int MEMFAULTENA    : 1;   // Memory management fault handler enable
      unsigned int BUSFAULTENA    : 1;   // Bus fault handler enable
      unsigned int USGFAULTENA    : 1;   // Usage fault handler enable
    } bits;
  } syshndctrl;                          // System Handler Control and State Register (0xE000ED24)

  /* 省略未寫 */

  volatile unsigned int afsr;            // Auxiliary Fault Status Register (0xE000ED3C), Vendor controlled (optional)
} HardFaultRegs;
#endif

 

11.6 IAR自帶的硬件異常分析

還以本章配套的例子為例,進入調試狀態,全速運行,然后按下K1按鍵,就會進入硬件異常中斷,此時停止調試,IAR還會彈出一個硬件異常錯誤分析,剛進來的時候也許是個空白

 

單步調試刷新下就出來了:

 

指出了問題的原因是操作的數據地址有問題。

11.7 實驗例程

專門為本章節配套了一個例子:V7-009_移植SEGGER的硬件異常分析機制。大家可以按照本章教程提供的方法進行測試。

11.8 總結

除了SEGGER的硬件異常分析方案,建議也測試下MDK和IAR的,以后遇到硬件異常問題,解決起來可以得心應手。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM