痞子衡嵌入式:揭祕i.MXRT600的ISP模式下用J-Link連線後PC總是停在0x1c04a的原因(Debug Mailbox)

痞子衡發表於2020-11-23

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT600中的Debug Mailbox實現對JLink除錯的影響

  事情緣起痞子衡的同事 - 喜歡打破砂鍋問到底的Kerry小姐姐,她最近在研究i.MXRT600這款晶片,她發現在晶片ROM序列下載(ISP)模式下,連上晶片USB埠可以在裝置管理器中正常看到列舉的HID裝置(0x1fc9,0x0020),這個HID裝置可配合上位機工具blhost.exe進行應用程式下載。但是當使用JLink正常連上晶片(選擇的是MIMXRT685,不是CM33)後,之前的那個HID裝置不見了,看起來晶片像是退出了ROM正常執行,這個體驗跟i.MXRT1050上不太一樣,這是為什麼?這其實是Debug Mailbox在搗鬼,且聽痞子衡細聊:

一、引出除錯問題

  按照我們之前在i.MXRT1050上的除錯經驗,將晶片設為序列下載模式後,使用JLink連線上晶片,並halt住核心,此時晶片PC是正常停在ROM區域的(0x200000之後),讓我們同樣的過程在i.MXRT600上也操作一次:

  我們發現PC指向了0x1c04a,並且不管你如何reset再重新halt,它一直停在這個地方,更奇怪的是這個地方不在ROM區域(0x03000000或0x13000000之後)裡,這是怎麼回事?

二、什麼是Debug Mailbox?

  與i.MXRT1050不同的是,i.MXRT600中引入了Debug Mailbox機制,這個機制由ROM負責實現,因此連線上JLink後的行為是由Debug Mailbox機制決定的。

  翻開i.MXRT600的User Manual,在Debug subsystem這一章節可以找到Debug Mailbox相關資訊,Debug Mailbox其實最早是NXP LPC系列新推的一項功能,後來也用在了i.MXRT600上面。

  下圖是i.MXRT600的SWD除錯系統內部連線圖,其中藍框標出的DM AP便是Debug Mailbox。

  我們知道i.MXRT600是基於Cortex-M33核心的MCU,這款ARM核心主打特點是安全,因此NXP在設計晶片時也加入了很多安全方面的特性,Debug Mailbox便是其一,Debug Mailbox基於NXP debug authentication protocol version 1.0,主要作用是實現外部偵錯程式與晶片內ROM的通訊,從而賦予偵錯程式擦寫Flash、進入ROM ISP、除錯認證等功能。

三、ROM中Debug Mailbox實現

  那麼ROM中的Debug Mailbox機制到底是什麼?簡單理解就是如下一段程式碼插入了ROM的初始化流程。這個機制其實很簡單,就是確保debug特性是正常開啟的,然後根據晶片復位型別來初始化debug port並決定要不要進入Mailbox命令處理。

// 確認IFR裡debug特性正常開啟
if (kStatus_DBG_Success != debug_auth_evaluate_dcfg_socu())
{
    __set_FAULTMASK(1);
    __WFI();
}
volatile uint32_t reset_status = RSTCTRL0->SYSRSTSTAT;
// 根據復位型別設定初始debug port狀態
if (kStatus_DBG_Success != debug_auth_hal_set_initial_debug_port_state(reset_status))
{
    __set_FAULTMASK(1);
    __WFI();
}
if (reset_status & 0x20)
{
    // 處理mailbox收到的來自debugger的命令
    debug_mailbox_GetRequest();
}

  RSTCTRL0->SYSRSTSTAT[5]位即ARM_APD_RESET,表明ARM核心是否發生了軟復位(warm reset),正常晶片上電,這個位不會被置1,但是如果有偵錯程式接入給核心發軟復位,這個位就會被置位。一旦這個位被置起來,ROM初始化過程中便會進入Mailbox命令處理函式debug_mailbox_GetRequest(),不再往後執行正常的ROM序列下載/啟動流程。

  debug_mailbox_GetRequest()函式是Debug Mailbox機制的核心,它藉助的是如下三個Mailbox暫存器來實現偵錯程式與ROM的互動。

  • CSW:命令狀態暫存器,偵錯程式操作這個暫存器指示ROM進入mailbox命令解析狀態
  • REQUEST:請求暫存器,偵錯程式將mailbox命令寫入這個暫存器指示ROM去執行
  • RETURN:結果暫存器,偵錯程式通過讀這個暫存器獲取ROM執行mailbox命令結果

  對於使用者來說,一般藉助偵錯程式先向CSW暫存器寫入0x21申請re-sync同時reset device ,然後再按需寫入如下具體的命令進REQUEST暫存器,便可實現Debug Mailbox相應功能。

