日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 嵌入式 > 嵌入式教程
[導讀]八位微控制器的代碼優(yōu)化技巧

本文將介紹一些優(yōu)化技術,幫助設計人員節(jié)約多達 10% 的代碼空間,從而讓容量有限的程序存儲器支持更多新特性和補丁。

良好的操作方法

許多程序員在 32 位處理器上學習編寫軟件,如 Intel 的 Pentium 處理器或某種 ARM 平臺。不過,嵌入式領域的軟件編寫需要不同的思路。在 32 位 CPU 上,存儲比特位的最佳方法通常是使用 32 位變量。對 8 位處理器而言,最好的辦法就是采用單字節(jié)。像增強型 8051s 等某些處理器可能提供特殊的 1 位變量。

嵌入式處理器通常會超出標準的哈佛架構(gòu)將存儲器分散到不同的存儲器空間中,有的相互重疊,有的又是相互分離。例如,8051 中常見的存儲器空間包括 CODE、XDATA、DATA、IDATA、BIT 以及寄存器等。當要決定在何處存放變量時,了解每個存儲器空間的優(yōu)缺點顯得非常重要,特別是在各個存儲空間的容量都有限時更是如此。例如,IDATA 空間可能只能運行 256 個字節(jié),不過它為間接存取進行了優(yōu)化。雖然 DATA 空間也只能運行 256 個字節(jié),但它包括了 位可尋址空間和寄存器。盡管 CODE 和 XDATA 只能通過慢速間接存取機制進行訪問,但它們的尋址空間卻高達 64K。

許多 8 位 CPU 的編譯器包含了很多優(yōu)化程序,不過,這些優(yōu)化程序都有其局限性。如果可以,應該盡可能簡化表達。例如下面這段代碼:

X = a * CONSTANT1;

X *= CONSTANT2;

通常要比下述代碼多占空間:

X = a * CONSTANT1* CONSTANT2;

因為編譯器能將兩個常量合并為一個。

優(yōu)化——三思而后行

經(jīng)驗豐富的木匠都知道做事應該事先作好計劃,三思而后行。嵌入式固件工程師也應該遵循這一原則。所有嵌入式編譯器都提供了一個可給出有用信息映射文件。如圖 1 所示,該映射文件提供了本文所用代碼示例的有用信息。圖中所示的庫 (LIB_CODE) 使用的空間超過了 1K,而且啟動代碼 (c51startup) 使用的代碼超過了 140 字節(jié)。

進行優(yōu)化的另一原因是可以節(jié)約時間。在優(yōu)化之前,衡量程序的性能尤為重要。顯而易見,如果源文件過大,肯定會占用大量的存儲器空間,但我們很難測定代碼的哪些關鍵部分在消耗寶貴的 MIPS。在此過程中,我們可將程序概要分析 (Profiling) 作為一個重要的工具來加以利用。

我們可利用未使用的單一輸出引腳來進行程序概要分析,不過輸出引腳越多,分析也就越容易。我們可創(chuàng)建一個宏來設置程序概要分析輸出,如下所示,再將宏放在每個例程的起點和終點處。

 

了解支付情況

[!--empirenews.page--]

在上述的映射文件中,我們了解到庫占用了 1K 的寶貴存儲器空間。深入查看映射文件,通過 Excel 進行分析后得到了如圖 2 所示的結(jié)果。我們從圖中移出較小的庫函數(shù)部分。盡管這些函數(shù)名稱比較晦澀,不過我們可以對照庫參考資料逐一了解其含義。首先,ULDIV 是指無符號數(shù)的長除法 (long division),而圖中第二個則是指長乘法 (long multiplication)。

.map 文件的交叉參考表明我們很幸運:上述函數(shù)只用于一個文件中。.lst 文件顯示了長除法函數(shù)的兩種使用情況以及長乘法函數(shù)的一種使用情況 

glNandDevCapacity = CYAN_NAND_DEV_NUMPAGES_BLOCK * CYAN_NAND_UBLKS_PER_ZONE * (uint32_t)glNandNumZones;

在該特定案例中,我們知道 zone 的數(shù)量是一個二進制數(shù),而另兩個值為常量。因此,我們可用重復 8 次的左移位 (left shift) 操作替代長乘法:

{

char zoneCtr = glNandNumZones;

glNandDevCapacity = CYAN_NAND_DEV_NUMPAGES_BLOCK * CYAN_NAND_UBLKS_PER_ZONE;

while (zoneCtr)

{

glNandDevCapacity <<= 1;

zoneCtr >>= 1;

}

}

