引言
嵌入式GUI為嵌入式系統提供了一種應用於特殊場合的人們交互接口。嵌入式GUI要求簡單、直觀、可靠、占用資源小且反應快速,以適應系統硬件資源有限的條件。另外,由於嵌入式系統硬件本身的特殊性,嵌入式GUI應具備高度可移植性與可裁減性,以適應不同的硬件條件和使用需求。總體來講,嵌入式GUI具備以下特點:
*體積小;
*運行時耗用系統資源小;
*上層接口與硬件無關,高度可移植;
*高可靠性;
*在某些應用場合應具備實時性。
1、基於嵌入式Linux的GUI系統底層實現基礎
一個能夠移植到多種硬件平台上的嵌入式GUI系統,應用至少抽象出兩類設備:基於圖形顯示設備(如VGA卡)的圖形抽象層GAL(Graphic Abstract Layer),基於輸入設備(如鍵盤,觸摸層等)的輸入抽象層IAL(Input Abstract Layer)。GAL層完成系統對具體的顯示硬件設備的操作,極大程度上隱蔽各種不同硬件的技術實現細節,為诮程序開發人員提供統一的圖形編程接口。IAL層則需要實現對於各類不同輸入設備的控制操作,提供統一的調用接口。GAL層與IAL層的設計概念,可以極大程序地提高嵌入式GUI的可移植性,如圖1所示。
目前應用於嵌入式Linux系統中比較成熟,功能也比較強大的GUI系統底層支持庫有SVGA lib、LibGGI、Xwindow、framebuffer等。
2、三種嵌入式GUI系統的分析與比較
2.1 Microwindows
Microwindows是一個典型的基於Server/Clinent體系結構的GUI系統,基本分為三層,如圖2所示。
最底層是面向圖形顯示和鍵盤、鼠標或觸摸屏的驅動程序;中間層提供底層硬件的抽象接口,並進行窗口管理;最高層分別提供兼容於X Window和ECMA APIW(Win32子集)的API。其中使用Nano-X接口的API與X接口兼容,但是該接口沒有提供窗口管理,如窗口移動和窗口剪切等高級功能,系統中需要首先啟動nano-X的Server程序nanoxserver和窗口管理程序nanowm。用戶程序連接nano-X的Server獲得自身的窗口繪制操作。使用ECMA APIW編寫的應用程序無需nanox-server和nanowm,可直接運行。
Microwindows提供了相對完善的圖形功能和一些高級的特性,如Alpha混合、三維支持和TrueType字體支持等。該系統為了提高運行速度,也改進了基於Socket套接字的X實現模式,采用了基於消息機制的Server/Client傳輸機制。Microwindows也有一些通用的窗口控件,但其圖形引擎存在許多問題,可以歸納如下:
*無任何硬件加速能力;
*圖形引擎中存在許多低效算法,如在圓弧圖函數的逐點判斷剪切的問題。
由於該項目缺乏一個強有力的核心代碼維護人員,2003年Microwindows推出版本0.90後,該項目的發展開始陷於停滯狀態。
2.2 MiniGUI
MiniGUI是由國內自由軟件開發人員設計開發的,目標是為基於Linux的實時嵌入式系統提供一個輕量級的圖形用戶界面支持系統。MiniGUI的體系架構如圖3所示。
MiniGUI分為最底層的GAL層和IAL層,向上為基於標准POSIX接口中pthread庫的Mini-thread架構和基於Server/Client的Mini-Lite架構。其中前者受限於thread模式對於整個系統的可靠性影響——進程中某個thread的意外錯誤可能導致整個進程的崩潰,該架構應用於系統功能較為單一的場合。Mini-Lite應用於多進程的應用場合,采用多進程運行方式設計的Server/Client架構能夠較好地解決各個進程之間的窗口管理、Z序剪切等問題。MiniGUI還有一種從Mini-Lite衍生出的standalone運行模式。與Lite架構不同的是,standalone模式一次只能以窗口最大化的方式顯示一個窗口。這在顯示屏尺寸較小的應用場合具有一定的應用意義。
MiniGUI的GAL層技術SVGA lib、LibGGI、基於framebuffer的native圖形引擎以及啞圖形引擎等,對於Trolltech公司的QVFB在X Window下也有較好的支持。IAL層則支持Linux標准控制台下的GPM鼠標服務、觸摸屏、標准鍵盤等。
MiniGUI下豐富的控件資源也是MiniGUI的特點之一。當前MiniGUI的最新版本是1.3.3。該版本的控件中已經添加了窗口皮膚、工具條等桌面GUI中的高級控件支持。 2.3 QT/Embedded
Qt/Embedded是著名的Qt庫開發商Trolltech公司開發的面向嵌入式系統的Qt版本。因為Qt是KDE等項目使用的GUI支持庫,許多基於Qt的X Window程序因此可以非常方便地移植到Qt/Embedded上。Qt/Embedded同樣是Server/Client結構。
Qt/Embedded延續了Qt在X上的強大功能,在底層摒棄了X lib,僅采用framebuffer作為底層圖形接口。同時,將外部輸入設備抽象為keyboard和mouse輸入事件,底層接口支持鍵盤、GPM鼠標、觸摸屏以及用戶自定義的設備等。
Qt/Embedded類庫完全采用C++封裝。豐富的控件資源和較好的可移植性是Qt/Embedded最為優秀的一方面。它的類庫接口完全兼容於同版本的Qt-X11,使用X下的開發工具可以直接開發基於Qt/Embedded的應用程序QUI界面。
與前兩種GUI系統不同的是,Qt/Embedded的底層圖形引擎只能采用framebuffer。這就注定了它是針對高端嵌入式圖形領域的應用而設計的。由於該庫的代碼追求面面俱到,以增加它對多種硬件設備的支持,造成了其底層代碼比較凌亂,各種補丁較多的問題。Qt/Embedded的結構也過於復雜臃腫,很難進行底層的擴充、定制和移植,尤其是用來實現signal/slot機制的moc文件。
Qt/Embedded當前的最新版本為3.3.2,能夠支持Trolltech的手持應用套件Qtopia的Qt/Embedded最高版本為2.3.8。Trolltech公司將於2004年末推出的Qt/Embedded 3為基礎的Qtopia 2應用套件。
3、三種嵌入式GUI的移植與中文化
在進行以上三種嵌入式GUI的研究和移植過程中,硬件平台采用自行設計的以Motorola MC9328 MX1為核心的開發系統。該系統采用CPU內部LCD控制器和320×240分辨率的16bpp TFT LCD作為顯示設備,使用I2C總線擴展出16按鍵的鍵盤,同時配置了9位A/D量化精度的電阻觸摸屏作為鼠標類輸入設備;同時移植了ARM Linux作為操作系統。以下分別討論這三種嵌入式GUI的底層移植和中文化技術。
移植以上三種嵌入式GUI系統,需要首先實現Linux內核中的framebuffer驅動。對應於開發系統為MC9328中的LCD控制器,該部分驅動程序必須以靜態方式編譯進內核,在系統啟動時由傳遞進內核的啟動參數激活該設備。I2C鍵盤的驅動程序和觸摸屏的驅動程序實現後,作為Linux內核模塊在使用時動態加載。
3.1 Microwindows的移植
Microwindows驅動層相應的源碼目錄為src/drivers/。其中以scr*開頭的源碼是針對顯示設備的驅動接口,以mou*開頭的源碼文件為鼠標設備(包括觸摸屏)的驅動接口,以kbd*開頭的源碼文件針對鍵盤設備的驅動接口。移植過程中需要實現自己的設備驅動接口提供給Microwindows使用,就必須按照指定的接口格式編寫相應的scr、mou、kbd的底層支持。這種方式實現簡單,條理也很清晰。
顯示設備驅動接口:Microwindows的圖形發生引擎支持framebuffer,修改src/中的config文件指定使用framebuffer作為底層圖形支持引擎;但需要注意嵌入式Linux的framebuffer較少支持控制台字符模式,需要修改Microwindows中對framebuffer的操作部分以關閉顯示模式的轉換。
在應用程序開發移植中需要注意的是:使用ECMAAPIW接口設計的程序無需nano-X的Server程序和nanowm,如圖2所示。系統中可以直接啟動使用該接口編寫的用戶程序;但需要注意的是,一個系統中如同時存在使用兩種不同的API接口編寫的進程,會造成nano-X的Server與ECMA APIW的進程對系統硬件資源的使用競爭,雙方的程序將無法正常顯示或響應應用戶輸入。
在為Microwindows增加中文顯示的支持時,主要工作包括兩個部分。一部分是系統字體的中文支持。此處使用等寬光柵字體,主要負責窗口標題和內置控件的中文繪制,將字體編譯進Microwindows內核中,光柵信息作為一維數組,顯示時按照字符偏移量從該數組中調出相應的光柵信息顯示即可。除此之外,當程序調用CreateFont時,需要在內部實現為打開文件系統中的字體文件。通過修改src/engine/devfont.c中的GdCreateFont部分,添加相應的hzk(漢字庫)支持,便可以實現在CreateFont時創建出一個支持GB2312字符集的邏輯字體,並使用外部字體進行顯示。在應用程序設計時,如果沒有調用SelectObjectu將外部字體選入,中文顯示時將默認使用系統字體。
3.2 MiniGUI
由於MiniGUI較好地將硬件設備抽象為GAL層和IAL層,移植時只需要針對自身的硬件特點按照GAL層調用接口和IAL層調用接口來做內部實現即可。圖4為MiniGUI的GAL層結構示意,IAL層結構類似。
實現了framebuffer的Linux驅動後,配置MiniGUI選擇Native的GAL引擎,便可以使用framebuffer作為MiniGUI的圖形發生引擎。
MiniGUI的IAL層將輸入設備的輸入事件最終映射為GUI系統API層的消息事件。IAL層默認處理兩種設備的輸入操作:鍵盤設備和鼠標設備。鍵盤設備向上層提供不同的按鍵輸入信息,鼠標設備提供點擊、抬起和落筆坐標等的信息。在實現MiniGUI與輸入設備驅動的接口時,采用Select的方式獲得輸入設備的動作,並轉換為消息隊列中的消息。消息參數按照Win32接口定義為點擊鍵編號或鼠標當前的坐標(其中觸摸屏事件與鼠標事件類似)。通過編寫針對硬件開發系統的IAL支持代碼,實現了IAL層的移植。
MiniGUI中多字體和字符集支持是通過設備上下文(DC)的邏輯字體(LOGFONT)實現的,創建邏輯字體時指定相應的字符集,其內部實現為對於所需顯示字符的所屬字符集的識別處理,最終調用相應字符集的處理函數族。應用程序在啟動時,可切換系統字符集,如GB2312、BIG5、EUCKR、UJIS。MiniGUI的這種字符集支持方式不同於采用UNICODE的解決方案。在節省系統資源的意義上講,這種實現更加適合於嵌入式系統應用,是MiniGUI的一大創新點。MiniGUI同時支持包括ttf、bdf、type 1、vbf等多種字體格式,可以根據需要配置MiniGUI來支持相應字體的顯示。
3.3 Qt/Embedded的移植
Qt/Embedded的底層圖形引擎完全依賴於framebuffer,因此在移植時需考慮目標平台的Linux內核版本和framebuffer驅動程序的實現情況,包括分辨率和顏色深度等在內的信息。當前嵌入式CPU大多內部集成LCD控制器,並支持多種配置方式。除少數CPU低色彩配置時的endian問題外,Qt/Embedded能夠較好地根據系統已有的framebuffer驅動接口構建上層的圖形引擎。
Qt/Embedded圖形發生引擎中的圖形繪制操作函數都是由源泉碼目錄src/kernel/中的src/kernel/qgfxreaster_qws.cpp中所定義的QgfxRasterBase類發起聲明的。對於設備更加底層的抽象描述,則在src/kernel目錄中的qgfx_qws.cpp中的Qscreen類中給予相應定義。這些是對framebuffer設備直接操作的基礎,包括點、線、區域填充、alpha混合、屏幕繪制等函數均在其中定義實現。在framebuffer驅動程序調試通過後,配置Qt/Embedded的編譯選項,可以保證Qt/Embedded的圖形引擎正常工作。Qt/Embedded中的輸入設備,同樣分為鼠標類與鍵盤類。其中鼠標設備在源泉碼目錄中的src/kernel/qwsmouse_qws.cpp中實現,從該類又重新派生出一些特殊鼠標類設備的實現類,其派生結構如圖5所示。
根據具體的硬件驅動程序實現的接口,可以實現類似的接口函數。
Qt/Embedded中對於鍵盤響應的實際函數位於src/kernel/qkeyboard_qws.cpp中,在qkeyboard_qws.h中,定義了鍵盤類設備接口的基類QWSKeyboardHandler。具體的鍵盤硬件接口依然要建立在鍵盤驅動程序基礎上,移植時需要根據鍵盤驅動程序從該類派生出實現類,實現鍵盤事件處理函數processKeyEvent()即可。
Qt/Embedded內部對於字符集的處理采用了UNICODE編碼標准。Qt/Embedded內部對於字符集的處理采用了UNICODE編碼標准。Qt/Embedded同時支持兩種對於其它編碼標准(如GB2312和GBK)的支持方式:靜態編譯和動態插件裝載。通過配置config.h文件添加相應的編碼支持宏定義,可以獲得其它編碼標准向UNICODE的轉換支持,從而在Qfont類中得以轉換與顯示。由於UNICODE涵蓋了中文部分,Qt/Embedded對中文支持也非常好。
Qt/Embedded能夠支持TTF、PFA/PFB、BDF 和QPF字體格式。由於自身采用UNICODE編碼方式對字符進行處理,在一定程序上導致了能夠使用的字體文件體積的增大。為了解決這一問題,Qt/Embedded采用了QPF格式,使用makeqpf等工具可以將TTF等格式的字體轉換至QPF格式。圖6為筆者在自行設計的MC9328系統上移植Qt/Embedded和Qtopia套件後,增加中文支持後的顯示截圖。Qt/Embedded版本為2.3.7,Qtopia版本為1.7.0。
4、結論
綜上所述,一個具備良好移植性的嵌入式GUI系統,其底層接口應該在很大程度上隱藏具體硬件的實現細節,抽象出GAL與IAL層。對於字符集的支持,也可以從MiniGUI的字符集支持方式和Qt/Embedded的UNICODE支持方式上獲得啟發。
4、結論
綜上所述,一個具備良好移植性的嵌入式GUI系統,其底層接口應該在很大程度上隱藏具體硬件的實現細節,抽象出GAL與IAL層。對於字符集的支持,也可以從MiniGUI的字符集支持方式和Qt/Embedded的UNICODE支持方式上獲得啟發。