大家好,我是痞子衡,是正經搞技術的痞子,今天痞子衡給大家介紹的是MCUXpresso IDE下工程鏈接檔案配置管理與自動生成機制,
痞子衡在 2018 年初寫過一個專題 《嵌入式開發檔案系列》,用 8 篇文章系統地介紹了 ARM Cortex-M 內核微控制器開發程序中所要了解的主要檔案型別:源檔案、鏈接檔案、工程檔案、可重定向檔案、映射檔案、可執行檔案、反匯編檔案、鏡像檔案,
上述 8 種檔案中,大家對源檔案、工程檔案以及鏡像檔案這三種應該是最熟悉的,而其余檔案型別,很多人應該都沒有深入研究過,但痞子衡一直認為只有深入了解了鏈接檔案才算是真正步入嵌入式開發老手行列,
我們知道不同 IDE 下鏈接檔案語法是不一樣的,而恩智浦 MCUXpresso IDE 底層編譯器是 Arm GCC,因此其鏈接檔案就是標準 GCC 下 .ld 檔案,如果你對 .ld 檔案語法非常精通,當然可以自己從頭開始寫鏈接檔案,如果不太熟的話,也不要緊張,MCUXpresso IDE 早就為你掃清了障礙,在這個 IDE 下能夠支持圖形界面里做鏈接配置,然后自動生成相應鏈接檔案的,今天痞子衡就和大家聊聊這個特性:
- Note: 在開始今天的主題之前,可以先看一下痞子衡的舊文 《MCUXpresso IDE下SDK工程在Build配置上與IAR,MDK差異》,本篇實際上就是這篇文章的后續,
一、準備開發環境
首先需要準備好環境,包含必要的軟體,痞子衡的環境如下:
- 集成開發環境: MCUXpresso IDE_11.4.0_6224,點此下載
- 軟體開發包: SDK_2.10.0_EVK-MIMXRT1170(Toolchain需包含MCUXpresso IDE),點此下載
二、MCUXpresso IDE下鏈接檔案配置
現在進入正題,我們先按照 《MCUXpresso IDE下SDK工程匯入與workspace管理機制》 一文步驟從 SDK 包里匯入生成一個工程(就選最簡單的 hello_world 吧),工程匯入成功后,會在 \MCUXpressoIDE_11.4.0_6224\workspace\evkmimxrt1170_hello_world_demo_cm7 下看到 .project 工程檔案,在 MCUXpresso IDE 下打開這個工程,
2.1 Memory 空間定義
在工程名上右擊選擇 Properties 進入選項配置界面,其中 MCU settings 一欄里定義的就是 MCU 實際存盤空間,這是鏈接檔案的空間分配基礎,我們后面會將程式里全部的段都鏈接在這些區域里,
存盤空間屬性(Type)分為兩類:一類是 Flash(存放 RO 段),一類是 RAM(存放 RW 段),每個屬性的空間都可以被定義很多個,但其中僅 Alias 名為 Flash 和 RAM 的空間才是默認被選中用于鏈接程式段的(可通過上下移動按鈕將指定空間調整到前排 Flash 和 RAM 的位置),

2.2 默認程式段分配
還是在上一節打開的 Properties 選項配置界面,其中 Settings / Managed Linker Script 頁面就是鏈接檔案里具體程式段鏈接設定,這個頁面的最上面 Manage linker script 要保持勾選,勾選上則代表使用 IDE 的鏈接檔案自動生成功能,
在一個具體應用程式專案工程里,如果源檔案僅包含標準 C 和匯編代碼,那么程式段會被默認歸納為三大類:RO 段(函式代碼,常量,全域變數初值等),RW 段(全域變數,重定向到 RAM 中函式代碼等),Heap/Stack,IDE 里分別提供了這三類程式段的空間指定:
1. Link application to RAM 勾選框:
- 不勾選,則 RO 段放在 2.1 節圖中 Alias 名為 Flash 的空間里
- 勾選上,則 RO 段放在 2.1 節圖中 Alias 名為 RAM 的空間里
2. Heap and Stack placement 配置框:
- 可以按需調整 Heap/Stack 里的 Region,Location,Size,其中 Region 可以是 2.1 節圖中屬性為 RAM 的任意空間
- Heap/Stack 默認大小均為 4KB,放在 2.1 節圖中 Alias 名為 RAM 的空間里
3. Global data placement 下拉框:
- 可以按需鏈接 RW 段到 2.1 節圖中屬性為 RAM 的任意空間
- RW 段默認放在 2.1 節圖中 Alias 名為 RAM 的空間里

