大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是IAR環境下無法直接下載調試i.MXRT分散鏈接工程的解決方案。 分散鏈接與載入一直是嵌入式領域比較勸退新手的難題,在恩智浦 i.MXRT 系列為代表的多存儲器架構的 MCU 上,分散鏈接問題體現得尤為明顯,畢竟你在鏈接應用程式各種段( ...
大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是IAR環境下無法直接下載調試i.MXRT分散鏈接工程的解決方案。
分散鏈接與載入一直是嵌入式領域比較勸退新手的難題,在恩智浦 i.MXRT 系列為代表的多存儲器架構的 MCU 上,分散鏈接問題體現得尤為明顯,畢竟你在鏈接應用程式各種段(section)時可能會面對包括內部 ITCM/DTCM/OCRAM 和外部 Flash/SDRAM/PSRAM/HyperRAM 等多種存儲器空間選擇。
雖然存儲器空間選擇很多,但是一個最終可離線啟動的 i.MXRT 程式(即能被下載進外部非易失存儲器,且能被 BootROM 載入啟動)其 readonly 段應該是一段連續的數據(SREC/HEX格式鏡像文件里僅能包含一段空間地址),即要鏈接在一個主存儲器空間里,這也意味著其它鏈接在非主存儲器空間的 .text 段應該使用重定向方法來實現,不可直接原地鏈接,參考痞子衡文章 《IAR下將源文件代碼重定向到任意RAM中的方法》。
最近有一個 i.MXRT1060 客戶,他們就遇到了分散鏈接工程調試問題,工程 readonly 段被直接分散鏈接到了兩個不同的外部存儲器空間,沒有用重定向方法,這雖然不符合離線啟動要求,但是在 IAR 下直接下載調試也會報錯,這是怎麼回事?
一、引出客戶問題
我們再進一步描述客戶工程分散鏈接問題,下圖包含了 i.MXRT 架構下程式段的全部鏈接選擇,根據這些選擇組合,我們能產生多種不同的工程鏈接文件。
先來看不涉及分散鏈接的簡單情況,即 readonly 段全在 Flash 里,readwrite 段在一個或多個 RAM 空間里,這種情況下 IAR 下載調試沒有什麼特殊註意事項,flashloader 會負責外部 Flash 初始化,並將 readonly 段數據下載進 Flash,然後巨集文件負責外部 RAM 初始化,線上調試一切正常。
Case1: APP readonly text/data1 + APP readwrite data2/3/4
再來看第二種情況,這裡開始涉及分散鏈接,readonly 段分散在多個 RAM 空間,readwrite 段在一個或多個 RAM 空間里。這種情況下因為沒有鏈接在 Flash 空間,因此無需 flashloader,完全由巨集文件將相關外部 RAM 初始化好,多個 readonly 段都能正常下載,線上調試一切正常。
Case2: APP readonly text/data2/3/4 + APP readonly text/data2/3/4 + APP readwrite data2/3/4
第三種情況再複雜一點,readonly 段除了在 Flash 空間外,還有一部分放在了內部 RAM 里,然後 readwrite 段依然在一個或多個 RAM 空間里。這種情況下 IAR 下載調試感覺上應該沒問題,因為內部 RAM 無需初始化可直接訪問,兩個不連續 readonly 段原則上可以下載,但是很遺憾,IAR 會報錯,其 flashloader 無法處理放在內部 RAM 的 readonly 段,調試無法進行。
Case3: APP readonly text/data1 + APP readonly text/data2 + APP readwrite data2/3/4
最後一種分散鏈接的情況最複雜,也是客戶的問題所在,readonly 段除了在 Flash 空間外,還有一部分放在了外部 RAM,然後 readwrite 段在一個或多個 RAM 空間里。這種情況下 IAR 下載調試一定會出問題,預設 flashloader 只做了 Flash 初始化,並不負責初始化外部 RAM,因此部分 readonly 段往外部 RAM 下載時會報錯,工程巨集文件雖然負責初始化外部 RAM,但其執行階段在 flashloader 作用之後,鞭長莫及。
Case4: APP readonly text/data1 + APP readonly text/data3/4 + APP readwrite data2/3/4
二、復現客戶問題
我們在恩智浦官方 MIMXRT1060-EVK 板上復現一下客戶問題,使用 \SDK_2.11.0_EVK-MIMXRT1060\boards\evkmimxrt1060\demo_apps\hello_world\iar 工程,原工程有很多 Build,我們就選用 flexspi_nor_sdram build,它用到了兩塊外部存儲器,符合客戶場景。在這個 build 里 readonly 段都鏈在外部 Flash 里,readwrite 段都鏈接在外部 SDRAM 里,顯然這個情況屬於第一節介紹的 case1:
1. Flash初始化工作:\IAR Systems\Embedded Workbench 9.10.2\arm\config\flashloader\NXP\FlashIMXRT1060_FlexSPI.out
2. SDRAM初始化工作:\SDK_2.11.0_EVK-MIMXRT1060\boards\evkmimxrt1060\demo_apps\hello_world\iar\evkmimxrt1060_sdram_init.mac
我們現在要將工程稍微改動一下,在工程源文件里定義一個 sw_delay() 函數(記得要在 main 函數里調用一下),並且將其指定在自定義 .sdramCodeSection 段里:
#pragma default_function_attributes = @ ".sdramCodeSection"
void sw_delay(void)
{
__NOP();
}
#pragma default_function_attributes =
然後在工程鏈接文件里將這個自定義 .sdramCodeSection 段放到 SDRAM 空間里,這樣我們在外部 Flash 和 SDRAM 空間里就都有 readonly 段了,跟客戶情況一致了。
place in DATA3_region { section .sdramCodeSection };
板卡上電,直接用板載 DAP-Link 調試器線上下載工程(為了減少對板子設置的依賴,我們將調試器複位類型改為 Core),下載過程中 IAR 果然一直在報錯,如果你忽略錯誤繼續調試,雖然斷點會停在 main 函數,但是只要單步進放到 SDRAM 空間的函數里時,程式就會跑飛進 hardfault,因為 SDRAM 中根本就沒有正確的 .sdramCodeSection 段數據。
三、嘗試僅藉助巨集文件(.mac)解決問題
分析到這裡,其實你應該知道問題出在哪裡了,工程配套巨集文件 evkmimxrt1060_sdram_init.mac 本應負責 SDRAM 初始化,但是其執行順序在 FlashIMXRT1060_FlexSPI.out 作用之後,所以沒有產生其該有的效果,這個具體可見痞子衡舊文 《IAR內部C-SPY調試組件配套巨集文件(.mac)用法介紹》 3.1 小節,有非常詳細的解釋。
現在的解決思路就是,如何讓 evkmimxrt1060_sdram_init.mac 里的 SDRAM 初始化語句在 flashloader 作用之前生效,所以我們很自然地想在 flashloader 配套的巨集文件 FlashIMXRT1060_FlexSPI.mac 里的 execUserFlashInit() 介面里將 SDRAM 初始化語句都加上,但是很遺憾,這招不湊效,其實在第一節介紹的 case3 里就應該認清現實了,內部 RAM 無需初始化 IAR 也無法正常下載。
四、藉助雙Flashloader解決問題
其實 IAR 軟體設計里,對於兩個 readonly 段,只要其中有一個段被放入了 Flash 里(即需要 flashloader),那麼另外一個段不管是不是放在 Flash 里也需要有相應 flashloader,這裡痞子衡要吐槽下 IAR 的設計,有點呆板了。
所以本文案例里解決問題的關鍵就是為 SDRAM 也設計一個 flashloader,具體製作方法可以參考痞子衡舊文 《串列NOR Flash下載演算法(IAR EWARM篇)》。因為 SDRAM 擦寫其實也不需要什麼特殊命令時序,就是單純 AHB 方式地寫就行了,所以這個 SDRAM 版本的 flashloader 就是個傀儡 flashloader 而已。
痞子衡為了讓這個傀儡 flashloader 更通用一些,是按如下方式實現三個主要 flashloader API 的,其中 FlashInit() 函數里故意沒有加 SEMC 模塊初始化代碼,就是為了讓這個 flashloader 適用所有類型的 RAM(ITCM/DTCM/OCRAM/SDRAM/PSRAM/HyperRAM),外設初始化工作放在傀儡 flashloader 配套巨集文件里去完成。
FlashInit() - 什麼都不做,直接返回
FlashWrite() - 用 memcpy 函數實現
FlashErase() - 用 memset 函數實現
最終 RAM 型通用 flashloader 源碼工程地址如下:
https://github.com/JayHeng/imxrt-tool-flash-algo/tree/master/boards/nxp_evkmimxrt1060_rev.a1/ram_algo/IAR
我們把新生成的 SDRAM flashloader 相關的所有文件(.out/.flash/.mac)放到對應 IAR 系統目錄下,並且修改原來的 FlashIMXRT1060_EVK_FlexSPI.board 文件,加入 SDRAM 相關的部分:
1. FlashIMXRT1060_SEMC.mac 文件基本沿用 evkmimxrt1060_sdram_init.mac 文件,只是 setup 巨集函數從 execUserPreload 換到 execUserFlashInit
2. FlashIMXRT1060_SEMC.flash 文件內容按 FlashIMXRT1060_FlexSPI1.flash 寫即可,註意文件尾碼一定要是 .flash, IAR 只認這個尾碼。
現在再去下載調試,就一切正常了,說明雙 Flashloader 解決方案生效了。本例是以 IAR flashloader 為例的,如果用 J-Link flashloader 也是可以的,一樣的原理製作兩個 Flashloader 即可。
至此,IAR環境下無法直接下載調試i.MXRT分散鏈接工程的解決方案痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時發佈到我的 博客園主頁、CSDN主頁、知乎主頁、微信公眾號 平臺上。
微信搜索"痞子衡嵌入式"或者掃描下麵二維碼,就可以在手機上第一時間看了哦。
最後歡迎關註痞子衡個人微信公眾號【痞子衡嵌入式】,一個專註嵌入式技術的公眾號,跟著痞子衡一起玩轉嵌入式。



衡傑(痞子衡),目前就職於恩智浦MCU系統部門,擔任嵌入式系統應用工程師。
專欄內所有文章的轉載請註明出處:http://www.cnblogs.com/henjay724/
與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]
可以關註痞子衡的Github主頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。
關於專欄文章有任何疑問請直接在博客下麵留言,痞子衡會及時回覆免費(劃重點)答疑。
痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。