MDK編譯過程及檔案型別全解

sunset journey發表於2019-03-15

C語言編譯步驟

1.預處理    gcc -E
2.編譯      gcc -S
3.彙編      gcc -C
4.連線      gcc -l
複製程式碼
  • 預處理
    • 一般就是處理巨集以及標頭檔案
  • 編譯
    • 在這個階段將C語言轉化為彙編程式碼。
    • 一般會進行程式的優化
  • 彙編
    • 將彙編程式碼轉化為機器碼
  • 連線
    • 將所有目標檔案按照連線指令碼的要求進行連結
    • 在這個時候,什麼程式碼段,資料段之類的就可以進行位置的指定了。
      • 在這個階段就出現了位置無關碼之類的名詞以及動態連結和靜態連結
    • 最終在連結後生成了可執行檔案
程式元件 所屬類別
機器程式碼指令 Code
常量 RO-data
初值非0的全域性變數 RW-data
初值為0的全域性變數 ZI-data
區域性變數 ZI-data棧空間
使用malloc動態分配的空間 ZI-data堆空間

MDK編譯過程及檔案型別全解
ROM可以理解為硬碟,SRAM理解為記憶體。前者掉電不丟失,但是讀寫慢,後者掉電丟失,讀寫快。 ROM中儲存了只讀(RO-SECTION)段,以及讀寫段(RW-section)。 顯然,RO段是用作bootloader的。而RW段用來儲存檔案系統的。

程式狀態與區域 組成
程式執行時的只讀區域(RO) Code + RO data
程式執行時的可讀寫區域(RW) RW data + ZI data
程式儲存時佔用的ROM區 Code + RO data + RW data

*.dep,*.d依賴檔案

  • Dependency file
    • 記錄的是工程或其它檔案的依賴,主要記錄了引用的標頭檔案路徑,其中*.dep是整個工程的依賴,它以工程名命名,而*.d是單個原始檔的依賴,它們以對應的原始檔名命名。

*.crf交叉引用檔案

  • Cross-Reference file
    • 它主要包含了瀏覽資訊(browse information),即原始碼中的巨集定義、變數及函式的定義和宣告的位置。

o、axf及elf檔案

  • *.o、*.elf、*.axf以及前面提到的lib檔案都是屬於目標檔案,它們都是使用ELF格式來儲存的。
    • Executable and Linking Format
  • 目標檔案主要有如下三種型別
    • 可重定位的檔案(Relocatable File),包含基礎程式碼和資料,但它的程式碼及資料都沒有指定絕對地址,因此它適合於與其他目標檔案連結來建立可執行檔案或者共享目標檔案。 這種檔案一般由編譯器根據原始碼生成。
    • 可執行檔案(Executable File) ,它包含適合於執行的程式,它內部組織的程式碼資料都有固定的地址(或相對於基地址的偏移),系統可根據這些地址資訊把程式載入到記憶體執行。這種檔案一般由連結器根據可重定位檔案連結而成,它主要是組織各個可重定位檔案,給它們的程式碼及資料一一打上地址標號,固定其在程式內部的位置,連結後,程式內部各種程式碼及資料段不可再重定位(即不能再參與連結器的連結)。
    • 共享目標檔案(Shared Object File), 它的定義比較難理解,我們直接舉例,MDK生成的*.lib檔案就屬於共享目標檔案,它可以繼續參與連結,加入到可執行檔案之中。另外,Linux的.so,如/lib/ glibc-2.5.so,Windows的DLL都屬於這一類

常見檔案型別

MDK編譯過程及檔案型別全解

MDK編譯過程及檔案型別全解

MDK編譯過程及檔案型別全解

sct 分散載入檔案的格式與應用

當工程按預設配置構建時, MDK 會根據我們選擇的晶片型號,獲知晶片的內部 FLASH 及內部 SRAM 儲存器概況,生成一個以工程名命名的字尾為*.sct 的分散載入檔案 (Linker Control File, scatter loading)。

程式啟動後連結地址和啟動地址有可能不一樣。會有一段程式將所有的程式自舉到連結地址指定的地方。

野火rt1052 pro為例子

儲存 大小(十進位制) 大小(十六進位制) 起始地址
片上儲存 RAM(ITCM) 512K 0x0008 0000 0x0000 0000
off-chip SDRAM 32M 0x0‭200 0000‬ 0x8000 0000
QSPI nor Flash 32M 0x0200 0000 這個是由自己對映的
NAND Flash 128M 0x8000 0000 同樣是自己對映的
片上 DTCM 512k 0x0008 0000 0x2000 0000

假設使用 QSPI nor flash。將其對映到 0x80000000的地址(SEMC external memories 起始地址)。

MDK編譯過程及檔案型別全解

#define m_data_start                   0x80000000
#define m_data_size                    0x01E00000

#define m_ncache_start                 0x81E00000
#define m_ncache_size                  0x00200000

#define m_data2_start                  0x20000000
#define m_data2_size                   0x00020000

#define m_data3_start                  0x20200000
#define m_data3_size                   0x00040000
複製程式碼

如上,分為了四個段。

  • m_data_startm_ncache_start共同佔據所有QSPI nor flash的地址。
  • m_data2_startm_data3_start共同佔據部分DTCM區域
  • 那麼最上面圖中IRAM2配置的就是ITCM的區域了。只不過ITCM的大小是可以配置的。猜測是為了相容以前的晶片。
    • 不過以前只是用過arm9。不清楚ITCM的操作,等以後補上。
程式狀態與區域 組成
程式執行時的只讀區域(RO) Code + RO Data
程式執行時的讀寫區域(RW) RW Data+ ZI Data
程式儲存時的佔用區域(ROM) Code + RO Data +RW Data
節區屬性描述符 說明
RO code & Code 只讀程式碼段
RO Data & Const 只讀資料段
RO & TEXT 包括RO code 和 RO Data
RW Data 讀寫資料段
RW CODE 讀寫程式碼段
RW & Data 包括 RW Data 和 RW Code
ZI & BSS 初始為0的段
XO 只可執行的段
ENTRY 節區的入口

上面m_data_start表示的是片上chip的可讀寫區域開始地址。

  • m_flash_config_start就是片上flash的起始地址以及大小。
  • m_data2_start就是片外的sdram的起始地址以及大小。

更正

*.sct 檔案 改成 *.scf檔案。在工程檔案中沒找到*.sct。興許是改名字了。但是沒找到關於官方檔案的解釋。暫且先這樣。

參考資料

MDK的編譯過程及檔案型別全解     https://flash-rtd.readthedocs.io/zh_CN/latest/
MDK的幫助手冊   《ARM Development Tools》
Keil sct分散載入檔案    https://blog.csdn.net/kobesdu/article/details/38258449
KEIL下分散載入檔案  *.sct檔案 http://www.cnblogs.com/darren-715/p/3457214.html
MDK的編譯過程及檔案型別全解 https://www.cnblogs.com/yangguang-it/p/7697967.html
配置DTCM,ITCM和OCRAM       http://forum.armfly.com/forum.php?mod=viewthread&tid=86733
如何讓RT1050的程式碼執行速度飛起來  http://www.eeworld.com.cn/mp/ZLG/a57247.jspx
複製程式碼

相關文章