盡管這個例程相當大,但它仍能減少庫的使用并減小代碼的整體大小。

掌握比編輯器更多的信息

成熟的 8 位編譯器包括代碼編寫良好、經(jīng)過優(yōu)化的庫函數(shù)。不過,這些函數(shù)須考慮到通過對數(shù)據(jù)的了解可自行處理的一些不常見情況。映射文件中顯示的最大庫函數(shù)就是這樣一個很好的例子。調(diào)用兩次 ULDIV 例程,以獲得輸入值除以常量后得到的除數(shù)和余數(shù): 

zn = (adj_lba / CYAN_NAND_UBLKS_PER_ZONE);

glNandRelativeBlkAddr = (adj_lba % CYAN_NAND_UBLKS_PER_ZONE);

由于我們在預期值方面比編譯器了解的更多,因此我們可以讓編譯器不使用龐大的長除法函數(shù),而采用較小的 16 位版本來替代。

{

xdata unsigned char lastNibble = adj_lba & 0xf;

adj_lba >>= 4;

zn = ((uint16_t)adj_lba / (uint8_t)CYAN_NAND_UBLKS_PER_ZONE/16));

glNandRelativeBlkAddr = ((uint16_t)adj_lba % (uint8_t) (CYAN_NAND_UBLKS_PER_ZONE/16));

glNandRelativeBlkAddr = (glNandRelativeBlkAddr << 4) + lastNibble;

}

激進的的程序優(yōu)化者甚至可能實現(xiàn)他們自己的二進制長除法例程。[!--empirenews.page--]

全局變量更好用

將參數(shù)傳遞給函數(shù)是一個很好的代碼經(jīng)驗。在 C 程序中,編譯器可絕對確保調(diào)用的子程序不會修改參數(shù)。編譯器可處理存儲器管理的問題。不過,這將占用難以承受的大量時間和空間。試考慮下面這段代碼:

Main()

{

Int effectiveGlobal;

Foo(effectiveGlobal)

}

由于變量在 main() 中已經(jīng)聲明,因此該變量與真正的全局變量之間的真正差別是命名空間 (namespace)。但是,每次調(diào)用 foo() 時,編譯器都必須在新的位置存儲 effectiveGlobal。聲明真正的全局變量有助于降低因調(diào)用而造成的代碼和數(shù)據(jù)開銷。

向編譯器提供盡可能多的信息

8051 可提供 64K 的地址空間 XDATA、256 字節(jié)的堆棧與間接尋址空間 IDATA 以及 256 字節(jié)的直接尋址空間 DATA 等多個存儲器空間。在大多數(shù)情況下,代碼編寫人員都知道指針指向了哪個存儲器空間。如果用戶指定了存儲器空間,編譯器就無需包含對例程中的所有三類存儲器進行尋址的代碼,只需使用一個即可。由于指針無需包含數(shù)據(jù)空間信息,因此有助于節(jié)約數(shù)據(jù)空間。

在我的 8051 編譯器中,上述變量可通過包含 OPTR 字符串的庫例程進行存取。在列表和庫文件中搜索對OPTR的引用可以發(fā)現(xiàn)長變量被多次使用,而且由于在代碼中假定了指針的大小,其中某些長變量還會導致一些問題。

在變量聲明中使用 const 關鍵詞可以實現(xiàn)兩方面的優(yōu)化:第一,編譯器不必再存儲變量的初始值;第二,編譯器能在編譯時間而非執(zhí)行時間執(zhí)行一些數(shù) 學 運 算。查看示例程序的編譯輸出,以確定對 const與 #define 的處理是否真的一樣。以下是我對代碼的測試:

 

經(jīng)過測試,得到以下輸出,表明它并不清楚 const 變量的值。

匯編語言

不少嵌入式固件工程師信誓旦旦的表示他們始終能比編譯器做得更好,不僅如此,他們還認為應該使用匯編語言重新編寫所有代碼。然而事實上,現(xiàn)代編譯器提供的許多特性已經(jīng)能趕上人腦的水平了。

變量共享:一些 8 位處理器尚無有效的機制來存取堆棧上的變量。一般的解決方案是創(chuàng)建調(diào)用樹,并在相互不進行調(diào)用的函數(shù)間共享變量。在匯編程序中要想保持這種結(jié)構(gòu)相當困難,且容易出錯。

