RISC-V MCU編譯過程分析
1、前言
使用MounRiver Studio(MRS)這款集成開發環境(IDE)對RISC-V MCU進行嵌入式開發時,工程師不用關注RISC-V MCU 繁雜的底層編譯過程,只需用C語言編寫相應的工程代碼,點擊build編譯按鈕,即可生成hex或bin目標文件,下載后即可運行。
本文將分析點擊bulid按鍵后,.c文件是如何一步一步變為可執行的.hex或.bin文件。
2、編譯過程
而將.C文件轉變為最終的.hex或.bin目標文件,需要經過預處理、編譯、匯編、鏈接這四個步驟。
建議關閉多線程編譯,讓整個編譯過程按順序執行。(切記及時打開,以提升編譯速度)
可以通過取消MRS的簡潔輸出模式,Project -> Concise Build Output Mode,觀察整個編譯過程。
MRS默認是不保存編譯過程中的.i和.s等臨時文件,為了更好的分析編譯的過程,可配置保存這些文件,操作如下:
2.1 預處理(Pre-Processing)
主要包括宏定義(#define),文件包含(#include),條件編譯(#ifdef)三部分。
預處理期間將檢查包含預處理指令的語句和宏定義,並對其進行響應和替換,並刪除程序中的注釋和多余空白字符,最后會生成 .i 文件。
2.2 編譯(Compiling)
編譯器會將預處理完的 .i 文件進行一些列的語法分析,並優化后生成對應的匯編代碼,生成 .s 文件。
RISC-V MCU的工程采用GCC編譯,官方工具鏈地址:https://github.com/riscv/riscv-gnu-toolchain。
當然,各廠家會根據自家的內核設計,修改對應的工具鏈以支持其特色功能,如沁恆微電子的RISC-V MCU所特有的HPE硬件壓棧和VTF免表中斷技術,需要在中斷服務函數增加指令 __attribute__((interrupt("WCH-Interrupt-fast")))
,然后在編譯時會識別並省略軟件壓棧的過程。
2.3 匯編(Assembling)
通過匯編器將編譯器生成的 .s 匯編程序匯編為機器語言或指令,也就是可以機器可以執行的二進制程序,生成 .o 文件。
2.4 鏈接(Linking)
根據“*.ld”鏈接文件將多個目標文件(.o)和庫文件(.a)輸入文件鏈接成一個可執行輸出文件(.elf)。涉及到對空間和地址的分配以及符號解析與重定位。
3、elf、hex、bin文件說明
使用MRS編譯時,最終生成的可執行文件為elf、hex或bin文件,這些文件之間的聯系如下:
3.1 elf文件
ELF(Executable and Linkable Format),可執行與可鏈接格式。
elf是一種用於二進制文件、可執行文件、目標代碼、共享庫和核心轉儲格式文件。是UNIX系統實驗室(USL)作為應用程序二進制接口(Application Binary Interface,ABI)而開發和發布的,也是Linux的主要可執行文件格式。
ELF文件記錄的信息更多、更復雜。主要包含以下內容:
- ELF頭(ELF header) - 描述文件的主要特性:類型,CPU架構,入口地址,現有部分的大小和偏移等等;
- 程序頭表(Program header table) - 列舉了所有有效的段(segments)和他們的屬性。 程序頭表需要加載器將文件中的節加載到虛擬內存段中;
- 節頭表(Section header table) - 包含對節(sections)的描述。
3.2 hex文件
HEX格式文件由Intel制定的一種十六進制標准文件格式,一種ASCII文本文件。文件的每一行都包含了 一個HEX記錄。這些記錄是由一些代表機器語言代碼和常量的16進制數據組成的。Intel HEX文件常用來傳輸要存儲在ROM 或者 EPROM中的程序和數據。大部分的EPROM編程器和FLASH能使用Intel HEX文件。
格式如下:
行開始 | 數據長度 | 地址 | 數據類型 | 數據 | 校驗 |
---|---|---|---|---|---|
: | BB | AAAA | TT | D……D | CC |
1字節 | 2字節 | 1字節 | n字節 | 1字節 |
- :冒號,代表行開始
- BB代表Bytes,數據長度
- AAAA代碼Address,表示數據這行數據的存儲地址
- TT代表Type,數據類型(標識)
- 00:數據標識
- 01:文件結束標識
- 02:擴展段地址
- 03:開始段地址
- 04:線性地址
- 05:線性開始地址
- D……D代表Data,有效數據
- CC代表CheckSum,校驗和
3.3 bin文件
bin是binary的縮寫,即二進制文件,全是0或1的文件,最底層的可執行的機器碼。只包含程序數據。bin文件的大小直接反應所占flash內存的大小。
3.4 轉換關系
因為bin、hex都是只是記錄數據的,但elf類型不僅記錄數據還有程序描述,所以elf文件通過gcc中的objcopy可轉換成hex或bin文件,hex文件也可轉換成bin文件,但反之不可。
3.5 總結
bin文件最小最簡單,但是安全性差,功能性差,hex包含頭尾和檢驗,就有很好的安全性,但是文件比bin大,功能沒有elf強大;elf功能多,但是文件最大。
在使用工程編譯結果是,最好有bin或者hex同時具有elf文件,elf用於仿真和調試,但輸出的到工廠的文件可以使用hex和bin。