#define ENTER_DEBUGGER_MAILBOX (0x0001)  // Start Mailbox debug
#define GET_CRP_LEVEL          (0x0002)  // Deprecated and retuen 3
#define DM_ERASE_FLASH         (0x0003)  // Mass erase flash
#define EXIT_DEBUGGER_MAILBOX  (0x0004)  // Exit Mailbox debug
#define ENTER_ISP_MODE         (0x0005)  // Enter specified ISP mode
#define SET_FA_MODE            (0x0006)  // Set to "Fault Analysis" mode
#define START_DEBUG_SESSION    (0x0007)  // Start Debug session
#define DEBUG_AUTH_START       (0x0010)  // Start Debug Authentication Protocol
#define DEBUG_AUTH_RESP        (0x0011)  // Debug Authentication response

  瞭解了Debug Mailbox機制原理,我們再來看JLink連線i.MXRT600時必須要載入執行的如下Script內容(開頭痞子衡說了必須選擇MIMXRT685,而不是CM33,因為在JLink DLL / JLinkDevices.xml裡MIMXRT685才預設指定了配套Script指令碼)。關於JLink Script知識,可以先看痞子衡之前文章 《JLink Script檔案基礎及其在IAR下呼叫方法》

  這個指令碼內容其實在i.MXRT600的User Manual中已經給出了相應虛擬碼,通過呼叫JLINK_CORESIGHT_WriteAP()來寫Mailbox暫存器(index 0對應CSW,index 1對應REQUEST),基本是按照前面介紹的Debug Mailbox使用流程來的,最後通過寫入START_DEBUG_SESSION命令進REQUEST暫存器開啟晶片除錯模式。

void InitTarget(void) {
  int v;

  JLINK_CORESIGHT_Configure("IRPre=0;DRPre=0;IRPost=0;DRPost=0;IRLenDevice=4");
  // Pre-select that we have a Cortex-M33 connected
  CPU = CORTEX_M33;
  // J-Link is allowed to use a TAP reset for JTAG-chain auto-detection
  JTAG_AllowTAPReset = 0;

  JTAG_SetDeviceId(0, 0x6BA02477);

  // Read AP ID register to identify DM AP at index 2
  JLINK_CORESIGHT_WriteDP(2, 0x020000f0);
  v = JLINK_CORESIGHT_ReadAP(3);
  JLINK_SYS_Report1("DAP-IDCODE:", v);
  // Select DM AP index 2
  JLINK_CORESIGHT_WriteDP(2, 0x02000000);
  JLINK_CORESIGHT_ReadDP(0);

  // Active DebugMailbox
  JLINK_CORESIGHT_WriteAP(0, 0x21);
  JLINK_CORESIGHT_ReadAP(0);

  // Enter Debug Session
  JLINK_CORESIGHT_WriteAP(1, 0x07);
  JLINK_CORESIGHT_ReadAP(0);
}

五、晶片除錯模式(REQUEST = 0x07)下的狀態

  前面講了JLink Script會使晶片進入除錯模式,那除錯模式下晶片到底是什麼狀態?ROM其實是通過如下函式載入執行了0x1c040 - 0x1c04B處的一小段程式碼,並最終停在了0x1c04a處的while(1);,至此真相大白。

void go_debug_mode(void)
{
#define VECTOR_DUMMY_ROUTINE 0x0001c000u
#define APP_ENTRY (VECTOR_DUMMY_ROUTINE + 0x40 + 1)
    uint32_t dummy_loop_routines[] = {
        VECTOR_DUMMY_ROUTINE + 0x1000, // SP
        APP_ENTRY,                     // Reset Handler
        APP_ENTRY,                     // NMI Handler
        APP_ENTRY,                     // HardFault_Handler
        APP_ENTRY,                     // MemManage_Handler
        APP_ENTRY,                     // BusFault_Handler
        APP_ENTRY,                     // UsageFault_Handler
        APP_ENTRY,                     // SecureFault_Handler
        0,                             // Reserved
        0,                             // Reserved
        0,                             // Reserved
        APP_ENTRY,                     // SVC_Handler
        APP_ENTRY,                     // DebugMon_Handler
        0,                             // Reserved
        APP_ENTRY,                     // PendSV_Handler
        APP_ENTRY,                     // SysTick_Handler
        // Below are the binary codes for : 
        //   register uint32_t dummy = SCB->CPUID; 
        //   while(1);
        0x5000f64eu,
        0x0000f2ceu,
        0xe7fe6801u,
    };

    {
        uint32_t *dest = (uint32_t *)VECTOR_DUMMY_ROUTINE;
        uint32_t *src = (uint32_t *)&dummy_loop_routines[0];
        for (uint32_t i = 0u; i < ARRAY_SIZE(dummy_loop_routines); i++)
        {
            *dest++ = *src++;
        }
        jump_to_boot_image(VECTOR_DUMMY_ROUTINE);
    }
}

六、Debug Mailbox對JLink除錯的影響

  基於上面分析,最後痞子衡再總結一下Debug Mailbox對JLink除錯的影響:

  1. 當晶片在ROM中執行(比如ISP模式,比如Flash中沒有應用程式)時,JLink要想正常連線,必須載入使能晶片除錯模式的Script才行,否則會連不上晶片。
  2. 通過載入執行JLink Script成功連線上晶片後,PC總是停在0x1c04a,這是Debug Mailbox機制決定的。
  3. 只有當晶片正常啟動Flash裡的應用程式後(即離開了ROM),用JLink連線晶片(選擇CM33,不載入Script),halt住核心,PC指向的才是真實的應用程式位置。

  至此,i.MXRT600中的Debug Mailbox實現對JLink除錯的影響痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時釋出到我的 部落格園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

相關文章