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