Qt/Embedded在嵌入式Linux系統中的應用(ARM)
Qt/Embedded在嵌入式Linux系統中的應用
摘要:分析和討論Qt/Embedded的主流版本3.x系列的底層實現技術;結合2.x版本系列和3.x版本系列,在兩種不同的硬體平臺(Intel PXA255開發系統與筆者自行設計的Motorola MC9328 MX1開發系統)上的移植過程,討論Qt/Embedded的底層裝置介面與應用移植技術。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
關鍵詞:Qt/嵌入式Linux framebuffer 驅動介面
引言
隨著嵌入式Linux
Qt/Embedded是著名的Qt庫開發商Trolltech公司開發的面向嵌入式系統的Qt版本,開發人員多為KDE專案的核心開發人員。許多基於Qt的X Window程式可以非常方便地移植到Qt/Embedded上,與X11版本的Qt在最大程度上介面相容,延續了在
1 Qt/Embedded的實現技術基礎分析
橫向來看,由於釋出的版權問題,Qt/Embedded採用兩種方式進行釋出:在GPL協議下發布的free版與專門針對商業應用的commercial版本。二者除了釋出方式外,在原始碼上沒有任何區別。縱向看來,當前主流的版本為Qtopia的2.x系列與最新的3.0x系列。其中2.0版本系統較多地應用於採用Qtopia作為高檔PDA主介面的應用中;3.x版本系列則應用於功能相對單一,但需要高階GUI圖形支援的場合,如Volvo公司的遠端公交資訊系統。圖1為Qt/Embedded的實現結構。
3.x版本系列的Qt/Embedded相對於2.x版本系統增加了許多新的模組,如SQL資料庫查詢模組等。幾乎所有2.x版本中原有的類庫,在3.x版本中都得到極大程度的增強。這就極大地縮短了應用軟體的開發時間,擴大了Qt/Embedded的應用範圍。
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
在程式碼設計上,Qt/Embedded巧妙地利用了C++獨有的機制,如繼承、多型、模板等,具體實現非常靈活。但其底層程式碼由於追求與多種系統、多種硬體的相容,程式碼補丁較多,風格稍顯混亂。
1.1 Qt/Embedded的圖形引擎實現基礎
Qt/Embedded的底層圖形引擎基於framebuffer。Framebuffer是在Linux核心架構版本2.2以後推出的標準顯示裝置驅動介面。採用mmap系統呼叫,可以將framebuffer的顯示快取對映為可連續訪問的一段記憶體儲針。由於目前比較高階的ARM體系的嵌入式CPU中大多集成了LCD控制模組,LCD控制模組一般採用雙DMA控制器組成的專用DMA通道。其中一個DMA可以自動從一個數據結構佇列中取出並裝入新的引數,直到整個佇列中的DMA操作都已完成為止。另外一個DMA與畫面緩衝區相關,這部分由兩個DMA控制器交替執行,並每次都自動按照預定的規則改變引數。雖然使用了雙DMA,但這兩個DMA控制器的交替使用對於CPU來說是不可見的。CPU所獲得的只是由兩個DMA組成的一個“通道”而已。
Framebuffer驅動程式的實現分為兩個方面:一方面是對LCD及其相關部分的初始化,包括畫在緩衝區的建立和對DMA通道的設定;另外一方面是對畫面緩衝區的讀寫,具體到程式碼為read、write、lseek等系統呼叫介面。至於將畫面緩衝區的內容輸出到LCD顯示屏上,則由硬體自動完成。對於軟體來說是透明的。當對於DMA通道和畫面緩衝區設定完成後,DMA開始正常工作,並將緩衝區中的內容不斷髮送到LCD上。這個過程是基於DMA對於LCD的不斷重新整理的。基於該特性,framebuffer驅動程式必須將畫面緩衝區的儲存空間(物理空間)重新對映到一個不加高快取和寫快取的虛擬地址區間中,這樣能才保證應用程式通過mmap將該快取對映到使用者空間後,對於該畫面快取的寫操作能夠實時的體現在LCD上。
在Qt/Embedded中,Qscreen類為抽象出的底層顯示裝置基類,其中聲明瞭對於顯示裝置的基本描述和操作方式,如開啟、關閉、獲得顯示能力、建立GFX操作物件等。另外一個重要的基類是QGfx類。該類抽象出對於顯示裝置的具體操作介面(圖形裝置環境),如選擇畫刷、畫線、畫矩形、alpha操作等。以上兩個基類是Qt/Embedded圖形引擎的底層抽象。其中所有具體函式基本都是虛擬函式,Qt/Embedded對於具體的顯示裝置,如Linux的framebuffer、Qt Virtual Framebuffer做的抽象介面類全都由此繼承並重載基類中的虛擬函式實現。圖2為Qt/Embedded中底層圖形引擎實現結構。
在圖2中,對於基本的framebuffer裝置,Qt/Embedded用QlinuxFbScreen來處理。針對具體顯示硬體(如Mach卡、Voodoo卡)的加速特性,Qt/Embedded從QlinuxFbScreen和圖形裝置環境模板類QgfxRaster繼承出相應子類,並針對相應硬體過載相關虛擬函式。
Qt/Embedded在體系上為C/S結構,任何一個Qt/Embedded程式都可以作為系統中唯一的一個GUI Server存在。當應用程式首次以系統GUI Server的方式載入時,將建立QWSServer實體。此時呼叫QWSServer::openDisplay()函式建立窗體,在QWSServer::openDisplay()中對QWSDisplay::Data中的init()加以呼叫;根據QgfxDriverFactory實體中的定義(QLinuxFbScreen)設定關鍵的Qscreen指標qt_screen並呼叫connect()開啟顯示裝置(dev/fb0)。在QWSServer中所有對於顯示裝置的呼叫都由qt_screen發起。至此完成了Qt/Embedded中QWSServer的圖形發生引擎的建立。當系統中建立好GUI Server後,其它需要執行的Qt/Embedded程式在載入後採用共享記憶體及有名管道的程序通訊方式,以同步訪問模式獲得對共享資源framebuffer裝置的訪問權。
1.2 Qt/Embedded的事件驅動基礎
Qt/Embedded中與使用者輸入事件相關的訊號,是建立在對底層輸入裝置的介面呼叫之上的。Qt/Embedded中的輸入裝置,分為滑鼠類與鍵盤類。以3.x版本系列為例,其中滑鼠裝置的抽象基類為QWSMouse Handler,從該類又重新派生出一些具體的滑鼠類裝置的實現類。該版本系列的Qt/Embedded中,滑鼠類裝置的派生結構如圖3所示。
與圖形發生引擎載入方式類似的,在系統載入構造QWSServer時,呼叫QWSServer::openMouse與QWSServer::openKeyboard函式。這兩個函式分別呼叫QmouseDriverFactory::create()與QkbdDriverFactory::create()函式。這時會根據Linux系統的環境變數QWS_MOUSE_PROTO與QWS_KEYBOARD獲得滑鼠類裝置和鍵盤類裝置的裝置型別和裝置節點。開啟相應裝置並返回相應裝置的基類控制代碼指標給系統,系統通過將該基類指令強制轉換為對應的具體子類裝置指標,獲得對具體滑鼠類裝置和鍵盤類裝置的呼叫操作。
值得注意的是,雖然幾乎滑鼠類裝置的功能上基本一致,但由於觸控式螢幕和滑鼠底層介面並不一樣,會造成對上層介面的不一致。舉例來講,從滑鼠驅動介面中幾乎不會得到絕對位置資訊,一般只會讀到相對移動量。另外,滑鼠的移動速度也需要考慮在內,而觸控式螢幕介面則幾乎是清一色的絕對位置資訊和壓力資訊。針對此類差別,Qt/Embedded將同一類裝置的介面部分也給予區別和抽象,具體實現在QmouseDriverInterface類中。鍵盤類裝置也存在類似問題,同樣引入了QkbdDriver Inteface來解決。具體實現此處暫不多述。
2 Qt/Embedded的移植與應用
針對Qt/Embedded的實現特點,移植該嵌入式GUI系統一般分為以下幾個步驟:
①設計硬體開發平臺,並移植Linux作業系統;
②採用靜態連結進Linux核心的方式,根據該平臺顯示裝置的顯示能力,開發framebuffer驅動程式;
③開發針對該平臺的滑鼠類裝置驅動程式,一般為觸控式螢幕或USB滑鼠;
④開發針對該平臺的鍵盤類裝置驅動程式,一般為板載按鈕或USB鍵盤(該部分可選);
⑤根據framebuffer驅動程式介面,選擇並修改Qt/Embedded中的QlinuxFbScreen和QgfxRaster類;
⑥根據滑鼠類裝置驅動程式,實現該類裝置在Qt/Embedded中的操作介面;
⑦根據鍵盤類裝置驅動程式,實現該類裝置在Qt/Embedded中的操作介面(該部分可選);
⑧根據需要選擇Qt/Embedded的配置選項,交叉編譯Qt/Embedded的動態庫;
⑨交叉編譯Qt/Embedded中的Example測試程式,在目標平臺上執行測試。
Framebuffer裝置驅動程式提供出的介面是標準的,除了注意endian問題外,配置Qt/Embedded時選擇相應的色彩深度支援即可,因此該部分的移植難點就在於framebuffer驅動程式的實現。Qt/Embedded部分的QWSServer開啟/dev/中的framebuffer裝置後讀出相應的顯示能力(螢幕尺寸、顯示色彩深度),模板QgfxRaster將根據色彩深度在使用者空間裝置創建出與顯示快取同樣大小的緩衝作為雙緩衝,並採用正確方式進行顯示。
2.1 在PXA255平臺上移植和應用
在筆者參與設計的某Smart-Phone開發平臺中,GUI系統實現方案採用了Qt/Embedded 2.3.7和Qtopia 1.7.0(基於Qt/Embedded 2.x系列的手持套件),硬體平臺採用了基於Intel XScale PXA255處理器的嵌入式開發系統。該開發系統採用640×480解析度的TFT LCD和PXA255內部LCD控制模組作為顯示裝置,ADS7846N作為外部電阻式觸控式螢幕控制器;另外,採用了五方向按鍵作為板載鍵盤。由於該系統採用了ISP1161作為USB Host控制器,較好地支援了USB介面的鍵盤和滑鼠,作業系統為ARM Linux 2.4.19。參考Linux 2.4.19核心目錄drivers/input部分,可以按照標準核心中input device介面設計實現觸控式螢幕和鍵盤,在實現了基於ISP1161的EHCI驅動程式後,移植標準的USB