大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是 i.MXRT 部分型號上新增的 FlexSPI Remap 功能。
OTA 升級設(shè)計幾乎是每個量產(chǎn)客戶都繞不開的話題,產(chǎn)品發(fā)布后免不了要做固件(App)升級以修復(fù) bug 或者增加新特性。升級 App 是個麻煩事,因為處理不好,App 被破壞了導(dǎo)致啟動不了,產(chǎn)品就容易變磚,變了磚即使能救回來,也非常影響用戶體驗。
如今基于 i.MXRT 的客戶量產(chǎn)產(chǎn)品越來越多,關(guān)于 OTA 安全升級的客戶支持也越來越多。早期的 i.MXRT 型號(比如 i.MXRT1050/1020/1015)在做基于 FlexSPI NOR Flash 的 OTA 升級時,有一個最大痛點即 App 版本切換不便,因此后面的 i.MXRT 型號中(比如 i.MXRT1064/1060/1010)新增了 FlexSPI 的 Remap 功能。今天痞子衡就來介紹一下這個 Remap 功能是如何用于安全 OTA 的。
一、OTA 設(shè)計中的痛點
1.1 OTA 一般設(shè)計
在講 App 版本切換不便痛點前,先給大家簡單介紹一下 OTA 升級設(shè)計過程中處理 App 版本的一般套路。下面是一個典型的 OTA 設(shè)計中 NOR Flash 里內(nèi)容分布,最前面一般是 L2 OTA Boot,負(fù)責(zé)更新升級或者啟動 App;接下來是主 App 區(qū),就是真正實現(xiàn)產(chǎn)品功能的 App;然后是 Temp 區(qū),一般用作 App 更新臨時緩沖區(qū);最后是 User Data 區(qū),存放一些固定不變的圖片資源(如果有 GUI 的話),或者放一些動態(tài)保存的系統(tǒng)關(guān)鍵數(shù)據(jù)。
這里面的 Temp 區(qū)設(shè)計是一個關(guān)鍵,如果沒有 Temp 區(qū),在 OTA 升級時只能原地覆蓋主 App 區(qū)(App 1),升級過程中一旦發(fā)生意外(比如斷電),系統(tǒng)里就沒有完整 App 可用了,會導(dǎo)致產(chǎn)品變磚。而有了 Temp 區(qū)作緩存,升級過程就會可靠多了,如下圖所示,新版本 App(App 2)首先會被放在 Temp 區(qū),僅當(dāng) App 2 完整性校驗通過之后,才會從 Temp 區(qū)搬移到主 App 區(qū),搬移完成之后再擦除 Temp 區(qū)。這樣的設(shè)計下,即使 App 2 下載到 Temp 區(qū)或者 App 2 往 App 1 搬移時發(fā)生意外,系統(tǒng)里都有完整 App 用于恢復(fù)。
?
上面介紹的處理 App 版本的典型設(shè)計在實際應(yīng)用中其實不算特別常用,因為系統(tǒng)中僅存在一份最新的 App,其不支持版本回滾。有時候我們的新版本 App 因為一些原因(比如新增功能有 bug)導(dǎo)致運行并不穩(wěn)定,我們希望能夠回退到上一個已經(jīng)運行穩(wěn)定的舊版本 App,系統(tǒng)需要保留兩份不同版本 App,所以就有了如下改進的 OTA 設(shè)計 NOR Flash 內(nèi)容分布,在主 App 區(qū)(App 2)后面增加一個次 App 區(qū)(App 1)。
?
這時候升級過程稍微復(fù)雜一點,如下圖所示,多了一步主 App 區(qū)(App 2)搬移到次 App 區(qū)(App 1)的過程(Step 2),這也是版本回滾的關(guān)鍵。不過萬事都是有代價的,版本回滾的代價就是增加了 OTA 升級的時間,以及將 Flash 中 App 區(qū)從兩段劃分成三段,導(dǎo)致 App 最大長度減少了 1/3。
?
?
1.2 App 版本切換痛點
前面介紹了 OTA 升級設(shè)計中管理 App 版本的兩種方法,注意這里的 App 都是指在 FlexSPI NOR Flash 中原地執(zhí)行(XIP)的 App,代碼鏈接在芯片內(nèi)部 SRAM 或者外擴 RAM 的 App 不在討論范疇(這種 Non-XIP 屬性的 App 升級不存在版本切換的痛點)?,F(xiàn)在聊 XIP App 版本切換的痛點:
?
在上面的圖中你會發(fā)現(xiàn),新版本 App 最終都會被搬到主 App 區(qū)(就是緊接著 L2 OTA Boot 后面的第一個 App 位置),為什么要這么做?這就涉及 MCU 中 App 鏈接相關(guān)知識了,因為 MCU 不同于 MPU,其沒有 MMU 組件,不支持虛擬內(nèi)存,所以 App 一般都是固定地址鏈接,App 代碼體二進制數(shù)據(jù)僅放在鏈接的位置才可以正常執(zhí)行,將 App 拷貝到非鏈接位置是不能運行的。OTA 升級中雖然 App 版本不同,但是這些 App 都有一個共同的鏈接地址,即都是鏈接在主 App 區(qū)的。
?
比如下圖 OTA 系統(tǒng)中使用了一塊 8MB 的 Flash,在 i.MXRT 里的系統(tǒng)映射起始地址是 0x60000000,L2 OTA Boot 和 User Data 各占 1MB,剩余 6MB 被均分成 3 段,那么 App x/2/1 都需要從 0x60100000 地址開始鏈接放中斷向量表。
?
?
可能你會說,我們也可以設(shè)計不同鏈接地址的 App,這樣就不需要將新版本 App 都往主 App 區(qū)搬移了,是的,原理上可以這么做,但實踐中,需要管理不同鏈接地址的 App,導(dǎo)致 OTA 升級上位機端操作比較復(fù)雜,容易出錯(當(dāng)前待升級的 App 必須與上一次升級的 App 鏈接地址不同),因此這種方法不推薦。
?
所以最大的痛點就是 App 總要往主 App 區(qū)搬移,既增加了 OTA 升級時間,也因為搬移操作過多減小了 Flash 的壽命(總擦寫次數(shù)是一定的)。
?
二、詳解 FlexSPI Remap 功能
2.1 FlexSPI NOR 系統(tǒng)映射地址
我們知道 FlexSPI 連接的 NOR Flash 能夠?qū)崿F(xiàn) XIP,最主要的原因是 FlexSPI 有對應(yīng)系統(tǒng)映射空間且 NOR Flash 自身可以按 Byte 地址訪問,這里的系統(tǒng)映射空間主要用于 AHB 方式讀。CPU 去從系統(tǒng)映射空間里讀 App 指令碼,F(xiàn)lexSPI 模塊會自動將 AHB 總線傳來的地址數(shù)據(jù)請求轉(zhuǎn)換成 IPG 命令方式去獲取 NOR Flash 里的對應(yīng)指令內(nèi)容。
?
i.MXRT1060 中分配給 FlexSPI 的系統(tǒng)映射空間如下,兩個 FlexSPI 一共分配了 496MB。
?
?
i.MXRT1010 中分配給 FlexSPI 的系統(tǒng)映射空間如下,一個 FlexSPI 分配了 504MB。
?
?
2.2 FlexSPI Remap 功能設(shè)計
i.MXRT 中的 Remap 設(shè)計其實是系統(tǒng)架構(gòu)層面的,在 AHB 總線層面做一個地址重定向,并不是在 FlexSPI 模塊里實現(xiàn)的,這也是為什么 Remap 相關(guān)控制在 IOMUXC_GPR 寄存器里(設(shè)置后 Remap 立刻生效,但這些寄存器不是非易失性的,普通軟復(fù)位就會置位)。下面是 Remap 控制寄存器(對于含兩個 FlexSPI 的型號,Remap 控制是同時作用的):
?
Remap 功能 | 對應(yīng)控制寄存器 | |
---|---|---|
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 設(shè)計說起來其實特別簡單,就是地址(addr)落在[ADDR_START, ADDR_END]里的 AHB 訪問,其實際訪問到的是 addr + ADDR_OFFSET 位置處的數(shù)據(jù)。(注意 ADDR_START, ADDR_END, ADDR_OFFSET 都是 4KB 對齊的)
?
舉例來看,根據(jù) ADDR_OFFSET 的大小不同,會有三種情況:第一種是 ADDR_OFFSET = ADDR_END - ADDR_START,如下圖所示。這也是 OTA 中最常用的情況,ADDR_START 可設(shè)為主 App 區(qū)起始地址,ADDR_END 可設(shè)為次 App 區(qū)起始地址。
?
?
第二種是 ADDR_OFFSET > ADDR_END - ADDR_START,如下圖所示:
?
?
第三種是 ADDR_OFFSET < ADDR_END - ADDR_START,如下圖所示。不過這種情況在實際應(yīng)用中并不推薦。
?
?
2.3 Remap 對擦寫 Flash 的影響
啟用了 Remap 功能后,很多人會對調(diào)用 FlexSPI NOR 驅(qū)動函數(shù)去擦寫 Flash 有點疑惑。其實完全不必要有這種疑惑,擦寫 Flash 操作走的是 FlexSPI IPG 命令方式,屬于 FlexSPI 模塊內(nèi)部的事情,完全不受上層系統(tǒng) Remap 功能影響,你可以就當(dāng) Remap 功能完全不存在,原來怎么做還是怎么做。
?
三、FlexSPI Remap 解決 OTA 痛點
有了 Remap 功能,現(xiàn)在再回到 OTA 設(shè)計,此時我們只需要兩個 App 分區(qū)即可。新版本 App(App 2)首先會被放在后 Temp 區(qū),App 2 更新完成且校驗通過之后,直接使用 Remap 功能將 App 2 重映射到 App 1 位置,此舉既不增加額外物理搬移操作,也同時保留了新舊兩份 App 可以實現(xiàn)版本回滾,而且整個 OTA 過程僅有一次 App 擦寫耗時也最短,完美解決痛點。
?
當(dāng) Remap 功能已被使能,再有新版本 App(App 3)更新需求時,其需要被下載到前 Temp 區(qū),注意 Flash 擦寫操作都是通過 IPG 方式實現(xiàn),所以不受 Remap 功能干擾,僅需關(guān)注絕對物理地址偏移,App 下載完成,取消 Remap 功能即可,如此往復(fù)。
?
?
至此,i.MXRT 部分型號上新增的 FlexSPI Remap 功能痞子衡便介紹完畢了,掌聲在哪里~~~