你們好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給你們介紹的是i.MXRT部分型號上新增的FlexSPI Remap功能。html
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的。安全
在講App版本切換不便痛點前,先給你們簡單介紹一下OTA升級設計過程當中處理App版本的通常套路。下面是一個典型的OTA設計中NOR Flash裏內容分佈,最前面通常是L2 OTA Boot,負責更新升級或者啓動App;接下來是主App區,就是真正實現產品功能的App;而後是Temp區,通常用做App更新臨時緩衝區;最後是User Data區,存放一些固定不變的圖片資源(若是有GUI的話),或者放一些動態保存的系統關鍵數據。微信
這裏面的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用於恢復。架構
上面介紹的處理App版本的典型設計在實際應用中其實不算特別經常使用,由於系統中僅存在一份最新的App,其不支持版本回滾。有時候咱們的新版本App由於一些緣由(好比新增功能有bug)致使運行並不穩定,咱們但願可以回退到上一個已經運行穩定的舊版本App,系統須要保留兩份不一樣版本App,因此就有了以下改進的OTA設計NOR Flash內容分佈,在主App區(App 2)後面增長一個次App區(App 1)。app
這時候升級過程稍微複雜一點,以下圖所示,多了一步主App區(App 2)搬移到次App區(App 1)的過程(Step 2),這也是版本回滾的關鍵。不過萬事都是有代價的,版本回滾的代價就是增長了OTA升級的時間,以及將Flash中App區從兩段劃分紅三段,致使App最大長度減小了1/3。函數
前面介紹了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區的。flex
好比下圖OTA系統中使用了一塊8MB的Flash,在i.MXRT裏的系統映射起始地址是0x60000000,L2 OTA Boot和User Data各佔1MB,剩餘6MB被均分紅3段,那麼App x/2/1都須要從0x60100000地址開始連接放中斷向量表。ui
可能你會說,咱們也能夠設計不一樣連接地址的App,這樣就不須要將新版本App都往主App區搬移了,是的,原理上能夠這麼作,但實踐中,須要管理不一樣連接地址的App,致使OTA升級上位機端操做比較複雜,容易出錯(當前待升級的App必須與上一次升級的App連接地址不一樣),所以這種方法不推薦。
因此最大的痛點就是App總要往主App區搬移,既增長了OTA升級時間,也由於搬移操做過多減少了Flash的壽命(總擦寫次數是必定的)。
咱們知道FlexSPI鏈接的NOR Flash可以實現XIP,最主要的緣由是FlexSPI有對應系統映射空間且NOR Flash自身能夠按Byte地址訪問,這裏的系統映射空間主要用於AHB方式讀。CPU去從系統映射空間裏讀App指令碼,FlexSPI模塊會自動將AHB總線傳來的地址數據請求轉換成IPG命令方式去獲取NOR Flash裏的對應指令內容。更多原理可參看 《在串行NOR Flash XIP調試原理》。
i.MXRT1060中分配給FlexSPI的系統映射空間以下,兩個FlexSPI一共分配了496MB。
i.MXRT1010中分配給FlexSPI的系統映射空間以下,一個FlexSPI分配了504MB。
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區起始地址。
第二種是ADDR_OFFSET > ADDR_END - ADDR_START,以下圖所示:
第三種是ADDR_OFFSET < ADDR_END - ADDR_START,以下圖所示。不過這種狀況在實際應用中並不推薦。
啓用了Remap功能後,不少人會對調用FlexSPI NOR驅動函數去擦寫Flash有點疑惑。其實徹底沒必要要有這種疑惑,擦寫Flash操做走的是FlexSPI IPG命令方式,屬於FlexSPI模塊內部的事情,徹底不受上層系統Remap功能影響,你能夠就當Remap功能徹底不存在,原來怎麼作仍是怎麼作。
下面這段測試代碼是在MIMXRT1060-EVK上跑的,用ROM API驅動擦寫0x60100000地址,擦寫操做前加了一段Remap設置干擾,實測下來Remap設置對擦寫沒有任何影響,復位後去讀Flash,操做的仍是原0x60100000地址。其實從測試代碼也能看出端倪,API裏傳入是0x100000,這是Flash絕對偏移地址,跟系統映射不要緊。
flexspi_nor_config_t flashConfig; serial_nor_config_option_t configOption; configOption.option0.U = 0xc0000007; uint32_t programBuffer[64]; for (uint32_t i = 0; i < sizeof(programBuffer); i++) { *((uint8_t *)programBuffer + i) = (uint8_t)(i & 0xFF); } IOMUXC_GPR->GPR30 = 0x60100000; IOMUXC_GPR->GPR31 = 0x60200000; IOMUXC_GPR->GPR32 = 0x100000; g_bootloaderTree->flexSpiNorDriver->get_config(0, &flashConfig, &configOption); g_bootloaderTree->flexSpiNorDriver->init(0, &flashConfig); g_bootloaderTree->flexSpiNorDriver->erase(0, &flashConfig, 0x100000, 0x100); g_bootloaderTree->flexSpiNorDriver->program(0, &flashConfig, 0x100000, programBuffer);
有了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功能便可,如此往復。
至此,i.MXRT部分型號上新增的FlexSPI Remap功能痞子衡便介紹完畢了,掌聲在哪裏~~~
文章會同時發佈到個人 博客園主頁、CSDN主頁、知乎主頁、微信公衆號 平臺上。
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就能夠在手機上第一時間看了哦。