天天看點

S3C2416裸機開發系列十四_GCC下UCGUI的移植(2)S3C2416裸機開發系列十四

象棋小子    1048272975

現在主要講解一下在gcc移植ucgui,makefile工程如何加入目錄,加入源碼,c标準庫,編譯選項的設定。

筆者的makefile模闆提取自uboot,工程中加入目錄,加入源碼都是很簡單的,詳細的介紹請參考前面章節” gcc啟動代碼工程應用執行個體”。下面主要介紹ucgui目錄下很多的源碼檔案makefile的編寫,一種可行的方式就是把gui目錄上所有的c檔案,不管有無用到,均加入工程進行編譯,第一次編譯時間較長,但以後不用重複編譯。是以這部分的makefile實作如下:

include $(topdir)/config.mk

srcs   := $(wildcard *.c)$(wildcard *.c)

objs   := $(srcs:.c=.o)$(srcs:.c=.o)

curdir := $(shell pwd)

folder := $(notdir $(curdir))

lib := lib$(folder).a

.phony: all clean

all: .depend $(lib)

$(lib): $(objs)

    @$(ar) $(arflags) $@ $(objs)

clean:

    rm -f .depend *.o $(lib)

#########################################################################

# defines$(obj).depend target

include$(topdir)/rules.mk

sinclude .depend

把這個makefile模闆加入到gui下所有的子目錄和guidemo目錄中,其它目錄的makefile也類似編寫加入,這樣即可把所有要編譯的源碼加入工程。每個子目錄的makefile需加入該目錄下要編譯的源碼檔案,生成該目錄下的源碼依賴關系檔案.depend,最終生成該目錄下的靜态庫檔案,以供頂層目錄的makefile連結輸出相應的可執行代碼檔案,工作方式與uboot是完全一緻的。

修改頂層目錄的makefile,加入各個子目錄makefile的路徑,以調用編譯該目錄下的源碼。子目錄路徑subdirs變量的修改如下:

subdirs = $(topdir)/start_code $(topdir)/apps

subdirs += $(topdir)/gui/antialias $(topdir)/gui/convertcolor \

       $(topdir)/gui/convertmono  $(topdir)/gui/core \

       $(topdir)/gui/font  $(topdir)/gui/lcddriver \

       $(topdir)/gui/memdev  $(topdir)/gui/multilayer \

       $(topdir)/gui/widget  $(topdir)/gui/wm

subdirs += $(topdir)/gui_x $(topdir)/guidemo

修改頂層目錄的config.mk,對編譯選項如-o2二級編譯優化或-g加入調試等進行設定,此處需加入工程c編譯器的頭檔案的搜尋路徑,對于ucgui頭檔案搜尋路徑隻需加入config、gui/core、gui/widget、gui/wm這四個目錄路徑即可。頭檔案搜尋路徑cflags變量的修改如下,s3c2416沒有硬體浮點單元,加-msoft-float防止配置成隻支援硬浮點的交叉工具通過編譯。

cflags := -wall  -wstrict-prototypes  -mcpu=arm920t -msoft-float

cflags += -i $(topdir)/start_code  -i$(topdir)/apps

cflags += -i $(topdir)/gui/core  -i$(topdir)/gui/widget \

      -i $(topdir)/gui/wm  -i $(topdir)/config

cflags += -i $(topdir)/guidemo

設定庫,嵌入式開發很大程度上依賴于标準c庫。在linux作業系統下,标配的c庫為glibc,glibc囊括了幾乎所有的unix通行标準,可見其内容包羅萬象。是以glibc對于很多嵌入式系統來說過于臃腫和龐大,并且很多函數嚴重依賴于linux的系統調用。筆者在較老版本交叉編譯工具開發裸機代碼,可以連結glibc,但新版本的工具卻無法順利連結glibc。為了解決glibc在嵌入式應用中的不足,很多面向嵌入式的c标準庫已經被開發出來,如uclibc、newlib、eglibc等。這些嵌入式c庫特點就是比glibc小很多,相對獨立,可不需要作業系統支援,不支援glibc的完整實作,很多功能可以根據空間需求進行取舍。一般開發linux系統,可以用glibc,如果對代碼容量等方面有要求,也可使用嵌入式c庫。筆者測試用相同的ucgui移植代碼分别連結uclibc和glibc,代碼容量差距相當明顯,連結uclibc時,可執行代碼隻有270k,而glibc達到700k。此處采用uclibc作為c庫,對于在linux下做開發而采用glibc的讀者,可以下載下傳uclibc的最新源碼庫,通過make

menuconfig簡單配置,用交叉編譯工具編譯源碼庫,即可生成交叉編譯工具可使用的c庫。嵌入式開發最常使用到字元處理、數學處理方面的庫函數,非linux作業系統開發,隻能連結靜态庫,在linux下對應庫名為libc.a和libm.a。由于不使用glibc,是以标準c庫應指定uclibc的庫存放路徑。同時,對于沒有硬體除法器,浮點處理單元的arm,對取餘和除法操作,浮點處理都需要libgcc.a的支援。ucgui移植用到了這三個庫,是以需要在makefile中指定這三個庫的路徑,庫路徑設定如下,對于uclibc中的libc.a和libm.a庫路徑,需要讀者根據自己的嵌入式庫路徑進行修改。

platform_libs :=

# 加入uclibc标準c庫以及數學函數庫

platform_libs += -l /opt/crosstool/uclibc-0.9.33.2/lib -lm -lc

# 加入gcc庫

platform_libs += -l $(shell dirname `$(cc) $(cflags)-print-libgcc-file-name`) –lgcc

