GNU 編譯器組合

来源:互联网 发布:python parse教程 编辑:程序博客网 时间:2024/06/11 23:34

http://cms.mcuapps.com/techinfo/toolchains/gcc/

GNU Compiler Collection 意即採用 GNU 系列開源編譯器的工具組合,如果有碰過 Linux 交互編譯開發的朋友,應該對這套工具體系的概念和使用方法已經非常熟悉了。基本上你可以自行抓取這些工具程式的源碼,配合你的 host(即開發主機)環境與 target 裝置,設定相關選項進行編譯,集結而成你自己的專屬工具組。也可以從網路上抓取善心人士編譯好的工具直接採用,有時這些編譯好的工具還會附上完整的製作 scripts,方便你檢視或修改成更為適合你開發環境的版本。

如果你對於編譯 toolchain 的方式比較陌生,或是急切地想要立刻上手開發 MCU 的應用,就可以參考本篇文件所介紹的幾套主流的現成 toolchains 加以安裝。基本上安裝程序只是解壓縮到你所指定的特定目錄,再把這個特定目錄下的bin 子目錄附加到系統環境變數的 PATH 之後,一般的 Makefile 或 Eclipsed-based 的 IDE 環境就可以套用了。

GCC for Bare-Metal(裸機)

先前談過,如果你玩過 Linux 開發,應該已經非常熟悉 GNU cross compiler toolchain for Linux 這類型的工具。但是對於 MCU 而言,所編譯出來的應用程式並不適用於 Linux 環境下,主要就是沒有支援 Linux 系統呼叫,另外就是所採用的 C 函式庫也並非 Linux 上常用的 glibc,而經常會是較適於嵌入式系統開發的 newlibc。

另一個值得注意的是在進行 Linux 開發時已經預先定義好可執行檔的一些相關設定,而裸機開發時則必須要針對不同的 MCU 環境建立這些設定。通常分為兩個部分,第一個部分是啟動程式碼,在 Linux 的 ELF 可執行檔會被gcc 自動連結到 crt1.o,而裸機開發時使用者需要自行提供一個經常被命名為 startup.s 的啟動程式碼,作為 MCU 被 reset 後的進入點,所以其中必須包含了基本的中斷向量表設置。

第二個部分則是 linker scripts,是用來指定記憶體類型,以及程式碼或資料需要放置在哪一種記憶體類型之中的描述文件。在進行 Linux 開發時,gcc 也會自動載入一般應用程式所需要的 linker scripts 定義。而在裸機開發時,程式員就得根據實際 MCU 的定義,自行撰寫或找到類似的 linker scripts 檔案套用,以便編譯出來的代碼能夠被載入到正確的位置。

接下來就是除錯的部分,裸機開發時我們必須用到仿真器 (emulator) 這個實體裝置,以便透過(通常是共通標準的)JTAG 或 SWD 介面進行燒錄、單步、斷點等除錯工作。但嵌入式 MCU 世界中,各家作法都不盡相同,所以這部分向來是見招拆招。不過目前的趨勢看來,在仿真器軟體中提供 GDB server 的廠商越來越多了,而且經常還會跨三大桌面開發平台。另一方面,如果廠商本身沒有支援,OpenOCD 這個開源的仿真器萬用驅動程式,也能提供一個非常不錯的 GDB server 環境。

還有一個入門者會覺得奇怪的地方,就是交互編譯器 gcc 的名稱通常會是 arm-none-eabi-gcc,這一方面是為了和可以產生開發系統主機應用程式的gcc 進行區別,另一方面則是強調輸出結果是 arm 的代碼,none 即是無作業系統的意思,而eabi 則是 ARM 公司為了統一各個編譯器所產生的 .o 代碼之間可以彼此互相呼叫所制定的標準。

除以上四點之外,所謂的「裸機」 (Bare-Metal) 所採用的 GCC toolchain 基本上和交互編譯 Linux 時的並無太大差異。

操作方法 Operation Howto

其實不論是 IDE 或是 GCC,在編譯程式時的處理原則都是相通的,只是讓使用者設定編譯流程的方式不同而已。以下我們就很簡短地分析一下編譯程式的動作到底有哪些。

一般而言,編譯源碼的時段會區分成兩大步驟。

第一步驟稱為編譯時段,也就是將個別的源碼檔案(如 .c 檔案)編譯成為 .o 的 object file,有時亦會編譯成為 .s 等組合語言檔案,再由組譯器編譯成為 .o 檔案。基本上這個過程就是將程式員看得懂得 C 語言源碼,轉換成機器看得懂得 binary code,但為了未來與其它程式代碼相互呼叫的需要,會保留本身的名稱表 (symbol table),以供未來 linker 執行時的參考。此外,由於在目前尚未決定這些二進制代碼將來被載入機器時的記憶體位置,.o 檔案中也隱含了一些代碼之間的相對位址指標,也是在未來的連結時段時會被 linker 補上正確的絕對位址。

