痞子衡嵌入式:FlexSPI復位方式不當會致使i.MXRT系列下OTFAD加密啓動失敗


  你們好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給你們分享的是FlexSPI復位方式不當會致使i.MXRT系列下OTFAD加密啓動失敗問題html

  本篇是《系統時鐘配置不當會致使i.MXRT1xxx系列下OTFAD加密啓動失敗》 的後續篇,咱們爲i.MXRT1010解決了OTFAD時鐘配置限制問題後,加密的App就必定能正常跑了嗎?其實並不必定,若是你的App跟IAP有關(即會調用FlexSPI驅動去擦寫Flash),免不了會在FlexSPI驅動裏操做FlexSPI外設寄存器的軟復位位,軟復位操做方式使用不當可能會致使App沒法正常運行,今天痞子衡就來好好聊一聊這個FlexSPI復位小限制:微信

  • Note1: 雖然i.MXRT1170也包含OTFAD,可是本文中的FlexSPI復位限制問題在i.MXRT1170上並不存在。
  • Note2: 三位數系列i.MXRT600一樣包含OTFAD,且也受本文中的FlexSPI復位限制影響。

1、問題描述

  從恩智浦官網下載一個SDK包(痞子衡下的是v2.9.1),選擇其中 flexspi 例程 \SDK\boards\evkmimxrt1010\driver_examples\flexspi\nor\polling_transfer\ 。編譯這個 flexspi_nor_polling_transfer 工程(選擇 flexspi_nor_debug build,即XIP工程),獲得可執行文件,將其下載到 MIMXRT1010-EVK 板載Flash中離線啓動(正常模式,不加密),打開串口調試助手看到以下結果:app

  這個結果是例程預期結果,你可能會對這個XIP build也能擦寫Flash感到奇怪,按說板載Flash沒有RWW功能,擦寫Flash操做不能在Flash裏原地執行,可是例程的連接文件裏已經將涉及Flash擦寫代碼的源文件直接放在RAM裏了,所以例程是能夠正常執行的。函數

  如今讓咱們根據《系統時鐘配置不當會致使i.MXRT1xxx系列下OTFAD加密啓動失敗》 文中操做使能OTFAD加密,將整個App空間都加密,記得要修復系統時鐘配置限制問題,這時候再離線啓動,看到串口調試助手沒有任何輸出,說明例程執行失敗了。查看工程源代碼,main()函數裏第一句打印前調用了 flexspi_nor_flash_init(EXAMPLE_FLEXSPI);, 看起來OTFAD加密後這個Flash初始化函數執行不太正常。flex

  爲了定位問題方便,咱們回到不加密模式,給 flexspi_nor_polling_transfer 工程加上一些輔助調試的打印信息,主要是FlexSPI相關API函數調用前加上打印信息。注意:須要將以下三個源文件也放到RAM中才能看到控制檯完整輸出。ui

initialize by copy {
  object fsl_debug_console.o,
  object fsl_adapter_lpuart.o,
  object fsl_lpuart.o,
};

  有了輔助打印信息,咱們如今再回到OTFAD加密模式,能夠看到代碼停在 FLEXSPI_UpdateLUT() 函數就沒有繼續執行下去了。本文不是爲了講述如何一步步找到問題的方法,痞子衡其實知道就是 FLEXSPI_SoftwareReset() 函數惹的禍(沒有停在這個函數,是因爲系統buffer的緣故),至因而什麼緣由,詳見下節。加密

static inline void FLEXSPI_SoftwareReset(FLEXSPI_Type *base)
{
    base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
    while (0U != (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK))
    {
    }
}

2、緣由分析

  老規矩,痞子衡直接給答案,這是OTFAD對FlexSPI外設復位的小限制,當OTFAD被使能時,若是被加密的app代碼是XIP執行,app裏利用FlexSPI->MCR0[SWRESET]位作復位時,這個swreset復位功能會同時清掉FlexSPI->INTR[KEYDONE]位,而FlexSPI的運行依賴OTFAD解析KeyBlob的結果,當FlexSPI->INTR[KEYDONE]位是0時,對Flash的AHB訪問會被禁掉,故而發生CPU lockup,代碼沒法繼續執行。.net

KEYDONE位爲1 - 代表OTFAD解析KeyBlob已正常完成;
KEYDONE位爲0 - 代表OTFAD正在解析KeyBlob過程當中;

  FlexSPI->MCR0[SWRESET]位存在於任何一款i.MXRT芯片型號中,其功能是復位FlexSPI外設,在下面幾個場景均可以去作一次FlexSPI外設復位,不用擔憂,這個外設復位並不影響FlexSPI配置寄存器裏的值。不過比較遺憾的是在此時的OTFAD加密啓動使能情形下,不能再用MCR0[SWRESET]位去作復位了debug

場景一:初始化FlexSPI,打開MCR0[MDIS]位使能模塊時
場景二:更新了FlexSPI的LUT表後
場景三:切換了FlexSPI的工做模式後(好比使能Flash四線)
場景四:完成了FlexSPI的擦、寫命令後

3、解決方案

  不少時候FlexSPI->MCR0[SWRESET]位更可能是被用來清除AHB TX/RX Buffer(尤爲是在Flash擦寫以後),在i.MXRT1010 FlexSPI外設的AHBCR寄存器裏其實新增了單獨的CLRAHBTXBUF和CLRAHBRXBUF控制位,用以實現AHB TX/RX Buffer的清除。所以咱們爲了不影響OTFAD加密啓動,可使用AHBCR[CLRAHBTXBUF/CLRAHBRXBUF]位來代替MCR0[SWRESET]位去作復位。調試

  所以在 flexspi_nor_polling_transfer 工程裏,將FLEXSPI_SoftwareReset()函數調用所有改爲以下的FLEXSPI_ClearAhbBuffer()函數調用就能夠保證工程正常運行了。

static inline void FLEXSPI_ClearAhbBuffer(FLEXSPI_Type *base)
{
#if defined(FSL_FEATURE_SOC_OTFAD_COUNT) && defined(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK)
    base->AHBCR |= FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK;
    base->AHBCR &= ~(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK);
#endif
}

  至此,FlexSPI復位方式不當會致使i.MXRT系列下OTFAD加密啓動失敗問題痞子衡便介紹完畢了,掌聲在哪裏~~~

歡迎訂閱

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

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

相關文章
相關標籤/搜索