大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是恩智浦i.MXRT系列MCU的ROM啟動日志。
關(guān)于 i.MX RT 啟動問題解決的文章,痞子衡寫過非常多,其中大部分都是具體到某一類啟動設(shè)備下的具體問題分析,比較依賴經(jīng)驗,這些經(jīng)驗當然是非常有用的。此外也有一篇 《啟動失敗先查看SRC_SBMRx寄存器》,這篇內(nèi)容通用于全部啟動設(shè)備,算是葵花寶典系列了。
一直以來我們都當芯片啟動 ROM 程序運行狀態(tài)完全是個黑盒子,如果遇到異常,我們通常是去猜其可能遇到的問題,那么能不能不全靠猜呢?答案是可以的!這便是痞子衡今天要聊 ROM 啟動日志:
一、ROM啟動日志原理
我們知道 i.MX RT 系列上電都是片內(nèi)固化的 ROM 程序代碼先運行,由 ROM 來加載啟動設(shè)備里的用戶程序去執(zhí)行,所以如果用戶程序不能正常啟動,一定是 ROM 程序執(zhí)行過程中遇到了異常。
i.MX RT 初始 ROM 代碼來源于它的老大哥 i.MX 處理器,翻看 i.MX 參考手冊其中有關(guān)于 ROM Log Event 功能的描述,所謂 ROM Log Event 就是 ROM 程序在執(zhí)行過程中將其重要節(jié)點事件(狀態(tài))按時間軸記錄到一個日志緩沖區(qū)里(日志緩沖區(qū)通常在片內(nèi) RAM 固定地址處),這個日志內(nèi)容顯然對于分析 ROM 執(zhí)行過程非常有用,那么 i.MX RT 系列 ROM 代碼里有沒有保留這個功能呢?很高興,它還在!
下表記錄了 i.MX RT 全系列型號的 ROM 啟動日志緩沖區(qū)地址:
二、獲取ROM啟動日志數(shù)據(jù)
上一節(jié)我們知道了 ROM 啟動日志緩沖區(qū)存儲地址,獲取其數(shù)據(jù)的方法就簡單了,可以直接連接上仿真器去讀取。不過這里有需要注意的地方:如果是在 ROM 跳轉(zhuǎn)用戶程序之前發(fā)生的異常(日志體現(xiàn)為啟動失?。?,那么內(nèi)核 PC 應該還停留在 ROM 空間,這時候 RAM 區(qū)數(shù)據(jù)是完整的,無人破壞。如果是在 ROM 跳轉(zhuǎn)到用戶程序之后發(fā)生的異常(日志體現(xiàn)為啟動成功),這時候用戶程序已經(jīng)開始執(zhí)行了,這可能會破壞 RAM 區(qū)數(shù)據(jù)(如果用戶程序鏈接文件里用到了存儲啟動日志的 RAM 區(qū)域),這時候啟動日志內(nèi)容就不一定有效了。
以 i.MXRT1170 為例,痞子衡找了一塊開發(fā)板,上電后掛上 J-Link 調(diào)試器,使用 J-Link 命令行工具里的 SaveBin 命令從 0x2024ad78 地址處讀取最大的日志數(shù)據(jù)存儲到 bootlog.bin 文件中。這里需要注意在用 J-Link 連接目標設(shè)備時盡量不要選 MCU 型號,而用內(nèi)核 CORTEX-M7 代替,這樣可以防止選了 MCU 型號而自動加載執(zhí)行相應配套初始化腳本(萬一腳本里有片內(nèi) RAM 相關(guān)操作破壞日志數(shù)據(jù))。
命令格式:SaveBin <filename>, <addr>, <NumBytes>
命令解釋:Save target memory range into binary file.
除了借助調(diào)試器,我們也可以借助芯片串行下載模式下配套的 MCUBoot 工具鏈(Flashloader+blhost)來獲取 ROM 日志數(shù)據(jù),具體可見 《MCUBootUtility v6.3發(fā)布,支持獲取與解析啟動日志》 一文 2.3 小節(jié)里的途徑二。
三、解析ROM啟動日志
i.MXRT 全系列 ROM 啟動日志緩沖區(qū)數(shù)據(jù)結(jié)構(gòu)并不是完全一樣的,主要分為兩個版本。其中 i.MXRT10xx 系列的日志結(jié)構(gòu)如下,跟 i.MX 處理器差不多,每條日志內(nèi)容壓縮存儲在一個 uint32_t 型變量里,最大支持 64 條日志(當實際日志超出 64 條時,后面的日志直接被忽略不記)。
uint32_t?pu_irom_log_buffer[64];
而 i.MXRT11xx 系列以及 i.MXRTxxx 系列的日志結(jié)構(gòu)相比前一代有一些改進,其結(jié)構(gòu)如下,首先增加了 entryIndex 用于記錄有效的日志個數(shù),同時也增加了 checkSum 用于校驗全部日志的完整性(但實際意義并不大,ROM 異常運行時計算 checkSum 時機難以確定)。
typedef?struct?_log_context
{
????uint32_t?entryIndex;
????uint32_t?logEntries[64];
????uint32_t?checkSum;
}?log_context_t;
此時最大日志個數(shù)依舊是 64(當實際日志超出 64 條時,會找到日志緩存區(qū)里排在最后的狀態(tài)為 Fail 或者 Fatal 的日志,然后只保存其后面的正常日志并繼續(xù)向下記錄)。
舉例說明:當前記錄到了第 65 條日志
- 如果 logEntries[63:0] 里沒有 Fail 或者 Fatal 狀態(tài)的日志,那么清空數(shù)組,entryIndex 從 0 開始記錄。
- 如果 logEntries[31] 是排在最后的 Fail 或者 Fatal 狀態(tài)的日志,那么將 logEntries[63:32] 拷貝到 logEntries[31:0],entryIndex 重置為 32 再開始記錄。
除了以上啟動日志緩沖區(qū)數(shù)據(jù)結(jié)構(gòu)差別之外,i.MXRT10xx 與 i.MXRT11xx/i.MXRTxxx 在單條日志值定義上也是完全不同的,不過具體如何解析每條日志內(nèi)容,用戶無需過多關(guān)注,這在痞子衡開發(fā)的 MCUBootUtility v6.3 軟件里已經(jīng)全部搞定了,用戶可以直接查看解析后的日志結(jié)果。
還是繼續(xù)以 i.MXRT1170 為例查看解析后的日志結(jié)果,我們在 FlexSPI1 連接的串行 NOR Flash 里下載一個能正常啟動的 XIP 裸用戶程序(非簽名非加密),將芯片啟動模式設(shè)為 2'b10,當看到程序正常執(zhí)行后,掛上調(diào)試器讀出啟動日志數(shù)據(jù)(確保日志存儲空間未被用戶程序破壞),并用 MCUBootUtility 軟件解析如下,還是能夠清晰地看到 ROM 執(zhí)行過程信息的。
至此,恩智浦i.MXRT系列MCU的ROM啟動日志痞子衡便介紹完畢了,掌聲在哪里~~~