痞子衡嵌入式:揭秘i.MXRT1060,1010上串行NOR Flash冗余程序啟動設計



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT1060,1010上串行NOR Flash冗余程序啟動設計

  工業產品設計里經常會有冗余程序/備份程序設計的需求,因為在工業環境里要求設備能夠持續穩定運行,不能輕易宕機,但現實環境中常常有各種意外發生,其中一個常見的意外就是設備主控 MCU 程序被破壞。為了降低程序損壞這種意外帶來的影響,一個很典型的做法就是增加 MCU 程序的份數,第一份被破壞,就啟動第二份...,用程序數量的增加來降低啟動失敗率,這屬於概率學手段范疇。

  我們知道恩智浦 i.MXRT 系列 MCU 內部沒有非易失性存儲器,它需要搭配外部存儲器來工作,可選存儲器類型非常多: NOR Flash, NAND Flash, eMMC, SD卡都行。其中對於 NAND 型存儲器,冗余程序設計是必備的,因為 NAND 本身允許壞塊現象存在,所以不得不做冗余設計。而對於 NOR 型存儲器,冗余設計則不是必需的,偏偏串行 NOR Flash 是 i.MXRT 最常用的搭檔,那該怎么辦?別急,今天痞子衡介紹的就是 i.MXRT1010/1060 上串行 NOR Flash 冗余程序設計,恩智浦已經都給你考慮到了。

  • Note:本文所涉及的串行 NOR Flash 冗余程序設計在早期的 i.MXRT1050/1020/1015 型號上不被支持。

一、初識冗余程序啟動

  在 i.MXRT 上可以掛載串行 NOR Flash 去啟動程序的外設有兩個,分別是 FlexSPI 和 LPSPI,如下圖所示。其中連接在 FlexSPI 上的 Flash A 屬於主啟動設備,連接在 LPSPI 上的 Flash B 屬於備份啟動設備(關於備份設備啟動詳見痞子衡舊文 《從Serial(1-bit SPI) EEPROM/NOR恢復啟動》)。

  • Note: 並不是所有 i.MXRT 型號都支持 LPSPI 外設掛載存儲器去啟動。

  用兩片 NOR Flash 去完成冗余程序設計當然是沒問題,但也相應增加了硬件成本,而本文今天要討論得不是這種冗余程序設計,我們要聊的是在一片掛載在 FlexSPI 上的串行 NOR Flash 里做冗余程序設計,就是圖中的 image 0 和 image 1。

  冗余程序啟動流程其實特別簡單,上電永遠先啟動物理地址靠前的 image 0,如果 image 0 被破壞了,則啟動 image 1。原則上 image 0 和 image 1 應該是完全一樣的(鏈接地址也一樣,並且中途不需要搬移這兩份 image 數據,這個是靠芯片里的一個黑科技做到的,下文會細講),畢竟是冗余設計,不過你要執意放兩份不完全一樣的 image,倒也沒問題。

二、實測冗余程序啟動

  我們知道 i.MXRT 芯片上電總是先運行廠商固化好的 BootROM,所以冗余程序啟動設計是做在 BootROM 代碼里的。痞子衡之前有一篇舊文 《了解i.MXRT1060系列ROM中串行NOR Flash啟動初始化流程優化點》 中 2.1 節其實已經簡單地提到了冗余程序設計,其主要借助了芯片系統 FlexSPI 地址重映射(Remap)功能,這個功能是在恩智浦后期推出的 i.MXRT1060/1010 等型號上才有的,這也是上文所說的黑科技。關於這個黑科技,痞子衡也有舊文 《利用i.MXRT1060,1010上新增的FlexSPI地址重映射(Remap)功能可安全OTA》

  有了 FlexSPI Remap 黑科技存在,我們就可以將同一份 image binary 放在 Flash 中兩個不同位置,並且不用做擦除編程操作來交換其位置,就可以實現各自的啟動執行。如果沒有這個黑科技,我們只能老老實實做數據搬移,這會增加擦除次數從而影響 Flash 使用壽命。

  原理搞清楚了,現在我們在板子上實測一下這個功能,看看如何正確地放兩份 image 進 Flash,哪些情況會導致 image 0 啟動失敗從而去啟動 image 1。我們就以恩智浦官方 MIMXRT1060-EVK 開發板為例,這個板子 FlexSPI1 上掛了兩片 Flash,默認連接的 8MB QuadSPI Flash,還有一片 64MB HyperFlash(需要做板子改動才能使能):

2.1 使能冗余程序啟動

  使能冗余程序啟動特性很簡單,就是將 fuse 0x6E0[23:16] - FLEXSPI_NOR_SEC_IMAGE_OFFSET 燒錄為非 0 值即可,根據下面定義,第二份 image 偏移地址最大可以設到 Flash 中 0x3FC0000(63.75MB)處:

                                                  Remap功能的ADDR_START寄存器固定設為 Flash 起始映射地址。
fuse 0x6e0[15:13] - xSPI_FLASH_IMAGE_SIZE,       App的最大長度,標識了第一份App的結束地址,該值加上ADDR_START后被填入Remap功能的ADDR_END寄存器。
fuse 0x6e0[23:16] - FLEXSPI_NOR_SEC_IMAGE_OFFSET,標識了第二份App的起始地址(在Flash中偏移位置),即填入Remap功能的ADDR_OFFSET寄存器的值。

  本次測試,我們就將 FLEXSPI_NOR_SEC_IMAGE_OFFSET 燒錄為 0x10,xSPI_FLASH_IMAGE_SIZE 保持默認 0,即第二份 image 偏移地址在 Flash 0x400000(4MB)處,最大 image 長度也是 4MB,可借助 MCUBootUtility 工具完成 Fuse 燒錄:

2.2 下載兩份無簽名 image 進 Flash

  現在開始准備 image,我們就直接用 \SDK_2.10.1_EVK-MIMXRT1060\boards\evkmimxrt1060\demo_apps\led_blinky 例程,簡單直觀。為了便於肉眼分辨效果,我們生成兩個稍微不一樣的 image,閃燈間隔時間一個是 200ms(image 0 - iled_blinky_delay200ms.bin),另一個是 2s(image 1 - iled_blinky_delay2s.bin):

  然后還是借助 MCUBootUtility 工具,先使用 All-In-One 操作將 image 0 下載進 Flash,因為是 bin 文件,所以我們要填入正確的鏈接起始地址(對於 i.MXRT1060 就是 0x60000000;對於 i.MXRT1010 應該是 0x60000400,具體查看工程鏈接文件便知)。此外我們使用的是完整的可啟動鏡像文件(包含了全部所需啟動頭),也可以直接在軟件通用編程器界面做下載。

  image 0 下載進 Flash 后,繼續下載 image 1,這時候只能在軟件通用編程器界面操作。這里主要是設置好下載起始地址,前面我們使能冗余程序啟動時在 Fuse 里設置的偏移地址是 0x400000,那么此時下載起始地址就應該是 0x400000(對於 i.MXRT1060 是 0x400000;對於 i.MXRT1010 應該是 0x400400)。至此兩份 image 下載就完成了。

2.3 快速驗證兩份 image 正確性

  現在 Flash 里有了兩份 image,我們來做一個快速驗證,看看 image 是不是放得符合冗余程序啟動的要求。對於 image 0,沒什么好說的,芯片啟動模式設為 2'b10 后斷電復位應該可以看到 image 0 在執行,最重要的是驗證 image 1 是不是合法。

  這里開始涉及到芯片冗余程序啟動流程核心了,當 image 0 啟動失敗后,芯片 BootROM 不是立刻去執行 image 1 的,它用了一個取巧的方式,在一個軟復位不置位的寄存器里(SRC_GPR10)標記了當前狀態,然后調用 NVIC_SystemReset() 重新進入 BootROM 執行,第二次 BootROM 執行時才會去啟動 image 1。

  所以這也給了我們快速驗證 image 1 執行的可能性,我們在板子上掛上 J-Link 仿真器,然后打開 J-Link Commander,直接將 SRC_GPR10 寄存器改寫為 0x40000000,再依次執行 reset 和 go 命令,這時你應該可以看到 image 1 正在執行了。

2.4 測試無簽名 image 0 損壞條件

  痞子衡之前在 《i.MXRT Bootable image格式》 一文里介紹過一個可啟動 image 包含哪些組成部分,其中最簡單的無簽名 image 應該至少包含 FDCB, IVT, BD, App 四部分,芯片 BootROM 也是按序讀取這四部分數據完成程序啟動的。

  現在我們嘗試分別破壞這幾個組成部分來看看何種程度的 image 0 損壞能被 BootROM 識別出從而去啟動 image 1,下面是測試結果。從測試結果來看,除了 Image 0 - App 的損壞無法檢測外,image 0 其余啟動頭的損壞都可以被 BootROM 識別到。

測試項 損壞程度 測試結果 備注
Image 0 - FDCB 全無或關鍵配置丟失導致Flash無法訪問 無簽名image 0啟動失敗
無簽名image 1啟動成功
如啟用Auto Probe功能,則FDCB無所謂
Image 0 - IVT,BD 全無或關鍵配置丟失導致App信息無法找到 無簽名image 0啟動失敗
無簽名image 1啟動成功
N/A
Image 0 - App 任意破壞App區域 無簽名image 0被啟動,但執行情況視破壞程度而定
無簽名image 1未被啟動
N/A

2.5 能檢測 image 0 app 損壞的方法

  如果不能檢測 image app 部分的損壞,那這個冗余程序啟動功能就比較雞肋了,畢竟 app 部分的數據才是整個 image 核心所在。如果要加上 app 損壞檢測,需要使能 i.MXRT 簽名啟動,還是可以借助 MCUBootUtility 工具完成全部流程,下載兩份含簽名的 image 進 Flash 的過程跟 2.2 節基本差不多,只是 Secure Boot Type 里需要選擇 "HAB Signed Image Boot",含簽名的 image 0 下載沒什么好說的,All-In-One 操作全搞定,含簽名的 image 1 數據可以通過在通用編程器界面里將含簽名的 image 0 數據全部讀回得到,這個具體操作就不詳細展開了。

  含簽名 image 0 相比無簽名 image 0 多了 HAB data(csf,cert,signature) 數據段,BootROM 在跳轉 image 之前會根據 HAB data 數據對 image 進行驗簽,驗簽通過才做跳轉。

  此時再做一次破壞實驗,結果如下,顯然加了簽名的 image 0 其完整性就有保證了,這時的冗余程序啟動設計才能發揮出最大效果。

測試項 損壞程度 測試結果 備注
Image 0 - FDCB 全無或關鍵配置丟失導致Flash無法訪問 含簽名image 0啟動失敗
含簽名image 1啟動成功
如啟用Auto Probe功能,則FDCB無所謂
Image 0 - IVT,BD 全無或關鍵配置丟失導致App信息無法找到 含簽名image 0啟動失敗
含簽名image 1啟動成功
N/A
Image 0 - App,HAB data 任意破壞App,HAB Data區域 含簽名image 0啟動失敗
含簽名image 1啟動成功
N/A

  至此,i.MXRT1060,1010上串行NOR Flash冗余程序啟動設計痞子衡便介紹完畢了,掌聲在哪里~~~

歡迎訂閱

文章會同時發布到我的 博客園主頁CSDN主頁知乎主頁微信公眾號 平台上。

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


免責聲明!

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



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