1. 程式人生 > >痞子衡嵌入式:利用i.MXRT1060,1010上新增的FlexSPI地址重對映(Remap)功能可安全OTA

痞子衡嵌入式:利用i.MXRT1060,1010上新增的FlexSPI地址重對映(Remap)功能可安全OTA

----   大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是**i.MXRT部分型號上新增的FlexSPI Remap功能**。   OTA升級設計幾乎是每個量產客戶都繞不開的話題,產品釋出後免不了要做韌體(App)升級以修復bug或者增加新特性。升級App是個麻煩事,因為處理不好,App被破壞了導致啟動不了,產品就容易變磚,變了磚即使能救回來,也非常影響使用者體驗。   如今基於i.MXRT的客戶量產產品越來越多,關於OTA安全升級的客戶支援也越來越多。早期的i.MXRT型號(比如i.MXRT1050/1020/1015)在做基於FlexSPI NOR Flash的OTA升級時,有一個最大痛點即App版本切換不便,因此後面的i.MXRT型號中(比如i.MXRT1064/1060/1010)新增了FlexSPI的Remap功能。今天痞子衡就來介紹一下這個Remap功能是如何用於安全OTA的。 ### 一、OTA設計中的痛點 #### 1.1 OTA一般設計   在講App版本切換不便痛點前,先給大家簡單介紹一下OTA升級設計過程中處理App版本的一般套路。下面是一個典型的OTA設計中NOR Flash裡內容分佈,最前面一般是L2 OTA Boot,負責更新升級或者啟動App;接下來是主App區,就是真正實現產品功能的App;然後是Temp區,一般用作App更新臨時緩衝區;最後是User Data區,存放一些固定不變的圖片資源(如果有GUI的話),或者放一些動態儲存的系統關鍵資料。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_basic_flash_layout.PNG)   這裡面的Temp區設計是一個關鍵,如果沒有Temp區,在OTA升級時只能原地覆蓋主App區(App 1),升級過程中一旦發生意外(比如斷電),系統裡就沒有完整App可用了,會導致產品變磚。而有了Temp區作快取,升級過程就會可靠多了,如下圖所示,新版本App(App 2)首先會被放在Temp區,僅當App 2完整性校驗通過之後,才會從Temp區搬移到主App區,搬移完成之後再擦除Temp區。這樣的設計下,即使App 2下載到Temp區或者App 2往App 1搬移時發生意外,系統裡都有完整App用於恢復。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_update_strategy_basic.png)   上面介紹的處理App版本的典型設計在實際應用中其實不算特別常用,因為系統中僅存在一份最新的App,其不支援版本回滾。有時候我們的新版本App因為一些原因(比如新增功能有bug)導致執行並不穩定,我們希望能夠回退到上一個已經執行穩定的舊版本App,系統需要保留兩份不同版本App,所以就有了如下改進的OTA設計NOR Flash內容分佈,在主App區(App 2)後面增加一個次App區(App 1)。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_advance_flash_layout.PNG)   這時候升級過程稍微複雜一點,如下圖所示,多了一步主App區(App 2)搬移到次App區(App 1)的過程(Step 2),這也是版本回滾的關鍵。不過萬事都是有代價的,版本回滾的代價就是增加了OTA升級的時間,以及將Flash中App區從兩段劃分成三段,導致App最大長度減少了1/3。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_update_strategy_advance.png) #### 1.2 App版本切換痛點   前面介紹了OTA升級設計中管理App版本的兩種方法,注意這裡的App都是指在FlexSPI NOR Flash中原地執行(XIP)的App,程式碼連結在晶片內部SRAM或者外擴RAM的App不在討論範疇(這種Non-XIP屬性的App升級不存在版本切換的痛點)。現在聊XIP App版本切換的痛點:   在上面的圖中你會發現,新版本App最終都會被搬到主App區(就是緊接著L2 OTA Boot後面的第一個App位置),為什麼要這麼做?這就涉及MCU中App連結相關知識了,因為MCU不同於MPU,其沒有MMU元件,不支援虛擬記憶體,所以App一般都是固定地址連結,App程式碼體二進位制資料僅放在連結的位置才可以正常執行,將App拷貝到非連結位置是不能執行的。OTA升級中雖然App版本不同,但是這些App都有一個共同的連結地址,即都是連結在主App區的。   比如下圖OTA系統中使用了一塊8MB的Flash,在i.MXRT裡的系統對映起始地址是0x60000000,L2 OTA Boot和User Data各佔1MB,剩餘6MB被均分成3段,那麼App x/2/1都需要從0x60100000地址開始連結放中斷向量表。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_xip_app_address_in_flash.PNG)   可能你會說,我們也可以設計不同連結地址的App,這樣就不需要將新版本App都往主App區搬移了,是的,原理上可以這麼做,但實踐中,需要管理不同連結地址的App,導致OTA升級上位機端操作比較複雜,容易出錯(當前待升級的App必須與上一次升級的App連結地址不同),因此這種方法不推薦。   所以最大的痛點就是App總要往主App區搬移,既增加了OTA升級時間,也因為搬移操作過多減小了Flash的壽命(總擦寫次數是一定的)。 ### 二、詳解FlexSPI Remap功能 #### 2.1 FlexSPI NOR系統對映地址   我們知道FlexSPI連線的NOR Flash能夠實現XIP,最主要的原因是FlexSPI有對應系統對映空間且NOR Flash自身可以按Byte地址訪問,這裡的系統對映空間主要用於AHB方式讀。CPU去從系統對映空間裡讀App指令碼,FlexSPI模組會自動將AHB匯流排傳來的地址資料請求轉換成IPG命令方式去獲取NOR Flash裡的對應指令內容。更多原理可參看 [《在序列NOR Flash XIP除錯原理》](https://www.cnblogs.com/henjay724/p/11791498.html)。   i.MXRT1060中分配給FlexSPI的系統對映空間如下,兩個FlexSPI一共分配了496MB。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_RT1060_flash_map.PNG)   i.MXRT1010中分配給FlexSPI的系統對映空間如下,一個FlexSPI分配了504MB。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_RT1010_flash_map.PNG) #### 2.2 FlexSPI Remap功能設計   i.MXRT中的Remap設計其實是系統架構層面的,在AHB匯流排層面做一個地址重定向,並不是在FlexSPI模組裡實現的,這也是為什麼Remap相關控制在IOMUXC_GPR暫存器裡(設定後Remap立刻生效,但這些暫存器不是非易失性的,普通軟復位就會置位)。下面是Remap控制暫存器(對於含兩個FlexSPI的型號,Remap控制是同時作用的):
Remap功能 對應控制暫存器
i.MXRT106x i.MXRT1010
ADDR_START IOMUXC_GPR_GPR30 IOMUXC_GPR_GPR27
ADDR_END IOMUXC_GPR_GPR31 IOMUXC_GPR_GPR28
ADDR_OFFSET IOMUXC_GPR_GPR32 IOMUXC_GPR_GPR29
  Remap設計說起來其實特別簡單,就是地址(addr)落在[ADDR_START, ADDR_END]裡的AHB訪問,其實際訪問到的是addr + ADDR_OFFSET位置處的資料。(注意ADDR_START, ADDR_END, ADDR_OFFSET都是4KB對齊的)   舉例來看,根據ADDR_OFFSET的大小不同,會有三種情況:第一種是ADDR_OFFSET = ADDR_END - ADDR_START,如下圖所示。這也是OTA中最常用的情況,ADDR_START可設為主App區起始地址,ADDR_END可設為次App區起始地址。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_remap_case_1.PNG)   第二種是ADDR_OFFSET >