當處理完所有的源碼檔案之後,接下來的第二時段也就是連結時段,主要工作就是將個別的 .o 連結起來,並且會引入整個應用程式所需要的動態函式庫 .a 檔案(MCU 嵌入式系統大半沒有動態函式庫的設計),較為聰明的 linker 除了會根據編譯時段所產生的名稱表解釋將 .o 檔相互結合,以及解決上述時段的代碼位址問題之外,還會進行一些最佳化的動作,比方說去除在整個應用程式執行過程中根本沒有呼叫到的函式。

而一般而言,我們只要呼叫單一程式 gcc,就會自動幫我們呼叫編譯器 (cc) 以及連結器 (ld) 去進行相關的工作。所以為單晶片 MCU 編譯最簡單的 “Hello World” 的命令會類似於

1
arm-none-eabi-gcc -o hello.elf hello.c startup.s

其中的 startup.s 就是先前所說的啟動程式碼。但是實際運作的細節又可能會有其他的考量,我們在 TT0004 – 在 Cortex-M3 上運用 CodeSourcery 裸機工具鏈 一文中來作一些更深入的探討。

make 與 Makefile

一般我們在運用 GCC 時會利用 Makefile 的方式來操作,而不會如前述般直接透過命令列敲入編譯命令。因為你可能會自訂一些 CFLAGS 或 LDFLAGS ,而且源碼文件也可能很多,散佈在不同的目錄和專案中,這些複雜的設定與動作是利用 shell script 命令也無法忠實傳達的,因此我們需要利用make 這個工具來協助我們管理。而 make 最基本的動作就是去尋找當前目錄之下的 makefileMakefile 檔案,並加以解釋與執行相關操作。簡單的 Makefile 寫起來就像是在指定一些 shell 命令和動作,倒也不會太難。但是我們主要是想利用 Makefile 的一些巨集擴展功能,自動幫忙處理各種檔案類型的源碼,所以實際上的Makefile 會複雜上許多,網路上已經有不少很好的介紹文章,因此我們在此也不再贅述,我們推薦參考以下幾篇文章。

  • “今天的 Tetralet 又在唧唧喳喳了”的 Makefile 語法簡介
  • “用 Open Source 工具開發軟體: 新軟體開發觀念”的 Chapter 5. Makefile撰寫

如果你和筆者一樣,實在記不太牢 Makefile 的語法,不妨看看下面幾篇相關於另外一套也相當好用的工具 CMake 的文章。

  • 系統開發界名人 jserv 的貓也會的 CMake
  • MCUApps 的打造一個專屬的 MCU 開發工具箱

GCC toolchains for ARM

由於所謂的 GCC 是一些工具的組合,所以就有不少善心人士,自行測試、修改、再組合各個版本的工具,發行自己的 toolchains。一方面是滿足自己需求,另一方面則是造福普羅大眾。當然也有不少是加上了一些商業性的私有工具如除錯器、IDE 等,再予以販售。總之,市面上流行的 GCC toolchains for ARM 還滿熱鬧的,以下我們略為介紹較常會被開源專案所採用的幾套 toolchains。

Sourcery CodeBench Lite Edition

CodeSourcery Lite 發行了相當豐富的 GCC toolchains,包含我們所需要的 ARM bare-metal 版本。由於它是由一家商業公司所發行,開發人力資源較充裕,經常會整理出不少工具程式的 patches,用以獨家發行自己的 toolchain。所以可以預期的是工具本身的 bugs 可能會較少,如果在開發過程中遭遇難以理解或解決的問題時,經常可以拿這套 toolchain 來試著驗證看看。

又因為 CodeSourcery 並不支援筆者較常採用的 Mac OS X 平台,而其所用以製作編譯程式的 makefile 移植性又較差,因此就有善心人士加以改寫並釋出summon-arm-toolchain,以便使用者自行編譯,也相當方便好用。

YAGARTO – Yet another GNU ARM toolchain

YAGARTO 似乎是一個程式高手所發行的 toolchain,最大優點有二:一是直接支援非 Linux 的兩大作業系統平台:Windows 與 Mac OS X。另一個優點則是工具版本很新,經常跟得上最近的更新。

有些朋友可能會懷疑工具太新會不會有問題,的確這是一個考量。不過 GCC 最近的新版本在編譯出來的程式大小和效率上,非常讓人吃驚,甚至不時超越商業發行的 Keil 和 IAR 的結果,所以成為「追新一族」也有其必要性。

devkitPro

devkitPro 也是一套頗負盛名的 GCC toolchain,目前共計針對三個 ARM、PPC、和 PSP 等三個 CPU 平台分別推出三大主流桌面系統 Windows、Mac OS X、和 Linux 上的安裝包,都可以透過Getting Started 上取得。

