痞子衡嵌入式:系統時鐘配置不當會致使i.MXRT1xxx系列下OTFAD加密啓動失敗


  你們好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給你們分享的是系統時鐘配置不當會致使i.MXRT1xxx系列下OTFAD加密啓動失敗問題git

  咱們知道,i.MXRT1xxx家族早期型號(RT1050/RT0160/RT1020)的硬件解密外設名字叫BEE,這個外設主要是配合FlexSPI外設去實現外接串行NOR Flash在線解密XIP執行用的。而到了最近的i.MXRT1xxx新型號(RT1010/RT1170)上,BEE外設被替換成了OTFAD外設,功能不變,解密效率獲得了很大提高,但客戶在使能OTFAD加密啓動時經常遇到App沒法正常運行問題,這其實跟OTFAD自身的一個時鐘小限制有關(這個限制在BEE上不存在),今天痞子衡就來好好聊一聊OTFAD的這個小限制:github

1、問題描述

  咱們以i.MXRT1010爲例,從恩智浦官網下載一個SDK包(痞子衡下的是v2.9.1),隨便選擇其中一個例程,就以最簡單的 \SDK\boards\evkmimxrt1010\demo_apps\led_blinky 爲例吧。編譯這個 led_blinky 工程(選擇 flexspi_nor_debug build,即XIP工程),獲得可執行文件(實際bin文件大小爲10KB左右),使用 NXP-MCUBootUtility 工具將可執行文件(led_blinky.out)下載進MIMXRT1010-EVK開發板中(下載時啓動模式爲2'b01,啓動時切換到2'b10),能夠看到板載綠色LED小燈(D25)會閃,例程是能夠正常工做的。微信

  如今讓咱們嘗試使能OTFAD加密,回到芯片下載模式依然藉助 NXP-MCUBootUtility 工具,將工具 Secure boot type 選項切換爲 OTFAD Encrypted Image Boot,其餘設置均默認(此時加密範圍是 0x60001000 - 0x60001fff,僅加密IVT等啓動頭,不含app),再次下載可執行文件(led_blinky.out),換到芯片啓動模式復位板子,例程依舊是正常工做的,看起來OTFAD加密啓動彷佛沒有問題。app

  讓咱們再進一步,將加密範圍設置爲0x60002000 - 0x60004fff,這時加密區域覆蓋到了整個app,從新按上述流程操做一遍,發現例程沒能正常工做,這時候OTFAD加密啓動出了問題,難道app區域不能被加密?那OTFAD加密還有啥意義?ide

  app區域固然能夠被加密,跟着痞子衡再作一次實驗,在 led_blinky.c 文件的 main() 函數中,咱們將時鐘配置函數 BOARD_BootClockRUN() 直接註釋掉或者在連接文件裏將其所有搞成 __ramfunc(即在芯片內部RAM裏執行這部分時鐘配置代碼),這個例程僅是利用SysTick定時翻轉GPIO,所以時鐘配置代碼去掉不影響正常運行,從新編譯工程再按上面流程操做一遍,這時候例程又能正常工做了,說明加密後的app是能被OTFAD正常解密執行的。函數

  如今的問題變成了爲什麼OTFAD加密啓動時,BOARD_BootClockRUN() 函數不能在Flash裏執行,這就是問題所在。工具

2、緣由分析

  關於上述問題的緣由,痞子衡先直接給答案,這是OTFAD外設自己的時鐘小限制,當OTFAD被使能時,若是被加密的app代碼是XIP執行,app裏作系統時鐘配置時要始終保證Core時鐘高於FlexSPI外設時鐘。若是Core時鐘低於FlexSPI時鐘,此時Core去訪問加密Flash區域,OTFAD沒法正常解密,會致使指令錯亂,發生系統故障flex

  咱們配合上面的i.MXRT1010系統時鐘樹來認真分析下OTFAD這個時鐘限制問題。芯片上電老是從BootROM執行,BootROM會先將Core配置到396MHz,將FlexSPI時鐘根據用戶放置在Flash偏移0x400處的FDCB裏的設定配到30MHz - 200MHz不等,再讀取Flash偏移0地址處OTFAD DEK KeyBlob數據使能OTFAD,而後讀取IVT等頭信息去跳轉到App。很顯然只加密IVT部分根本不受OTFAD限制的影響,這部分解析是在BootROM裏完成的,BootROM裏時鐘配置符合OTFAD時鐘限制要求。ui