可靠性:任何從事專業(yè)軟件或固件開發(fā)工作的人員都能讀懂 C 語言程序。如果您需要將代碼交給其它開發(fā)人員處理,他們無需掌握那些為發(fā)揮匯編語言的最大效率而需要的所有技巧便可立即開始修改代碼。

可移植性:C 語言最初的開發(fā)目的之一就是要提供一種非常抽象,以便可以在多種處理器上應用的語言。這一目標至今仍然非常重要。

代碼共享:許多 8 位編譯器都能在鏈接時間之后進行優(yōu)化,這使得編譯器不僅能執(zhí)行許多人工能完成的優(yōu)化,而且還能完成一些人工所不能完成的優(yōu)化。例如,現(xiàn)在許多編譯器都能搜索不同函數(shù) 中 共 有的代碼字符串,并將其合并為一個新的函數(shù)。而人類是不可能記住每個編譯周期中執(zhí)行此函數(shù)所需要的全部細節(jié)的。

匯編語言現(xiàn)在仍占有一席之地。不過,在使用匯編語言之前應首先考慮上述所有因素。

結(jié)論

在撰寫本文的過程中,我將成熟程序的大小從 0x6000 多字節(jié)縮減到了 0x5f2b 字節(jié),節(jié)約了 200 多字節(jié)。該程序過去曾是多次試圖優(yōu)化程序大小的目標。

本站聲明: 本文章由作者或相關機構(gòu)授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

全球半導體短缺讓所有微控制器使用者的生活都變得難熬了起來,如今的訂貨周期有時會長達好幾年。不過,售價4美元的樹莓派Pico是一個亮點,它是一個以新型RP2040芯片為基礎的微控制器。RP2040不僅有強大的計算能力,還沒...

關鍵字: 半導體 微控制器 芯片

據(jù)業(yè)內(nèi)消息,近日三星在一年一度的技術日研討會上公布了未來的3大規(guī)劃方向,其中包括1.4納米的代工制程工藝以及包括NAND、DRAM在內(nèi)的各類內(nèi)存和無晶圓廠的整體解決方案。

關鍵字: 存儲 三星 NAND DRAM

NAND Flash閃存芯片已經(jīng)低迷一年了,但看起來對應的SSD價格還沒觸底。知名分析機構(gòu)Trendfocus分析師在最新報告中指出,盡管主要顆粒廠已經(jīng)開始削減產(chǎn)能,然而存儲芯片和固態(tài)硬盤庫存過剩的情況極其嚴重,他甚至預...

關鍵字: SSD NAND PCIE 固態(tài)硬盤

在如今大數(shù)據(jù)時代,NAND閃存無疑是數(shù)據(jù)存儲的奠基者。不管是手機、電腦、家電還是汽車、安防等行業(yè),都少不了NAND閃存的身影,其重要性可見一斑。

關鍵字: NAND 閃存 密度

在下述的內(nèi)容中,小編將會對MCU微控制器的相關消息予以報道,如果MCU微控制器是您想要了解的焦點之一,不妨和小編共同閱讀這篇文章哦。

關鍵字: MCU 微控制器 智能控制

今天,小編將在這篇文章中為大家?guī)鞰CU微控制器的有關報道,通過閱讀這篇文章,大家可以對MCU微控制器具備清晰的認識,主要內(nèi)容如下。

關鍵字: MCU 微控制器 物聯(lián)網(wǎng)

MCU微控制器將是下述內(nèi)容的主要介紹對象,通過這篇文章,小編希望大家可以對MCU微控制器的相關情況以及信息有所認識和了解,詳細內(nèi)容如下。

關鍵字: MCU 微控制器 芯片

一直以來,MCU微控制器都是大家的關注焦點之一。因此針對大家的興趣點所在,小編將為大家?guī)鞰CU微控制器的相關介紹,詳細內(nèi)容請看下文。

關鍵字: MCU 微控制器 控制器

在這篇文章中,小編將對MCU微控制器的相關內(nèi)容和情況加以介紹以幫助大家增進對MCU微控制器的了解程度,和小編一起來閱讀以下內(nèi)容吧。

關鍵字: MCU 微控制器 芯片

單片機又稱單片微控制器,它不是完成某一個邏輯功能的芯片,而是把一個計算機系統(tǒng)集成到一個芯片上。相當于一個微型的計算機,和計算機相比,單片機只缺少了I/O設備。概括的講:一塊芯片就成了一臺計算機。它的體積小、質(zhì)量輕、價格便...

關鍵字: 單片機 微控制器 芯片

嵌入式教程

6897 篇文章

關注

發(fā)布文章

編輯精選

技術子站

關閉