筆者之所以會接觸到這套 toolchain 的過程也很有意思,當時是為了編譯一些能夠在 Wii 上面執行的應用程式。像是這麼封閉的系統,還硬是有人把開發工具給搞了出來,還推出各種可用的 libraries。這些高手的耐心與功力實在非常令人佩服,更可佩的是他們長期不斷地持續灌溉回饋給開放社群。

安裝建議 Installation Suggestions

面對那麼多套的 GCC toolchains,到底哪一套比較好呢?筆者的建議是能裝幾套就多裝幾套!因為經常遇到的狀況是有些專案的設定剛好只能配合某一套 toolchain,或是某些定義或函數只在某套 toolchain 中出現。當編譯發生錯誤,尤其又碰到是剛從網路上抓下來的開源專案時,換一套 toolchain 經常能夠立刻解決問題。因為我們最好能夠在下手改動程式碼之前,先確定這套程式碼可以如同預期般工作。

一個通常的作法是把這幾套 toolchains 通通掛到 /opt/ 目錄下,然後用再建立一個 symbolic link 如 /opt/arm-cs-tools 指向其中一套。如此一來只要將 /opt/arm-cs-tools/bin 包含在 PATH 環境變數中,就可以呼叫到需要的 arm-none-eabi- 開頭的工具。要切換 toolchain 也很簡單,將/opt/arm-cs-tools 更改一下所指向的目錄即可。

當你能夠成功編譯產生 .elf 檔案之後,接下來就會面臨燒錄與除錯的問題,目前 ARM 系列處理器通行的作法是透過 OpenOCD 這套萬用仿真器驅動之 GDB server 工具進行操作,網友可以繼續查閱。

GCC toolchain for MSP430

MSP430 版本的 GCC 被稱為 mspgcc,這部分基本上與一般 GCC toolchain 的操作無異。從它的首頁可以看到支援的平台有 Windows、Mac OS X、OpenBSD、還有兩種主流 Linux – Ubuntu 和 Fedora。當然也提供有 source code 讓你自己抓回去編譯。

TI 的開發套件工具基本上都有附帶 programmers 和 emulators 硬體支援,這本來是一件好事,但是種類好像有點太多了,先蒐集一些資料日後再整理。

The MSP-FET430UIF is a powerful flash emulation tool to quickly begin application development on the MSP430 MCU. It includes USB debugging interface used to program and debug the MSP430 in-system through the JTAG interface or the pin saving Spy Bi-Wire (2-wire JTAG) protocol. The flash memory can be erased and programmed in seconds with only a few keystrokes, and since the MSP430 flash is ultra-low power, no external power supply is required.

不過為了要除錯所需,原本需要啟動一個稱為 gdbproxy 的 GDB server,透過這個 proxy 才能將 MSP430 的 gdb 連到實際的 RF2500, eZ430, FET430UIF, Launchpad 等等各種的的 programmers 和 emulators 上。後來則是有善心人士整合出來一個稱為MSPDebug 的工具,透過這個工具就可以進行各式各樣的除錯操作了。甚至包含了 simulator 的功能,非常偉大。

Linux

先放一個連結 A Step by Step Guide To MSP430 Programming under Linux,有空再消化一下。

Mac OS X

官方有整理出來一個入口 MSP430 LaunchPad Mac OS X。寫得還不錯,不過關鍵在於 USB 的除錯介面驅動程式語焉不詳,搞不太懂到底是要怎樣。

後來在回應中看到 MSP430 LaunchPad toolchain for Mac OS X 有出懶人包,尤其是已經整合了一個帶 Virtual COM port 的萬用 USB 驅動程式,通通放在osx-launchpad 上,抓下來安裝一下就可以用了。以後再細看到底 patch 了哪些東西。

MSPDebug

MSPDebug 是 Anusha Beer 佛心的作品,可以透過 libUSB 在 userspace 直接與 TI 和其它 3rd party 廠商的燒錄除錯工具配合。目前計有 RF2500, eZ430, FET430UIF (V2 and V3), Launchpad, Chronos, Olimex MSP430-JTAG-TINY and MSP430-JTAG-ISO 等燒錄器。並且支援 TI flash bootloader。本身可以作為 GDP remote stub 且/或 GDB client 端。

使用上相當簡單,在命令後指定介面驅動方式,接著一些動作命令即可,如下例是燒錄 MSP430 LauchPad 範例程式代碼:

1
mspdebug rf2500 "prog launchpad.elf"

參考資料 References

  • Building Bare-Metal ARM Systems with GNU
  • Balau 的 embedded software,裡面有許多篇文章講解了非常多關於 bare metal 的 GCC 開發方法,內容詳實,比起上一份參考資料,更適合沒耐心的人直接參考。