至此,makefile工程設定完畢,跳轉到頂層目錄,執行make即可開始編譯工程。編譯時産生一大堆錯誤,主要是提示頭檔案未找到,micrium給出的guidemo目錄下的測試代碼寫的不夠嚴謹,源代碼中include頭檔案名不區分大小寫。例如實際要#include“gui.h”,但有些源碼中是#include"gui.h",這對于windows來說是沒有差別的,因為windows檔案系統不區分大小寫,但linux卻是區分大小的,是以會提示找不到檔案。windows作業系統假定它的使用者是兒童,對一般使用者來說,apple和apple都是蘋果,沒有差別。但linux/unix作業系統假定它的使用者是專業人士,apple和apple雖然都是蘋果,但它們的大小、産地、口感等均是不同的,是以是有差別的。為了代碼的可重用,這些問題都是需要注意的,尤其是同時在windows和linux下做開發,應保證一定的規範性。如在windows下檔案目錄名區分大小寫,在linux下檔案名加字尾(如.c、.h)表示這個檔案的用途等。此處沒有好的方法,隻能修改guidemo下所有不區分頭檔案名大小寫的源碼。

修改編譯通過後,會在頂層目錄生成三個比較重要的檔案,ucgui.map為連結mapping檔案,這裡可以看到各個全局符号、各個段記憶體連結位置、大小等資訊。s3c2416.dis為工程的彙編生成檔案,這是編譯器經過編譯所有的源碼并進行連結最終給出的彙編檔案,這是最權威的查錯檔案,編譯器的bug以及任何使用者的失誤造成編譯器未能很好地按照使用者的本意編譯等出現的問題,在這裡都可以查找出。s3c2416.bin即為我們用來燒錄進sd卡或nand等存儲器的二進制代碼檔案。

此處說明一點,筆者此系列的裸機例程都是有啟動代碼的,可以自動從sd/mmc卡、nand啟動的,代碼的燒錄與一般的bootloader的燒錄方式無異。最常用的燒錄方式是把裸機bin代碼通過sdboot工具進行格式轉換,再通過三星sd卡燒寫工具irom_fusing_tool把轉換後的bin代碼燒寫進sd卡,設定成sd卡啟動即可。從sd卡啟動成功後,通過調用相關的nand子產品接口函數,實作代碼固化進nand,以後即可從nand啟動。詳細教程請參考筆者前面章節的” gcc啟動代碼工程應用執行個體”或” mdk啟動代碼工程應用執行個體”。

筆者采用了相同的ucgui移植源碼在mdk、gcc下進行編譯,mdk和gcc均設定成二級優化條件下,對比這兩個平台下編譯器、标準c庫的差異。

編譯後,mdk下生成的二進制可執行代碼大小為250k,而gcc在采用uclibc标準庫時可執行代碼大小為273k,在老版本的gcc交叉編譯工具上,采用glibc生成的代碼大小為700k,從代碼容量看,mdk生成的代碼更小,采用gcc加uclibc并不比商業公司開發的平台工具差很多。在linux下做嵌入式開發,對代碼容量、性能有要求的話,無特殊情況,采用嵌入式c庫如uclibc、newlib等更适合。

均把所有源碼加入工程中進行全部編譯,mdk下編譯時間需225秒,可以明顯看到提示視窗的源碼在一個一個編譯,gcc下編譯時間為42秒,源碼編譯時可看到視窗是在刷屏的,編譯速度不是mdk能比的。

此處并不能準确對比mdk與gcc代碼生成品質的優劣,隻能以ucgui多層裁剪測試作為一個對比項。mdk生成的可執行代碼裁剪打點速度為11526060 pixel/秒,而gcc生成的可執行代碼打點速度為11985690 pixel/秒,打點速度gcc高出4%,可以看出開源免費的gcc編譯器以及c庫uclibc同樣高效優越。

對比可以看出,gcc與mdk不分上下,某些方面gcc做的更好,如編譯速度。當然,mdk還有必殺技microlib,這是mdk專為arm嵌入式應用高度優化的庫,用了這個外挂庫後,任何其它編譯器的标準c庫都暗然失色,當然隻能夠支援部分c庫的實作。總體來說,對于移植平台多、開源免費的gnu軟體來說,能達到絲毫不輸商業軟體的性能,确實令人尊敬,選擇gnu軟體進行開發也是相當不錯的。

移植後的ucgui效果:

S3C2416裸機開發系列十四_GCC下UCGUI的移植(2)S3C2416裸機開發系列十四
S3C2416裸機開發系列十四_GCC下UCGUI的移植(2)S3C2416裸機開發系列十四
S3C2416裸機開發系列十四_GCC下UCGUI的移植(2)S3C2416裸機開發系列十四
S3C2416裸機開發系列十四_GCC下UCGUI的移植(2)S3C2416裸機開發系列十四

對于ucgui的移植,總體還是比較簡單的,主要是根據特定的lcd和觸摸屏進行相應的接口移植,這隻需要實作相應的lcd、觸摸屏驅動子產品即可。如果讀者在windows下進行過win32視窗程式設計(非mfc),那麼對于ucgui的界面程式設計也會是得以應手的。

ucgui_mdk.rar,mdk平台下的ucgui 3.98版移植源碼工程,需根據特定lcd、觸摸屏進行驅動子產品的更改。

ucgui_gcc.rar,gcc下ucgui3.98版移植源碼工程,涉及到makefile的編寫,編譯器、連結器、标準庫等的設定,對了解編譯工具的原理有一定的幫助,可供參考。

繼續閱讀