2.3 自定義程式段分配
除了上一節聯結器默認的程式段名外,我們也可以自定義一些用戶段名,方便一些特殊代碼處理,這里需要使用 __attribute__((section("UserSectionName"))) 聯結器語法來修飾指定函式/變數,這樣該函式/變數就會被放在 UserSectionName 段里,然后我們在上一節圖中鏈接設定框的最后 Extra linker script input sections 框里單獨為自定義 UserSectionName 段指定鏈接空間,
比如工程 clock_config.c 檔案里如下函式 UpdateSemcClock(),這個函式在默認的 RO .text 段里,RO 段都是鏈接在 Flash 里的,但是我們希望將這個函式重定向到 ITCM 里執行,所以我們可以使用 __attribute__((section("CodeQuickAccess"))) 聯結器語法來修飾這個函式,然后在 Extra linker script input sections 框里將 CodeQuickAccess 段放到 SRAM_ITC_cm7 空間里即可,
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func
AT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));
void UpdateSemcClock(void)
{
SEMC->IPCMD = 0xA55A000D;
while ((SEMC->INTR & 0x3) == 0);
SEMC->INTR = 0x3;
SEMC->DCCR = 0x0B;
CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;
}
2.4 自動生成的鏈接檔案
鏈接設定完成后,會在工程目錄 \MCUXpressoIDE_11.4.0_6224\workspace\evkmimxrt1170_hello_world_demo_cm7\Debug 下自動生成最終鏈接檔案(假定用得 debug build),檔案一共有三個,其中 evkmimxrt1170_hello_world_demo_cm7_Debug.ld 是主鏈接檔案,感興趣的可以打開這個鏈接檔案學習一下(如果看不懂語法可以結合這篇文章 https://www.embedded.com/building-bare-metal-arm-systems-with-gnu-part-3/ ),

2.5 查看Map檔案確認
按照 2.1 節和 2.2 節 圖中的鏈接設定,我們編譯鏈接 evkmimxrt1170_hello_world_demo_cm7 工程可以得到如下鏈接結果,從空間占用上來看是符合預期的,

現在我們可以打開生成的 evkmimxrt1170_hello_world_demo_cm7.map 檔案具體分析一下最終鏈接情況,痞子衡摘錄了最核心部分如下:
Memory Configuration
Name Origin Length Attributes
/------------------------------------------------------------/
// RO .text 段在 BOARD_FLASH:0x30000000 - 0x30006eaf,共 28336 個位元組
// RO CodeQuickAccess 段在 BOARD_FLASH:0x30006eb0 - 0x30006ee7,共 56 個位元組
// RO .data_init 段在 BOARD_FLASH:0x30006ee8 - 0x30006eeb,共 4 個位元組
.boot_hdr 0x30000000 0x2000
.text 0x30002000 0x4eb0
// RW CodeQuickAccess 段在 SRAM_ITC_cm7:0x00000000 - 0x00000037,共 56 個位元組
.data_RAM4 0x00000000 0x38 load address 0x30006eb0
CodeQuickAccess
0x00000000 0x38 ./board/clock_config.o
0x00000000 UpdateSemcClock
// RW .data 段在 BOARD_SDRAM:0x80000000 - 0x80000003,共 4 個位元組
.data 0x80000000 0x4 load address 0x30006ee8
.data.SystemCoreClock
0x80000000 0x4 ./device/system_MIMXRT1176_cm7.o
// RW .bss 段在 BOARD_SDRAM:0x80000004 - 0x80000107,共 260 個位元組
.bss 0x80000004 0x104
// Heap 在 BOARD_SDRAM:0x80000108 - 0x80001107,共 4KB
.heap 0x80000108 0x1000
// Stack 在 BOARD_SDRAM:0x82fff000 - 0x82ffffff,共 4KB
.stack 0x82fff000 0x0
0x82fff000 _vStackBase = .
0x82fff000 . = ALIGN (0x4)
0x83000000 _vStackTop = (. + _StackSize)
簡單總結下,RO 段一般從 Flash 的最前面開始鏈接的,.text 段在最前面,然后是 ramfunc 函式物體,最后是 .data_init 段(全域變數初值),RW 段也是從 RAM 的最前面開始鏈接,.data 段在前,.bss 在后,然后是 Heap 和 Stack(Heap/Stack的具體位置是可以設定的,有 Start、End、Post Data 三種選擇),
三、MCUXpresso IDE下鏈接小實驗
根據上面的知識,我們現在來做些鏈接設定小實驗,在做實驗前,我們調整下 Memory 定義,把 SDRAM 相關空間移到后面去,默認 RAM 用 SRAM_DTC_cm7 空間,這樣看起來習慣一點,

3.1 默認 XiP 鏈接
調整過 Memory 空間順序后的鏈接結果如下:

3.2 Non-XiP 鏈接
現在我們嘗試使能 Link application to RAM 選項,其余不變,此時可以看到 28396 Bytes 的 RO 段也到了 SRAM_DTC_cm7 空間里,BOARD_FLASH 空間完全沒有任何占用:

3.3 XiP 鏈接,調整 Stack 大小并放置到 OCRAM1
我們嘗試調整 Stack 大小到 1KB 并放置到 SRAM_OC1,其余不變,此時可以看到 SRAM_DTC_cm7 空間消耗相比 3.1 節里少了 4KB,但 SRAM_OC1 空間消耗多了 1KB:

3.4 XiP 鏈接,調整 RW 段到 OCRAM2
我們嘗試調整 RW 段到 SRAM_OC2,其余不變,此時可以看到 SRAM_DTC_cm7 空間消耗相比 3.1 節里少了 264 Bytes,但 SRAM_OC2 空間消耗多了 264 Bytes:

至此,MCUXpresso IDE下工程鏈接檔案配置管理與自動生成機制痞子衡便介紹完畢了,掌聲在哪里~~~
歡迎訂閱
文章會同時發布到我的 博客園主頁、CSDN主頁、知乎主頁、微信公眾號 平臺上,
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦,

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