大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是MCUXpresso IDE下高度靈活的FreeMarker連結檔案模板機制。
痞子衡之前寫過一篇文章 《MCUXpresso IDE下工程連結檔案配置管理與自動生成機制》,這篇文章介紹了 MCUXpresso IDE 在連結檔案管理設計上跟其它 IDE(IAR/Keil)不一樣的地方,與 IAR/Keil 下使用者直接改寫連結檔案去做個性化目標連結(比如把某個原始檔裡全部程式碼重定向連結到 RAM 裡執行)不同的是, MCUXpresso IDE 下使用者都是在圖形化配置介面裡做對應操作,然後 MCUXpresso IDE 會自動生成相應的連結檔案(.ld)。但是圖性化操作介面裡有時候不能百分百滿足使用者的個性化連結需求,這時候除了回退到 IAR/Keil 下那種傳統方式外,還有沒有其它方式呢?答案是有的,這就是今天要聊的 MCUXpresso IDE 下 FreeMarker 連結檔案模板機制。
一、準備工作
首先需要準備好環境,包含必要的軟體,痞子衡的環境如下:
然後按照 《MCUXpresso IDE下將關鍵函式重定向到RAM中執行的幾種方法》 文章 一、準備工作 小節裡改造下 evkmimxrt1170_hello_world_demo_cm7 示例工程選項,並新增 critical_code.c 原始檔。在這篇文章的 2.3 針對原始檔中全部函式 小節裡,痞子衡為了將 critical_code.c 裡程式碼全部連結到 DTCM,使用了回退到 IAR/Keil 那種傳統改寫連結檔案的方式。今天我們就嘗試用 FreeMarker 連結檔案模板機制這個特性來實現。
二、FreeMarker機制
FreeMarker 是一個模板引擎(更通俗的說法其實就是連結文字的生成器),它整合在 MCUXpresso IDE 內部,由 MCUXpresso IDE 自動呼叫。MCUXpresso IDE 下最終的連結檔案其實是由這個 FreeMarker 處理生成的。在 MCUXpresso IDE 軟體內部有一組預設的系統模板(也叫根模板),它還支援使用者提供的模板(這些模板均是用一種專用的語法 FTL 來描述的),所有適用工程的模板最終統一經過 FreeMarker 來處理。
模板的設計是元件化的,這意味著使用者不需要編寫整個工程的模板,只需要加入指定的使用者模板實現個性化連結需求即可,其它部分仍由 MCUXpresso IDE 圖形配置介面完成。預設情況下,使用者模板需要被放在指定的 user_project_root/linkscripts 目錄下(這個路徑不用額外新增進工程選項 C/C++ General \ Paths and Symbols \ Source Location 中)。
- Note:更多 FreeMarker 細節,可以參見 \MCUXpressoIDE_11.6.0_8187\MCUXpresso_IDE_User_Guide.pdf 文件裡的 17.14 FreeMarker Linker Script Templates 小節。
三、新方法解決問題
現在我們嘗試用 FreeMarker 特性來解決 critical_code.o 的連結需求。首先是在 \MCUXpressoIDE_11.6.0_81874\workspace\evkmimxrt1170_hello_world_demo_cm7 下建立一個名為 linkscripts 的資料夾(前面說了,這個新資料夾路徑不需要在工程選項裡登記),然後在 linkscripts 裡面新建如下三個 .ldt 檔案(固定檔名,由 FreeMarker 定死的):
bss.ldt
data.ldt -- 作用是將 critical_code.o 放到指定 RAMx 區域
-- 備註:如果 MCU 僅一塊 RAM 空間,則此處應為 main_data.ldt
main_text.ldt -- 作用是將 critical_code.o 從 .text 段(預設連結在 Flash 區域)移出來
main_text.ldt 內容比較簡單,僅僅是用於告訴 FreeMarker 不要將 critical_code.o 裡的 text 段放進主 .text 段裡一起處理:
// 單目標檔案寫法
*(EXCLUDE_FILE(*critical_code.o) .text*)
// 如果是多目標檔案,寫法可以這樣
*(EXCLUDE_FILE(*critical_code1.o *critical_code2.o) .text*)
data.ldt 中內容比較關鍵,用於重置 critical_code.o 裡的 text 段。這裡需要注意的是如果是將該 text 放置進主 RAM 區域(即工程選項 MCU settings 裡 Alias 名為 RAM 的空間),其寫法跟不放進主 RAM 不一樣:
// 如果目標檔案放進主 RAM - 正確寫法,等效於放進 memory.alias=="RAM" 或者 memory.name=="SRAM_DTC_cm7" 區域
*critical_code.o(.text*)
// 如果目標檔案放進主 RAM - 錯誤寫法,實際不生效,等於沒有重置,程式碼依舊放進 Flash 區域
<#if memory.alias=="RAM">
*critical_code.o(.text*)
</#if>
// 如果目標檔案不是放進主 RAM - 正確寫法1
<#if memory.name=="SRAM_ITC_cm7">
*critical_code.o(.text*)
</#if>
// 如果目標檔案不是放進主 RAM - 正確寫法2
<#if memory.alias=="RAM2">
*critical_code.o(.text*)
</#if>
// 如果是多目標檔案,寫法可以這樣
<#if memory.name=="SRAM_ITC_cm7">
*critical_code1.o(.text*)
*critical_code2.o(.text*)
</#if>
現在編譯工程檢視對映檔案,我們會發現 critical_code.c 裡全部函式都已經連結在指定的 RAMx 區域了。如果你想更進一步,把 critical_code.c 裡全部 RO data 段都放進指定 RAMx 區域,則需要再在 linkscripts 資料夾裡增加一個名為 main_rodata.ldt 檔案。其內容如下,這裡是告訴 FreeMarker 不要將 critical_code.o 裡的 RO data 段放進主 RO data 段裡一起處理。
*(EXCLUDE_FILE(*critical_code.o) .rodata)
*(EXCLUDE_FILE(*critical_code.o) .rodata.*)
*(EXCLUDE_FILE(*critical_code.o) .constdata)
*(EXCLUDE_FILE(*critical_code.o) .constdata.*)
. = ALIGN(${text_align});
然後 data.ldt 裡改成如下這樣就可以了:
<#if memory.alias=="RAM2">
*critical_code.o(.text*)
*critical_code.o(.rodata .rodata.* .constdata .constdata.*)
</#if>
至此,MCUXpresso IDE下高度靈活的FreeMarker連結檔案模板機制痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時釋出到我的 部落格園主頁、CSDN主頁、知乎主頁、微信公眾號 平臺上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。