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

最后歡迎關注痞子衡個人微信公眾號【痞子衡嵌入式】,一個專注嵌入式技術的公眾號,跟著痞子衡一起玩轉嵌入式。
衡杰(痞子衡),目前就職于恩智浦(NXP)半導體MCU系統應用部門,擔任高級嵌入式系統應用工程師。
專欄內所有文章的轉載請注明出處:http://www.rzrgm.cn/henjay724/
與痞子衡進一步交流或咨詢業務合作請發郵件至 hengjie1989@foxmail.com
可以關注痞子衡的Github主頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。
關于專欄文章有任何疑問請直接在博客下面留言,痞子衡會及時回復免費(劃重點)答疑。
痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。
浙公網安備 33010602011771號