ADDR_END - ADDR_START,如下圖所示: ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_remap_case_3.PNG)   第三種是ADDR_OFFSET < ADDR_END - ADDR_START,如下圖所示。不過這種情況在實際應用中並不推薦。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_remap_case_2.PNG) #### 2.3 Remap對擦寫Flash的影響   啟用了Remap功能後,很多人會對呼叫FlexSPI NOR驅動函式去擦寫Flash有點疑惑。其實完全不必要有這種疑惑,擦寫Flash操作走的是FlexSPI IPG命令方式,屬於FlexSPI模組內部的事情,完全不受上層系統Remap功能影響,你可以就當Remap功能完全不存在,原來怎麼做還是怎麼做。 ### 三、FlexSPI Remap解決OTA痛點   有了Remap功能,現在再回到OTA設計,此時我們只需要兩個App分割槽即可。新版本App(App 2)首先會被放在後Temp區,App 2更新完成且校驗通過之後,直接使用Remap功能將App 2重對映到App 1位置,此舉既不增加額外物理搬移操作,也同時保留了新舊兩份App可以實現版本回滾,而且整個OTA過程僅有一次App擦寫耗時也最短,完美解決痛點。   當Remap功能已被使能,再有新版本App(App 3)更新需求時,其需要被下載到前Temp區,注意Flash擦寫操作都是通過IPG方式實現,所以不受Remap功能干擾,僅需關注絕對實體地址偏移,App下載完成,取消Remap功能即可,如此往復。 ![](http://henjay724.com/image/cnblogs/i.MXRT1060_FlexSPI_Remap_OTA_update_strategy_remap_v2.png)   至此,i.MXRT部分型號上新增的FlexSPI Remap功能痞子衡便介紹完畢了,掌聲在哪裡~~~ ### 歡迎訂閱 文章會同時釋出到我的 [部落格園主頁](https://www.cnblogs.com/henjay724/)、[CSDN主頁](https://blog.csdn.net/henjay724)、[知乎主頁](https://www.zhihu.com/people/henjay724)、[微信公眾號](http://weixin.sogou.com/weixin?type=1&query=痞子衡嵌入式) 平臺上。 微信搜尋"__痞子衡嵌入式__"或者掃描下面二維碼,就可以在手機上第一時間看了哦。 ![](http://henjay724.com/image/github/pzhMcu_qrcode_258x2