前言
文章基于HD-IMX6ULL-MB 系列開(kāi)發(fā)板測(cè)試驗(yàn)證,該開(kāi)發(fā)板由武漢芯路遙科技有限公司與武漢萬(wàn)象奧科電子有限公司合作推出。此開(kāi)發(fā)板基于 NXP iMX6ULL 系列 Cortex-A7 高性能處理器設(shè)計(jì),適用于快速開(kāi)發(fā)一系列具有創(chuàng)新性的產(chǎn)品如人機(jī)界面工業(yè) 4.0 掃描儀、車載終端以及便攜式醫(yī)療設(shè)備。
在 X86 架構(gòu) Linux 系統(tǒng)下進(jìn)行 C 程序開(kāi)發(fā)時(shí), 我們使用系統(tǒng)的 gcc 編譯器進(jìn)行代碼的編譯, 編譯生成的可執(zhí)行程序直接在 X86 架構(gòu)下的 PC 下運(yùn)行的,這個(gè)過(guò)程叫做 本地編譯 (Native Compile) 。 而如果該C程序想要編譯出來(lái)后放到ARM處理器架構(gòu)的系統(tǒng)上運(yùn)行, 則需要在 X86 架構(gòu)Linux系統(tǒng)下使用支持 ARM 的編譯器編譯, 這個(gè)編譯器我們通常稱為 交叉編譯器 (Cross Compiler)。
而在一種平臺(tái)上編譯出能在另外一種體系結(jié)構(gòu)完全不同處理器上運(yùn)行程序的編譯過(guò)程,叫做 交叉編譯(Cross Compile)。比如在PC平臺(tái)(X86 CPU)上編譯出能運(yùn)行在以ARM為內(nèi)核的CPU平臺(tái)上的程序,編譯得到的程序在X86 CPU平臺(tái)上是不能運(yùn)行的,必須放到ARM CPU平臺(tái)上才能運(yùn)行,雖然兩個(gè)平臺(tái)用的都是Linux系統(tǒng)。
交叉編譯工具鏈?zhǔn)且粋€(gè)由編譯器、連接器和解釋器組成的綜合開(kāi)發(fā)環(huán)境,交叉編譯工具鏈主要由binutils、gcc和glibc三個(gè)部分組成。有時(shí)出于減小 libc 庫(kù)大小的考慮,也可以用別的 c 庫(kù)來(lái)代替 glibc, 例如 uClibc 或 newlib。
之所以幾乎所有的ARM開(kāi)發(fā)板開(kāi)發(fā)都選擇交叉編譯,這是因?yàn)檫@些開(kāi)發(fā)板生產(chǎn)出來(lái)后并沒(méi)有系統(tǒng),這 時(shí)需要在PC上使用交叉編譯器交叉編譯操作系統(tǒng)源碼,為它構(gòu)建一個(gè)完整的 Linux 系統(tǒng)。另外,由于CPU處理能力、外存和內(nèi)存存儲(chǔ)空間的大小限制,它們不足以能夠運(yùn)行 gcc 編譯環(huán)境,所以嵌入式開(kāi)發(fā)絕大部分的過(guò)程都是交叉編譯。
1.2.1 Codesourcery 交叉編譯器
Codesourcery一直是在做 ARM 目標(biāo) GCC 的開(kāi)發(fā)和優(yōu)化,它直接提供 Windows和Linux下的二進(jìn)制版本交叉編譯器,不用下載源碼包一步一步自己編譯,非常方便。它的 ARM GCC 早期在市場(chǎng)上非常優(yōu)秀,很多公司在作嵌入式產(chǎn)品開(kāi)發(fā)時(shí),都會(huì)直接下載使用該公司提供的交叉編譯器。
Codesourcery 推出的產(chǎn)品叫 Sourcery G++ Lite Edition, 其中基于 command-line 的編譯器是免費(fèi)的, 在官網(wǎng)上可以下載, 而其中包含的 IDE 和 debug 工具是收費(fèi)的, 當(dāng)然也有30天試用版本的。后來(lái)CodeSourcery 被明導(dǎo)國(guó)際(Mentor Graphics)收購(gòu), 現(xiàn)在則被西門子(Siemens) 收購(gòu)了。
其下載地址為: https://www.plm.automation.siemens.com/global/en/products/embedded-softwa re/sourcery-toolchain-services.html
1.2.2 Linaro交叉編譯器
除了CodeSourcery外,還有一個(gè)組織也提供ARM Toolchain,它就是Linaro。Linaro是在2010年臺(tái)北國(guó)際計(jì)算機(jī)展(COMPUTEX)期間,ARM、Freescale、Samsung ,ST-Ericsson、德州儀器(TI)與IBM等6家大廠,宣布合資成立的非贏利Linux基礎(chǔ)架構(gòu)軟件研發(fā)商。
Linaro目標(biāo)在投入新資源和集成業(yè)界的努力,改進(jìn)與優(yōu)化在ARM-based架構(gòu)上運(yùn)行的開(kāi)放原始碼軟件及 開(kāi)發(fā)工具,將過(guò)去必須由系統(tǒng)單芯片(SoC)業(yè)者,各自將本身產(chǎn)品與Linux操作系統(tǒng)集成與開(kāi)發(fā)的重復(fù)投 資,透過(guò)這間合資公司推出開(kāi)放原始碼的底層軟件工具,解決ARM生態(tài)系中,重復(fù)投資造成的資源浪費(fèi)。
其下載鏈接地址為: https://launchpad.net/linaro-toolchain-binaries
1.2.3 Ubuntu交叉編譯器
Ubuntu之所以能成為嵌入式系統(tǒng)開(kāi)發(fā)的首選Linux發(fā)行版本,正是因?yàn)樗能浖诰€安裝倉(cāng)庫(kù)中包含 有海量的開(kāi)發(fā)工具/軟件,其中就包括嵌入式系統(tǒng)開(kāi)發(fā)所需的交叉編譯器、dtc等開(kāi)發(fā)工具,這也就是為 什么幾乎所有主流的半導(dǎo)體廠商在發(fā)布SDK時(shí)都推薦使用Ubuntu系統(tǒng)。
在Ubuntu 系統(tǒng)中提供了如下四個(gè)版本的交叉編譯器軟件包:
在上面的軟件包中,gcc-arm-none-eabi 和 gcc-aarch64-linux-gnu 都比較好理解。而 gcc-arm-linux- gnueabi 與 gcc-arm-linux-gnueabihf 有什么區(qū)別呢?這就涉及到 ARM 處理器架構(gòu)中的浮點(diǎn)運(yùn)算相關(guān)知識(shí)了。
出于低功耗、封裝限制等種種原因,以前的一些ARM處理器沒(méi)有獨(dú)立的硬件浮點(diǎn)運(yùn)算單元,需要使用軟 件來(lái)實(shí)現(xiàn)浮點(diǎn)運(yùn)算。隨著技術(shù)發(fā)展,現(xiàn)在高端的ARM處理器基本都具備了硬件執(zhí)行浮點(diǎn)操作的能力。這 樣,新舊兩種架構(gòu)之間的差異,就產(chǎn)生了兩個(gè)不同的嵌入式應(yīng)用程序二進(jìn)制接口(EABI)——軟浮點(diǎn)
(SoftFP)與矢量浮點(diǎn)(VFP)。但是軟浮點(diǎn)(soft float)和硬浮點(diǎn)(hard float)之間有向前兼容卻沒(méi)有向后兼容的能力,也就是軟浮點(diǎn)的二進(jìn)制接口(EABI)仍然可以用于當(dāng)前的高端ARM處理器。
在ARM體系架構(gòu)內(nèi)核中,有些有浮點(diǎn)運(yùn)算單元(fpu,floating point unit),有些沒(méi)有。對(duì)于沒(méi)有fpu內(nèi)核,是不能使用armel和armhf的。在有fpu的情況下,就可以通過(guò)gcc的選項(xiàng)-mfloat-abi來(lái)指定使用哪種,有如下四種值:
1.soft:不用fpu計(jì)算,即使有fpu浮點(diǎn)運(yùn)算單元也不用。
2.a(chǎn)rmel:(arm eabi little endian)也即softfp,用fpu計(jì)算,但是傳參數(shù)用普通寄存器傳,這樣中斷的時(shí)候,只需要保存普通寄存器,中斷負(fù)荷小,但是參數(shù)需要轉(zhuǎn)換成浮點(diǎn)的再計(jì)算。
3.armhf:(arm hard float)也即hard,用fpu計(jì)算,傳參數(shù)用fpu中的浮點(diǎn)寄存器傳,省去了轉(zhuǎn)換性能最好,但是中斷負(fù)荷高。
4.arm64:64位的arm默認(rèn)就是hard float的,因此不需要hf的后綴。
在之前的EABI中,armel(低端ARM硬件)在執(zhí)行浮點(diǎn)運(yùn)算之前,浮點(diǎn)參數(shù)必須首先通過(guò)整數(shù)寄存器, 然后傳遞到浮點(diǎn)運(yùn)算單元。新的EABI ,也就是armhf,通過(guò)直接傳遞參數(shù)到浮點(diǎn)寄存器優(yōu)化了浮點(diǎn)運(yùn)算的調(diào)用約定。相比我們熟悉的armel,armhf代表了另一種不兼容的二進(jìn)制標(biāo)準(zhǔn)。在一些社區(qū)的支持下,armhf目前已經(jīng)得到了很大的發(fā)展。像Ubuntu,已經(jīng)計(jì)劃在之后的發(fā)行版中放棄armel,轉(zhuǎn)而支持armhf編譯的版本。正如目前依然很火熱的Raspberry Pi(ARM11),由于ubuntu只支持armv7架構(gòu)的編譯,Raspberry Pi將不能直接安裝ubuntu系統(tǒng)。而 BB Black(Cortex-A8)和 Cubietruct(Cortex-A7)則同時(shí)支持ubuntu的armel與armhf的編譯。
kernel、rootfs和app編譯的時(shí)候,指定的必須保持一致才行。使用softfp模式,會(huì)存在不必要的浮點(diǎn)到 整數(shù)、整數(shù)到浮點(diǎn)的轉(zhuǎn)換。而使用hard模式,在每次浮點(diǎn)相關(guān)函數(shù)調(diào)用時(shí),平均能節(jié)省20個(gè)CPU周期。 對(duì)ARM這樣每個(gè)周期都很重要的體系結(jié)構(gòu)來(lái)說(shuō),這樣的提升無(wú)疑是巨大的。在完全不改變?cè)创a和配置的 情況下,在一些應(yīng)用程序上,雖然armhf比armel硬件要求(確切的是指fpu硬件)高一點(diǎn),但是armhf 能得到20-25%的性能提升。對(duì)一些嚴(yán)重依賴于浮點(diǎn)運(yùn)算的程序,更是可以達(dá)到300%的性能提升。
接下來(lái)我們以大家熟悉的 hello world 程序?yàn)槔v解嵌入式交叉編譯過(guò)程。
1.3.1 本地編譯運(yùn)行hello程序
首先,我們使用 vim 編輯器編寫 hello.c 測(cè)試程序:
我們知道,C程序必須要使用編譯器編譯生成可執(zhí)行程序,才能執(zhí)行。接下來(lái)我們使用 Linux服務(wù)器上的
gcc 編譯該程序并運(yùn)行:
我們可以使用 file 命令查看 hello 程序的相關(guān)信息,由此可知該程序應(yīng)該在X86-64位的系統(tǒng)上運(yùn)行:
我們將該程序下載到開(kāi)發(fā)板上運(yùn)行試試看,這時(shí)系統(tǒng)會(huì)提示可執(zhí)行文件格式出錯(cuò),不能正常運(yùn)行。
1.3.2 交叉編譯運(yùn)行hello程序
我們知道C程序具有可移植性,使用PC上的編譯器編譯生成的程序應(yīng)該在PC上運(yùn)行,而不能在其他處理 器架構(gòu)上運(yùn)行,那怎樣讓 hello.c 程序在ARM開(kāi)發(fā)板上運(yùn)行呢?這里就需要使用ARM的交叉編譯器來(lái)對(duì)該程序進(jìn)行交叉編譯,這樣編譯輸出的可執(zhí)行程序就能在ARM開(kāi)發(fā)板上運(yùn)行了。
因?yàn)槲覀兊?i.MX6ULL 處理器帶有硬件浮點(diǎn)FPU,所以這里我們選擇安裝硬浮點(diǎn)交叉編譯器:
接下來(lái),我們使用 ARM 的交叉編譯器編譯該 hello.c 程序,并嘗試在 X86-64位 Linux服務(wù)器上運(yùn)行,我們會(huì)發(fā)現(xiàn) Linux 服務(wù)器上默認(rèn)并不能運(yùn)行該程序:
接下來(lái)我們使用 file 命令查看該程序的相關(guān)信息,由此可知該程序應(yīng)該在ARM處理器系統(tǒng)上運(yùn)行:
我們將該程序下載到開(kāi)發(fā)板上則能正常運(yùn)行了。
由此可見(jiàn):
C程序如果想在PC上運(yùn)行,則應(yīng)該用PC的編譯器來(lái)編譯;而該程序想要在ARM開(kāi)發(fā)板上運(yùn)行,則必 須用ARM的交叉編譯器對(duì)源碼重新進(jìn)行交叉編譯;
C程序具有可移植性是指,C程序源代碼不用作任何的修改,使用不同的編譯器編譯生成的可執(zhí)行程 序可以在不同的處理器架構(gòu)平臺(tái)上運(yùn)行;
版權(quán)聲明
本文檔所有內(nèi)容文字資料由凌云實(shí)驗(yàn)室郭工編著,主要用于凌云嵌入式Linux教學(xué)內(nèi)部使用,版權(quán)歸屬 作者個(gè)人所有。任何媒體、網(wǎng)站、或個(gè)人未經(jīng)本人協(xié)議授權(quán)不得轉(zhuǎn)載、鏈接、轉(zhuǎn)帖或以其他方式復(fù)制發(fā)布/發(fā)表。已經(jīng)授權(quán)的媒體、網(wǎng)站,在下載使用時(shí)必須注明來(lái)源,違者本人將依法追究責(zé)任。
Copyright (C)2021 凌云物網(wǎng)智科實(shí)驗(yàn)室·郭工
Author:GuoWenxue guowenxue@gmail.com