// BootROM裏對Core時鐘配置
CCM_ANALOG->PFD_528[PFD3_FRAC] = 24,   PLL2 PFD3輸出 (528MHz * 18) / 24 = 396MHz
CCM->CBCMR[PRE_PERIPH_CLK_SEL] = 2,    時鐘來自PLL2 PFD3
CCM->CBCDR[PERIPH_CLK_SEL]     = 0,   內核時鐘來自CCM->CBCMR[PRE_PERIPH_CLK_SEL]
CCM->CBCDR[AHB_PODF]           = 0,   內核時鐘不分頻

// BootROM裏對FlexSPI時鐘配置
CCM_ANALOG->PFD_480[PFD0_FRAC] = x,    PLL3 PFD0輸出 (480MHz * 18) / x
CCM->CSCMR1[FLEXSPI_CLK_SEL]   = 3,    時鐘來自PLL3 PFD0
CCM->CSCMR1[FLEXSPI_CLK_SRC]   = 0,   FlexSPI時鐘來自CCM->CSCMR1[FLEXSPI_CLK_SEL]
CCM->CSCMR1[FLEXSPI_PODF]      = y,   FlexSPI時鐘作(y+1)分頻

  當BootROM跳轉到了App以後,咱們再來看看App裏對時鐘是怎麼配置的,就是BOARD_BootClockRUN()函數,能夠看到這個函數裏將內核頻率從BootROM設置的396MHz切換到外部OSC 24MHz。不管此時用戶FDCB裏對FlexSPI時鐘是多少配置,至少也會大於30MHz,那麼此時24MHz內核頻率必定會低於FlexSPI時鐘頻率,此時只要發生內核對Flash加密區域的訪問(時鐘配置代碼就在Flash裏執行),就觸發了OTFAD時鐘限制問題,App就會跑飛。加密

3、解決方案

  知道了緣由,解決方案就簡單了,在App時鐘配置裏,不要按照尋常套路去先將內核時鐘源切換到外部OSC再切到PLL,而是直接切到PLL上。好比i.MXRT1010內部有個PLL6(也叫Audio PLL),固定500MHz,正好是App要的最終內核頻率,咱們在BOARD_BootClockRUN()裏將Audio(Enet) PLL初始化設置代碼提到前面,刪掉原來的切換OSC設置代碼便可。

void BOARD_BootClockRUN(void)
{
    // 此處略去...
    /* Set Oscillator ready counter value. */
    CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(127);
-    /* Setting PeriphClk2Mux and PeriphMux to provide stable clock before PLLs are initialed */
-    CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); /* Set PERIPH_CLK2 MUX to OSC */
-    CLOCK_SetMux(kCLOCK_PeriphMux, 1);     /* Set PERIPH_CLK MUX to PERIPH_CLK2 */

    // 此處略去...
    /* Set IPG_PODF. */
    CLOCK_SetDiv(kCLOCK_IpgDiv, 3);
+     /* Init Enet PLL. */
+    CLOCK_InitEnetPll(&enetPllConfig_BOARD_BootClockRUN);
+    /* Set preperiph clock source. */
+    CLOCK_SetMux(kCLOCK_PrePeriphMux, 3);

    // 此處略去...
    /* Enable Audio PLL output. */
    CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK;
-    /* Init Enet PLL. */
-    CLOCK_InitEnetPll(&enetPllConfig_BOARD_BootClockRUN);
-    /* Set preperiph clock source. */
-    CLOCK_SetMux(kCLOCK_PrePeriphMux, 3);

    // 此處略去...
    /* Set SystemCoreClock variable. */
    SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
}

  最後再提一下,這個OTFAD時鐘限制問題在i.MXRT1170上一樣存在,解決思路與上面相似,痞子衡就再也不贅述了。

  至此,系統時鐘配置不當會致使i.MXRT1xxx系列下OTFAD加密啓動失敗問題痞子衡便介紹完畢了,掌聲在哪裏~~~

歡迎訂閱

文章會同時發佈到個人 博客園主頁CSDN主頁知乎主頁微信公衆號 平臺上。

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

相關文章
相關標籤/搜索