默認情況下,C庫利用semihosting機制來提供設(shè)備驅(qū)動級的功能,使得主機能夠用作輸入和輸出設(shè)備。這種機制對于嵌入式開發(fā)十分有用,因為用于開發(fā)的硬件系統(tǒng)通常沒有最終系統(tǒng)的輸入和輸出設(shè)備。
任何運行在實際硬件上的嵌入式應(yīng)用程序,都必須在啟動時實現(xiàn)一些基本的系統(tǒng)初始化。本節(jié)將對此予以詳細討論。
在創(chuàng)建多任務(wù)嵌入式系統(tǒng)時,最好有一個簡單的方式來編寫、裝載及運行各自獨立的任務(wù)。目前大多數(shù)的嵌入式系統(tǒng)不再使用自己定制的控制系統(tǒng),而使用操作系統(tǒng)來簡化這個過程。較高級的操作系統(tǒng)采用基于硬件的存儲管理單元MMU來實現(xiàn)上述操作。
本章主要講解C編譯器在代碼優(yōu)化時遇到的一些問題。要編寫高效的C語言源代碼,必須了解C編譯器對什么形式的代碼有所改動,編譯器涉及的處理器結(jié)構(gòu)的限制,以及一些特殊的C編譯器的限制。
因為ARM體系結(jié)構(gòu)本身并不包含除法運算硬件,所以在ARM上實現(xiàn)除法是十分耗時的。ARM指令集中沒有直接提供除法匯編指令,當(dāng)代碼中出現(xiàn)除法運算時,ARM編譯器會調(diào)用C庫函數(shù)(有符合除法調(diào)用_rt_sdiv,無符合除法調(diào)用_rt_udiv),來實現(xiàn)除法操作。根據(jù)除數(shù)和被除數(shù)的不同,32bit的除法運算一般要占有20-140個指令周期。
ARM指令都是可以條件執(zhí)行的。在代碼中使用條件執(zhí)行指令可以減小代碼密度并提高程序執(zhí)行效率。典型的條件執(zhí)行語句用在比較指令之后,形成程序的分支跳轉(zhuǎn)結(jié)構(gòu)。下面的例子顯示了條件執(zhí)行指令的典型用法。
通常,布爾表達式被用來檢測某個數(shù)值是否在特定的范圍內(nèi)。例如,在圖形窗口處理程序中,常使用布爾表達式判斷屏幕中一個點是否在當(dāng)前活動窗口范圍內(nèi)。
循環(huán)體是程序設(shè)計與優(yōu)化的重點考慮對象。本節(jié)將著重講解在ARM上處理for和while循環(huán)最有效的方法。
ARM處理器支持16個協(xié)處理器。在程序執(zhí)行過程中,每個協(xié)處理器忽略屬于ARM處理器和其他協(xié)處理器的指令。當(dāng)一個協(xié)處理器硬件不能執(zhí)行屬于它的協(xié)處理器指令時,將產(chǎn)生一個未定義指令異常中斷,在該異常中斷處理程序中,可以通過軟件模擬該硬件操作。比如,如果系統(tǒng)不包含向量浮點運算器,則可以選擇浮點運算軟件模擬包來支持向量浮點運算。
當(dāng)?shù)谝淮鶵ISC微處理器剛出現(xiàn)時,標(biāo)準(zhǔn)存儲器元件的速度比當(dāng)時微處理器的速度快。很快,半導(dǎo)體工藝技術(shù)的進展被用來提高微處理器的速度。標(biāo)準(zhǔn)DRAM部件雖然也快了一些,但其發(fā)展的主要精力則放在提高存儲容量上。
編譯器通常將C語言中的Switch語句編譯一個查找表(Table Lookup)以便跳轉(zhuǎn)到合適的入口處。
編譯器一項很重要的優(yōu)化功能就是對寄存器的分配。與分配在寄存器中的變量相比,分配到內(nèi)存的變量訪問要慢得多。所以如何將盡可能多的變量分配到寄存器,是編程時應(yīng)該重點考慮的問題。
ARM C編譯器支持基本的數(shù)據(jù)類型:char、short、int、long long、float和double。表14.2說明了armcc對C語言所使用的數(shù)據(jù)類型的映射。
函數(shù)設(shè)計的基本原則是使其函數(shù)體盡量的小。這樣編譯器可以對函數(shù)做更多的優(yōu)化。
大多數(shù)的ARM處理器硬件上并不支持浮點運算。但ARM上提供了以下幾個選項來實現(xiàn)浮點運算。
當(dāng)對源代碼使用不同的編譯器時,可能會出現(xiàn)一些移植上的問題,這時可以宏將一些ARM特有的關(guān)鍵字“打包”。
一些嵌入式系統(tǒng)使用多任務(wù)的操作和控制。這些系統(tǒng)必須提供一種機制來保證正在運行的任務(wù)不破壞其他任務(wù)的操作。即要防止系統(tǒng)資源和其他一些任務(wù)不受非法訪問。要達到這一目的通常有軟件保護和硬件保護兩種途徑。這里軟件保護是指僅靠軟件來保護系統(tǒng)資源。系統(tǒng)中無保護硬件或硬件沒啟動。在多任務(wù)的系統(tǒng)中,通常要運行操作系統(tǒng)來達到任務(wù)間同步與通信。
隨著片上系統(tǒng)設(shè)計變得更加精密、復(fù)雜,ARM處理器已成為包含多個處理部件和子系統(tǒng)的系統(tǒng)核心處理器。每個ARM處理器都有一個特定的指令集架構(gòu)ISA,ISA隨著嵌入式市場的需求而發(fā)展。每一個ISA的發(fā)布都是相后兼容的,這使得在較早的架構(gòu)版本上編寫的代碼也可以在后續(xù)版本上執(zhí)行。
為了滿足目前無線網(wǎng)絡(luò)、汽車電子和消費類電子產(chǎn)品不斷增長的市場需要,ARM公司在ARMv6中引入新的技術(shù)和結(jié)構(gòu)組成,包括增強的DSP支持和對多處理器環(huán)境的支持。
在ARM匯編語言程序里,有一些特殊指令助記符,這些助記符與指令系統(tǒng)的助記符不同,沒有相對應(yīng)的操作碼,通常稱這些特殊指令助記符為偽操作標(biāo)識符(directive),它們所完成的操作稱為偽操作。偽操作在源程序中的作用是為完成匯編程序作各種準(zhǔn)備工作的,這些偽操作僅在匯編過程中起作用,一旦匯編結(jié)束,偽操作的使命就完成。