詳述嵌入式系統(tǒng)下Microwindows的實(shí)現(xiàn)
前 言
目前,伴隨著各種手持、無線及嵌入式設(shè)備的迅猛發(fā)展,相應(yīng)的軟硬件設(shè)計(jì)也發(fā)生了很大的變化。許多設(shè)備都使用了Intel,MIPS,摩托羅拉的32位微處理器及大屏幕的液晶圖形顯示器。由于在過去10年中,桌面操作模式取得了巨大成功,于是許多開發(fā)者在嵌入式設(shè)計(jì)中開始使用類似于桌面的操作系統(tǒng)。其中一個(gè)比較好的方案就是使用Linux操作系統(tǒng)。由于Linux在嵌入式系統(tǒng)上具有桌面電腦的全部功能和特性,同時(shí)作為一種開放式源碼,它允許各種各樣的修改,并且還可以根據(jù)用戶的特定要求進(jìn)行定制。
Microwindows概述
Microwindows是一個(gè)著名的開放式源碼的嵌入式GUI軟件,目的是把現(xiàn)代圖形視窗環(huán)境引入到運(yùn)行Linux的小型設(shè)備和平臺(tái)上。作為XWindow的替代品,Microwindows可以使用更少的RAM和文件存儲(chǔ)空間(100K-600K)提供與XWindow相似的功能。該體系結(jié)構(gòu)允許設(shè)計(jì)者輕松加入各種顯示設(shè)備、鼠標(biāo)、觸摸屏和鍵盤等。Linux2.2以上版本的內(nèi)核代碼允許用戶將圖形顯存作為幀緩存進(jìn)行存取,這樣當(dāng)用戶對(duì)顯示設(shè)備進(jìn)行寫入、控制時(shí)可以避免對(duì)內(nèi)存映射區(qū)進(jìn)行操作,因此用戶可以在不了解底層圖形硬件或沒有使用過XWindow的情況下進(jìn)行圖形程序的開發(fā)。這就是為什么現(xiàn)在在嵌入式系統(tǒng)中廣泛使用Microwindows的原因。Microwindows的可移植性非常好,基本上用 C 語言實(shí)現(xiàn),只有某些關(guān)鍵代碼使用了匯編以提高速度。Microwindows支持 Intel16位、32位CPU,MIPS R4000 以及 ARM 芯片。
Microwindows已經(jīng)移植到一些掌上電腦。它的圖形引擎被設(shè)計(jì)成能夠運(yùn)行在任何支持readpixel, writepixel, drawhorzline和drawvertline, 和setpalette的系統(tǒng)之上。在底層函數(shù)的支持之下,上層實(shí)現(xiàn)了位圖,字體,光標(biāo)以及顏色的支持。Microwindows支持新的Linux內(nèi)核幀緩存結(jié)構(gòu),目前提供每像素1、2、4、8、16、24和32位的支持,另外還支持彩色顯示和灰度顯示,其中彩色顯示包括真彩色(每像素15、16和32位)和調(diào)色板(每像素1, 2, 4 和 8位)兩種模式。在彩色顯示模式下,所有的顏色用RGB格式給出,系統(tǒng)再將它轉(zhuǎn)換成與之最相似的可顯示顏色,而在單色模式下中則是轉(zhuǎn)換成不同的灰度級(jí)。Microwindows支持窗口覆蓋和子窗口概念、完全的窗口和客戶區(qū)剪切、比例和固定字體,還提供了字體和位圖文件處理工具。系統(tǒng)使用了優(yōu)化的繪制函數(shù),這樣當(dāng)用戶在移動(dòng)窗口時(shí)可以提供更好的響應(yīng)。內(nèi)存圖形繪制和移動(dòng)的實(shí)現(xiàn)使得屏幕畫圖顯得很平滑,這點(diǎn)特別在顯示動(dòng)畫、多邊形繪制、任意區(qū)域填充、剪切時(shí)有用。
盡管Microwindows完全支持Linux,但是它內(nèi)部的可移植結(jié)構(gòu)是基于一個(gè)相對(duì)簡(jiǎn)單的屏幕設(shè)備接口,可在許多不同的RTOS和裸機(jī)上運(yùn)行。這種特性的優(yōu)點(diǎn)突出體現(xiàn)在用戶設(shè)計(jì)的圖形程序不需重寫就可以被不同的工程共享,甚至可以運(yùn)行在不同RTOS的不同對(duì)象上。
Microwindows系統(tǒng)以圖形方式支持在主機(jī)平臺(tái)上的仿真目標(biāo)平臺(tái)。這樣,為L(zhǎng)inux設(shè)計(jì)的Microwindows應(yīng)用程序就可以在臺(tái)式機(jī)上進(jìn)行編寫和開發(fā)而不用進(jìn)行交叉編譯就可測(cè)試和運(yùn)行,并且直接在目標(biāo)平臺(tái)上運(yùn)行。臺(tái)式主機(jī)上運(yùn)行的目標(biāo)應(yīng)用程序在X window中顯示,這一點(diǎn)通過由Microwindows提供的Xwindow屏幕驅(qū)動(dòng)來完成,而不是通過幀緩存驅(qū)動(dòng)。該驅(qū)動(dòng)可以在像素位素和顏色深淺方面準(zhǔn)確的模擬目標(biāo)平臺(tái)上的顯示器,這樣即使桌面系統(tǒng)是24位顏色,它也可以預(yù)覽顯示2bpp灰度級(jí)的目標(biāo)應(yīng)用程序。
Microwindows采用分層設(shè)計(jì)方法。在最底層,屏幕,鼠標(biāo)/觸摸屏以及鍵盤驅(qū)動(dòng)程序提供了對(duì)物理設(shè)備訪問的能力。在中間層,實(shí)現(xiàn)了一個(gè)可移植的圖形引擎,支持行繪制,區(qū)域填充,剪切以及顏色模型等。在上層,實(shí)現(xiàn)多種API以適應(yīng)不同的應(yīng)用環(huán)境。
兩種API:Win32和Nano-X
Microwindows中使用兩種流行的圖形編程接口:MicrosoftWindows Win32/WinCE圖形顯示接口(GDI)和Xlib-like接口。前者應(yīng)用于所有的WindowsCE和Win32應(yīng)用程序,后者就象Nano-X,應(yīng)用于所有LinuxX插件集的最底層。這樣做可以讓大量的Windows程序員開發(fā)圖形應(yīng)用程序,類似地也可以讓Linux圖形程序員用X接口開發(fā)圖形應(yīng)用程序。
Nano-X程序設(shè)計(jì)
本文中將用Nano-XAPI設(shè)計(jì)一個(gè)應(yīng)用程序,并且討論底層Nano-X程序的設(shè)計(jì)問題。Nano-X允許應(yīng)用程序使用client/server網(wǎng)絡(luò)協(xié)議或本地UNIX的主域接口。這樣可以讓幾個(gè)應(yīng)用程序在嵌入式設(shè)備或遠(yuǎn)程主機(jī)上運(yùn)行而連接到Microwindows的服務(wù)器上顯示,這些特點(diǎn)使得Nano-X的操作非常像X Windows系統(tǒng)。在底層和大部分有關(guān)創(chuàng)建、刪除窗口以及基本畫圖函數(shù)方面,Nano-XAPI和X的Xlib庫很相似。另外,由于Microwindows被設(shè)計(jì)得很小,很多選項(xiàng)可以用資源包中的配置文件來進(jìn)行設(shè)置。
下面的過程是建立一個(gè)Nano-X服務(wù)器的一個(gè)具體操作。
(1)初始化
Mcrowindows的資源包可以從http://microwindows.org下載。首先通過編譯為主機(jī)和嵌入式目標(biāo)平臺(tái)建立一個(gè)Nano-X的服務(wù)器。大多數(shù)的設(shè)置選項(xiàng)在配置文件中,所以在解壓縮該資源包后進(jìn)入microwin/src目錄里編輯配置文件。下面是一些最重要的ARCH選項(xiàng):
ARCH=LINUX-NATIVE ARCH=LINUX-ARM ARCH=LINUX-MIPS ARCH=LINUX-POWERPC
為L(zhǎng)INUX-NATIVE設(shè)置ARCH選項(xiàng)的目的是通知系統(tǒng)為當(dāng)前運(yùn)行的主機(jī)的Linux系統(tǒng)生成程序,而為其他選項(xiàng)設(shè)置ARCH則是要給一個(gè)RISC目標(biāo)平臺(tái)進(jìn)行交叉編譯。Microwindows中使用Arch.rules文件為每一個(gè)選項(xiàng)確定一個(gè)具體的設(shè)置。
下面的設(shè)置項(xiàng)用于提供Nano-X 服務(wù)器的圖像支持:
HAVE_BMP_SUPPORT=Y HAVE_GIF_SUPPORT=Y HAVE_JPEG_SUPPORT=Y
設(shè)置JPEG圖像選項(xiàng)時(shí)必須給出外部jpeg解壓縮庫的位置,例如LIBJPEG=/usr/lib/libjpeg.a。大部分系統(tǒng)都提供了解壓庫,也可從Microwindows網(wǎng)站上下載。另外一個(gè)重要設(shè)置項(xiàng)為選擇是否提供大小可變字體支持,缺省項(xiàng)是在drivers/genfont.c中提供固定大小的位圖字體。如想顯示更大的字體,例如運(yùn)行一個(gè)嵌入式瀏覽器,則可加入對(duì)TrueType 或 Adobe Type1字體的支持。當(dāng)選項(xiàng)確定以后,就可以根據(jù)顯示的需要指定字體文件和像素點(diǎn)的大小,相應(yīng)Microwindows會(huì)根據(jù)外部字體文件來生成大小適當(dāng)?shù)淖煮w。最新的版本還可支持外部中文字體,其中所有的字體可用8位ASCII 碼、Unicode-16或UTF-8確定。其中UTF-8是Unicode的字節(jié)流編碼方案。
有關(guān)字符支持的選項(xiàng)如下:
HAVE_FREETYPE_SUPPORT=Y HAVE_T1LIB_SUPPORT=Y HAVE_HZK_SUPPORT=Y
FreeType 和T1lib外部庫分別用于支持TrueType 和 Adobe Type 1字體。這些庫必須預(yù)先編譯并且在配置文件中應(yīng)指定其位置。Microwindows的網(wǎng)站上提供的所有庫函數(shù)的下載。
(2)配置輸出顯示設(shè)備
由于Microwindows可在幀緩存系統(tǒng)和X Windows下運(yùn)行,每一種顯示驅(qū)動(dòng)需要確定不同的設(shè)置。如果已經(jīng)在Linux桌面上運(yùn)行了X ,最好首先用X屏幕驅(qū)動(dòng)建立系統(tǒng),然后再為嵌入式設(shè)備生成一個(gè)幀緩存。下列選項(xiàng)用以配置X屏幕驅(qū)動(dòng):
X11=Y SCREEN_WIDTH=640 SCREEN_HEIGHT=480 SCREEN_PIXTYPE=MWPF_TRUECOLOR0888
Microwindows通過這些選項(xiàng)在X桌面上生成一個(gè)640x480的虛窗口,采用了8位色彩模式(紅、綠、蘭各用8位表示)輸出。通過改變?cè)O(shè)置,可以在自己的桌面上控制目標(biāo)嵌入式設(shè)備的仿真。例如仿真一個(gè)每像素16位的顯示,SCREEN_PIXTYPE=MWPF_TRUECOLOR565。其中MWPF常數(shù)在src/include/mwtypes.h 頭文件中有詳盡的解釋。
由于必須確定Linux系統(tǒng)內(nèi)核支持幀緩存,因此設(shè)置幀緩存顯示比較復(fù)雜。其設(shè)置如下:
X11=N FRAMEBUFFER=Y FBVGA=Y VTSWITCH=Y PORTRAIT_MODE=N
FBVGA選項(xiàng)引入了對(duì)16色VGA平面模式屏幕驅(qū)動(dòng)的支持,但是該選項(xiàng)不可用于嵌入式系統(tǒng)。VTSWITCH選項(xiàng)允許Microwindows在幀緩存控制器上運(yùn)行,按下ALT鍵可打開另一個(gè)虛擬控制器。一些嵌入式系統(tǒng)要求該選項(xiàng)關(guān)閉。PORTRAIT_MODE選項(xiàng)利用 L/R鍵來指定系統(tǒng)偏向于左/右運(yùn)行,這一點(diǎn)和康柏公司出品的iPAQ PDA非常類似。
(3)Linux內(nèi)核幀緩存支持
如果在運(yùn)行Nano-X 服務(wù)器時(shí)顯示“Can’t open/dev/fb0”,說明沒有打開幀緩存或是系統(tǒng)內(nèi)核沒有引入幀緩存驅(qū)動(dòng)。最簡(jiǎn)單的識(shí)別方式是當(dāng)啟動(dòng)系統(tǒng)時(shí)是否看見一個(gè)企鵝圖標(biāo),如果沒有圖標(biāo)則確認(rèn)下列選項(xiàng)是否在/usr/src/linux/.config文件中:
CONFIG_FB=y CONFIG_FB_VGA16=y CONFIG_FBCON_VGA=y CONFIG_FBCON_CFB4=y CONFIG_FBCON_CFB8=y
如果系統(tǒng)支持圖形卡而不是標(biāo)準(zhǔn)的老式VGA,可以不用CONFIG_FB_VGA16選項(xiàng)。在重建內(nèi)核之前,需要備份舊的內(nèi)核,并且在lilo.conf文件中寫明備份位置。啟用幀緩存是大部分嵌入式系統(tǒng)的標(biāo)準(zhǔn)設(shè)置。
最后一項(xiàng)重要配置是為Microwindows指定鼠標(biāo)或觸摸屏輸入的驅(qū)動(dòng)程序。目前Microwindows上的鼠標(biāo)是通過GPM工具或直接使用串口。指令GPMMOUSE=Y是選擇GPM支持,設(shè)置之后運(yùn)行g(shù)pm工具,例如‘gpm–R –t ps2’(支持 PS/2 鼠標(biāo));指令SERMOUSE=Y 是選擇串口,同時(shí)還要在src/drivers/mou_ser.c中設(shè)置MOUSE_TYPE和MOUSE_PORT兩個(gè)環(huán)境變量。
(4)創(chuàng)建一個(gè)完整的演示系統(tǒng)
一旦在配置文件中設(shè)置好選項(xiàng)后,只要用戶不再改動(dòng),參數(shù)就保持不變。同時(shí)在src目錄中還有很多針對(duì)不同平臺(tái)的樣本配置文件。要?jiǎng)?chuàng)建一個(gè) Nano-X服務(wù)器并且運(yùn)行演示程序,首先進(jìn)入microwin/src目錄,然后鍵入“make”。所有的程序在microwin/src/bin目錄中生成,客戶鏈接庫也放在microwin/src/lib目錄下。要運(yùn)行演示程序,首先運(yùn)行Nano-X 服務(wù)器(在bin/nano-X下),然后再運(yùn)行應(yīng)用程序。
bin/nano-X & sleep 1; bin/world
在運(yùn)行demonstration world plotting程序之前運(yùn)行休眠命令以便服務(wù)器有一段時(shí)間來進(jìn)行初始化。創(chuàng)建一個(gè)簡(jiǎn)單的Nano-X應(yīng)用程序。目的:繪制一個(gè)帶蘭邊的白色方塊。源代碼如下:
filename :sample.c #define MWINCLUDECOLORS #include #include “nano-X.h” int main(int ac,char **av) { GR_WINDOW_ID w; GR_EVENT event; if (GrOpen() < 0) { printf(“Can’t open graphics\n”); exit(1); } w = GrNewWindow(GR_ROOT_WINDOW_ID, 20, 20, 100, 60, 4, WHITE, BLUE); GrMapWindow(w); for (;;) { GrGetNextEvent(&event); } GrClose(); return 0; }
在配置和檢測(cè)了Microwindows初始安裝程序以后,用“make install”指令來創(chuàng)建Nano-X 服務(wù)器、客戶庫和頭文件,然后鍵入下述字符編譯、鏈接和運(yùn)行示例程序:
gcc sample.c –o sample –lnano-X nano-X & sleep 1; sample
鍵入escape將退出服務(wù)器。
GrOpen()函數(shù)用于打開一個(gè)與正在運(yùn)行中的Nano-X服務(wù)器的連接,如果服務(wù)器沒有運(yùn)行,則返回-1值,應(yīng)用程序此時(shí)顯示錯(cuò)誤信息并退出。GrNewWindow函數(shù)在屏幕(20,20)的位置上創(chuàng)建一個(gè)100x60像素的窗口。它的邊界大小為4像素寬,蘭邊白底。然后調(diào)用GrMapWindow函數(shù)將剛剛創(chuàng)建的窗口在屏幕上顯示出來。這是因?yàn)橛袝r(shí)生成一組窗口很方便,但是要根據(jù)用戶指令在屏幕上顯示和移動(dòng)。在屏幕顯示窗口以后,程序進(jìn)入“event loop”狀態(tài),等待下一個(gè)鼠標(biāo)或鍵盤事件。
Expose event
更為復(fù)雜的Nano-X應(yīng)用程序基本上遵從上述同樣的邏輯結(jié)構(gòu)。首先生成窗口,接著顯示出來,然后程序進(jìn)入“eventloop”等待用戶發(fā)出指令。在該例中并沒有真正寫出明確的代碼在窗口上畫出東西。在實(shí)現(xiàn)這一點(diǎn)之前,首先應(yīng)當(dāng)理解關(guān)于Exposeevent的概念。Nano-XAPI提供一套完整的在屏幕上劃線、寫字、畫圓和顯示圖像的函數(shù)。當(dāng)一個(gè)窗口被遮住時(shí),Microwindows剪輯該窗口圖畫并保存下來,當(dāng)被遮掩部分再次需顯示時(shí),可以重新刷新以顯示以前的內(nèi)容。刷新發(fā)生時(shí),服務(wù)器首先向應(yīng)用程序發(fā)送一個(gè)Exposeevent,要求重新繪制窗口中的內(nèi)容。Microwindows在首次顯示窗口后就發(fā)出一個(gè)exposeevent指令,這樣重新繪制時(shí)使用的代碼和原來顯示時(shí)所用的代碼完全一樣,所以可以實(shí)現(xiàn)在原先位置上顯示同樣的內(nèi)容。下例是用該機(jī)制顯示一些文字,并在窗口移動(dòng)后重新顯示出來(sample2.c).
#define MWINCLUDECOLORS #include #include “nano-X.h” int main(int ac,char **av) { GR_WINDOW_ID w; GR_GC_ID gc; GR_EVENT event; if (GrOpen() < 0) { printf(“Can’t open graphics\n”); exit(1); } w = GrNewWindow(GR_ROOT_WINDOW_ID, 20, 20, 100, 60,4, WHITE, BLUE); gc = GrNewGC(); GrSetGCForeground(gc, BLACK); GrSetGCUseBackground(gc, GR_FALSE); GrSelectEvents(w, GR_EVENT_MASK_EXPOSURE); GrMapWindow(w); for (;;) { GrGetNextEvent(&event); switch (event.type) { case GR_EVENT_TYPE_EXPOSURE: GrText(w, gc, 10, 30, “Hello World”, -1, GR_TFASCII); break; } GrClose(); return 0; }
為了檢測(cè)expose event代碼,要運(yùn)行帶有NanoWM窗口管理器的Nano-X,這樣就可以移動(dòng)窗口了。命令如下:
bin/nano-X & sleep 1; bin/nanowm & sleep 1; sample2
在上例中用GrSelectEvents函數(shù)發(fā)送GR_EVENT_TYPE_EXPOSURE事件到客戶(client)程序中。為了保持client/server之間的通信,server只向每個(gè)client窗口發(fā)送選擇過的事件。程序中只有一句處理“HelloWorld”顯示文本,該句在expose event例程中。GrMapWindow調(diào)用后立即產(chǎn)生一個(gè)exposeevent,這樣即使窗口實(shí)際上并沒有真正移動(dòng)文字還是會(huì)被顯示出來。
Graphics contexts
當(dāng)繪制類似于線條或文字的圖形時(shí),所調(diào)用的每個(gè)畫圖函數(shù)都定義了一些可以影響操作的參數(shù)。每個(gè)調(diào)用除了一些類似于線條起始點(diǎn)這樣的最基本信息以外,還由系統(tǒng)確定一些其它信息。前景色、背景色、與或畫圖模式以及一些其它參數(shù)保存在一個(gè)graphics context結(jié)構(gòu)中。上例中g(shù)raphics context用GrNewGC生成。該函數(shù)按標(biāo)準(zhǔn)設(shè)置生成graphicscontext,然后調(diào)用GrSetGCForeground設(shè)置前景文字顏色。在expose event處理過程中,graphicscontext通過window id設(shè)置文本繪制參數(shù)。
畫圖函數(shù)
上面已經(jīng)介紹了生成程序、窗口和graphics context的基本知識(shí),下面介紹Microwindows圖形庫中提供的其它函數(shù)。
GrClearWindow 清除窗口(Clear a window to it’s background color)
GrPoint 畫點(diǎn)(Draw a single point)
GrLine 畫線(Draw a line)
GrRect 畫矩形(Draw a rectangle outline)
GrFillRect 填充矩形(Draw a filled rectangle)
GrEllipse 畫圓/橢圓(Draw an ellipse or circle outline)
GrFillEllipse 填充圓/橢圓(Draw a filled ellipse or circle)
GrArc 畫弧形(Draw an arc outline or pie wedge)
GrArcAngle 畫弧形,指定浮點(diǎn)及角度(Like GrArc, but uses floating point and angles)
GrPoly 畫多邊形(Draw a polygon outline)
GrFillPoly 填充多邊形(Draw a filled polygon)
GrBitmap 繪制位圖( Draw a bitmap image)
GrDrawImageFromFile 繪制存盤的BMP、GIF、JPEG圖形(Draw a BMP, GIF or JPEG file from disk)
GrDrawImageToFit 繪制cache中的圖形,并適當(dāng)調(diào)整其大?。―raw a cached image and stretch to fit)
GrArea 繪制內(nèi)存隊(duì)列中像素點(diǎn)(Draw from a memory array of pixels)
GrCopyArea 將某一窗口中的矩形區(qū)域復(fù)制到另一窗口(Copy a rectangular area fromonewindow to another)
Microwindows也支持一種從來不在屏幕上顯示的窗口,即像素映射(pixmap)。像素映射窗口有時(shí)也稱作虛窗口(offscreen),虛窗口不能在屏幕上顯示出來,但是可以使用GrCopyArea函數(shù)復(fù)制到別的窗口。有時(shí)在exposeevents期間,CPU太忙而無法保存顯示窗口的內(nèi)容,普通窗口在被遮掩時(shí)又從不保存它們的內(nèi)容,這時(shí)就可以使用像素映射。用GrNewPixmap函數(shù)可以生成一個(gè)像素映射。
希望上面的介紹可以幫助你理解在嵌入式Linux里,一個(gè)小型系統(tǒng)如何運(yùn)行復(fù)雜的應(yīng)用程序。Microwindows網(wǎng)站上還有更多的內(nèi)容。