大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是主從系統中i.MXRT系列MCU從主處理器接收App數據包超時機制。
在痞子衡舊文 《RT四位數Boot模式》 里的 1.2.1 Serial Downloader 模式、《RT三位數Boot模式》 里的 1.2.2 Serial Boot 模式里都介紹到了 i.MXRT 芯片內置 ROM 程序里支持與主機進行數據交互,而交互的通信協議均是 blhost 協議(這最早來自于飛思卡爾 Kinetis 系列 ROM ),有了這個功能,我們便可以直接將應用程序灌進 i.MXRT 內部 SRAM 去加載執行,這個功能在多處理器系統里(尤其是 i.MXRT 作為協處理器)大有用處。
最近有一個客戶設計了高通 AR1 + 恩智浦 i.MXRT600 的主從系統,RT600 作為協處理器直接通過 SPI 接口從主處理器 AR1 接收應用程序 App 并加載到自身內部 SRAM 執行,這樣硬件上便可省去 RT600 的專屬非易失性存儲器。客戶已經將 blhost 協議代碼集成進了 AR1 程序里,但在實際測試過程中發現有一定概率導致 RT600 程序加載失敗,RT600 ROM 會返回 kStatus_AbortDataPhase(0x5A,0xA3),這是怎么回事?今天痞子衡就來聊聊這個話題:
一、i.MXRT與主機交互方法
我們首先簡單回顧下 i.MXRT 內置 ROM 程序配套的與主機交互方法,有如下三種。其中方法一是比較常用的,把 PC 當作主機,因為 UART/USB 接口可以直接從 PC 引出,這種方式一般集成在上位機 GUI 工具里(比如恩智浦官方的 SPT 以及痞子衡的 NXP-MCUBootUtility)。方法二本質上和方式一差不多,主機仍然是 PC,只不過通信接口是 SPI/I2C,因為無法直接從 PC 引出,需要有一個橋接板,恩智浦一共做了三種不同的橋接實現。方式三就是本文提及的客戶所用到的方法,把主處理器當作主機,因為處理器接口豐富,所以不管哪種通信方式均可以直連。
因為方式一和方式二均可以直接使用恩智浦提供的配套工具鏈,因此 blhost 協議實現細節以及注意事項都被包在了工具鏈里面,客戶使用起來基本不會遇到問題。而方式三需要客戶自己移植實現 blhost 協議到主處理器代碼里,這可能會遇到一些協議細節上的設計問題。
這里需要特別提一下方式二里的 Embedded Host 橋接實現,在恩智浦官網 MCUBoot 主頁我們可以下載到 NXP_Kinetis_Bootloader_2_0_0.zip 包,在 \NXP_Kinetis_Bootloader_2_0_0\validation\embedded_host 路徑下我們可以找到基于 Kinetis K65 的實現,如果你想移植 blhost 協議到處理器上運行,不妨參考這個代碼。
二、i.MXRT從主機接收數據包超時機制
現在我們談回到 blhost 協議本身,這是一套數據包傳輸格式與支持命令的定義集合。打開 RT600 參考手冊的 Non-Secure Boot ROM 章節,可以找到具體的協議細節,這里就不再贅述。我們只取其中關于 write-memory 命令的介紹,主機給 i.MXRT 下載數據(App)主要就是借助這個命令。
write-memory 命令的過程其實很簡單,主機(Host)先要發送含 write-memory 信息的命令包(0x5A, 0xA4 ...) 給 i.MXRT (圖中叫 target),收到確認的回復(0x5A, 0xA1)后,主機繼續發送含 App 程序數據的數據包(0x5A, 0xA5 ...),等待 i.MXRT 處理完成返回確認信息,然后主機不斷發送數據包,直到 App 數據全部發送完成,最后還有一個結束命令包。
- Note: 注意這里的 App 數據不是一個數據包就全部發送完的,而是被拆分成了很多個小數據包,每個小數據包最大長度是 512 字節。拆分成小包的目的是防止通信過程中有干擾導致數據錯誤,出現錯誤就只需要重新發送該包數據。如果不拆分數據包,出現錯誤就得全部 App 數據重發,效率太低。
關于每個數據小包的接收與發送,i.MXRT 均設計了超時機制保護。如果主機已經開始發送當前小包數據(發完包固定起始字節 0x5A 后為超時起點),那么需要在規定時間內(包剩余長度(Bytes) * 10ms/Bytes)完成該包數據發送,如果超時時間內未完成,i.MXRT 則返回 kStatus_AbortDataPhase。至于 read-memory 時主機接收小包數據時超時機制相同,只不過時間單元是 20ms/Bytes。
- Note1:RT500/600/700 ROM 程序里數據包處理超時機制是一樣的,發送和接收均有超時。
- Note2:RT1160/1170/1180 ROM 程序里數據包處理僅有接收超時,沒有發送超時。
當然文檔里上述表述有未盡的地方,主機每發完一小包數據后都需要讀確認信息(0x5A, 0xA1),確認信息這里是否有超時限制?如果有,是怎樣的機制?痞子衡就不賣關子了,這里是需要特別注意的,當主機發完一包數據后,i.MXRT 需要及時處理數據的,由于這里是加載程序進內部 SRAM,所以就是將該數據包從緩沖區搬到 SRAM 指定位置,這個時間 t2 很短,文檔里并未給出。t3 是比較關鍵的時間,這里的計時起點并不是主機收到 ACK 包的第一個字節,而是 i.MXRT 處理完數據搬移后就開始了,因此主機每次發完數據包之后,都需要在 t2+t3 的時間內將確認信息數據包及時讀走,否則 i.MXRT 則返回 kStatus_AbortDataPhase。
那么問題來了,如果一小包數據是 200 bytes(包含 0x5A 包頭等信息),請問主機發送數據和接收確認的超時時間分別是多少?答案是 1990ms 和 t2+40ms(這里主機接收確認消息只拿了 2 bytes 數據)。
三、客戶主機發送數據包設計
最后回到客戶的問題,經過和客戶的溝通,主處理器 AR1 運行得是一個非實時操作系統。在給 RT600 加載 App 程序過程中會出現任務調度情況,發送完一個小數據包后,因為任務調度的關系,導致主機讀取確認消息(0x5A, 0xA1)的時間間隔不確定,有時候小于 40ms,有時候會超出 40ms,顯然這是不符合 blhost 協議超時機制規定的。
至此,主從系統中i.MXRT系列MCU從主處理器接收App數據包超時機制痞子衡便介紹完畢了,掌聲在哪里~~~