實(shí)現(xiàn)針對(duì)觸摸屏的輸入引擎移植解析方案
1.引言
嵌入式GUI指在嵌入式系統(tǒng)中為特定的硬件設(shè)備或者環(huán)境而設(shè)計(jì)的圖形用戶界面系統(tǒng)。它極大地方便了非專業(yè)用戶的使用,人們不再需要死記硬背大量的命令,而可以通過(guò)窗口、菜單方便地操作。在實(shí)際應(yīng)用中,嵌入式GUI應(yīng)滿足輕型、占用資源少、高性能、高可靠性、可配置等基本要求。
Linux作為一種可裁減的操作系統(tǒng),兼容多種主流CPU且支持所有的文件系統(tǒng)和網(wǎng)絡(luò)服務(wù),并具備源代碼公開(kāi)、易于定制、穩(wěn)定、功能強(qiáng)大和易開(kāi)發(fā)等優(yōu)點(diǎn),是發(fā)展未來(lái)嵌入式設(shè)備的絕佳資源。
2.Linux在嵌入式系統(tǒng)上的實(shí)現(xiàn)
2.1系統(tǒng)引導(dǎo)
系統(tǒng)上電或者復(fù)位后,將對(duì)系統(tǒng)硬件設(shè)備進(jìn)行自檢,無(wú)錯(cuò)誤則將硬盤0磁道的第一個(gè)扇區(qū),即MBR中的BootLoader調(diào)至內(nèi)存0x07C00處,并將控制權(quán)交給BootLoader[1]。BootLoader通常是一段匯編代碼,存放在MBR中,作用是將系統(tǒng)啟動(dòng)代碼讀到內(nèi)存中。目前可選用的引導(dǎo)工具主要有GRUB和LILO,這里我們選用主流的GRUB,由于選用的存儲(chǔ)介質(zhì)是CF卡,格式化CF卡后建立GRUB安裝目錄,按照提示安裝GRUB后,在 /etc目錄下新建grub.conf文件,內(nèi)容如下:
default=0
timeout=5
title Linux-2.4.34
root (hd0,0)
kernel /boot/vmlinuz-2.4.34 ro root=/dev/hdc1
其中root (hd0,0)指定了/boot所在的分區(qū),kernel一行用來(lái)指定Linux的內(nèi)核,及/所在的分區(qū)。
2.2內(nèi)核配置、編譯及裁減
內(nèi)核是Linux操作系統(tǒng)的核心,它負(fù)責(zé)管理系統(tǒng)進(jìn)程和進(jìn)程調(diào)度等大小事務(wù),決定著系統(tǒng)的性能和穩(wěn)定性,其它應(yīng)用程序都必須通過(guò)它才可以使用系統(tǒng)資源,獲取系統(tǒng)服務(wù)。由于嵌入式硬件資源的限制,我們需要對(duì)Linux內(nèi)核進(jìn)行定制,精簡(jiǎn)出符合實(shí)際需要的最小內(nèi)核文件。
首先在www.kernel.org上獲取相應(yīng)的內(nèi)核包,解壓后進(jìn)行配置,然后根據(jù)目標(biāo)板的硬件特點(diǎn)和實(shí)際需求配置內(nèi)核的編譯選項(xiàng)。這里我們選用基于X86 架構(gòu)的PC104主板,為了減低不必要的復(fù)雜性,內(nèi)核中取消kernel module支持,將有關(guān)CPU類型、內(nèi)存管理、doc驅(qū)動(dòng)、ext2文件系統(tǒng)支持、串口支持等常用功能編譯進(jìn)內(nèi)核,SCSI、Floppy之類的外設(shè)在我們的嵌入式系統(tǒng)中沒(méi)有使用,編譯時(shí)可去掉。這樣實(shí)際編譯出的內(nèi)核只有 747.6KB?;静襟E如下[2]:
#cd /usr/src/linux //內(nèi)核包所在目錄,這里下載的內(nèi)核包版本是2.4.34
#make mrproper //確保源代碼目錄下沒(méi)有不正確的.o文件以及文件的相互倚賴關(guān)系
#make menuconfig //圖形界面下編譯選項(xiàng)配置
#make dep //確保關(guān)鍵文件在正確位置
#make clean //確保所有有關(guān)文件都處于最新版本狀態(tài)
#make bzImage //編譯內(nèi)核
#cp /usr/src/linux/arch/i386/bzImage /mnt/cf/boot //將內(nèi)核文件拷貝至boot
2.3根文件系統(tǒng)實(shí)現(xiàn)
Linux 的根文件系統(tǒng)以樹(shù)的結(jié)構(gòu)方式組織,主要由配置文件、設(shè)備文件、Linux基本命令、基本C語(yǔ)言庫(kù)組成。后兩者是主要的,也是占空間最大的,用 Busybox和uClibc的組合夠建這兩部分內(nèi)容,可以大大節(jié)省空間。根據(jù)根文件系統(tǒng)的基本結(jié)構(gòu),我們建立各個(gè)對(duì)應(yīng)的目錄:
#mkdir proc dev bin boot boot/grub etc src lib //由于是單用戶系統(tǒng),刪除了root、home、sbin目錄
#cp –r /dev/null /dev/mem … /mnt/cf/dev //拷貝所需設(shè)備文件
最后需要在etc目錄下建立幾個(gè)配置文件,分別是/etc/inittab、/etc/init.d/rcS、/etc/fstab,限于篇幅,僅介紹inittab文件,內(nèi)容如下[4]:
:: sysinit: /etc/init.s/rcS //指定初始化文件
:: askfirst: /bin/sh //啟動(dòng)時(shí)執(zhí)行的shell
:: respawn: /bin/getty 38400 ttyS0 //打開(kāi)一個(gè)串口,波特率為38400
:: restart: /bin/init //重啟時(shí)執(zhí)行進(jìn)程init
:: ctrlaltdel: /bin/reboot //捕捉特定按鍵動(dòng)作
:: shutdown: /bin/umount –a –r //關(guān)機(jī)時(shí)動(dòng)作,卸載所有文件系統(tǒng)
[!--empirenews.page--]
3.嵌入式GUI研究
3.1基于嵌入式Linux的GUI系統(tǒng)底層實(shí)現(xiàn)基礎(chǔ)
一個(gè)能夠兼容多硬件平臺(tái)的嵌入式GUI系統(tǒng),應(yīng)至少抽象出兩類設(shè)備:基于圖形顯示設(shè)備(如VGA卡)的圖形抽象層 GAL(Graphic Abstract Layer)和基于輸入設(shè)備(如鍵盤,觸摸屏等)的輸入抽象層 IAL(Input Abstract Layer)[3]。抽象層的概念類似Linux內(nèi)核虛擬文件系統(tǒng)的概念,它定義了一組不依賴于任何特殊硬件的抽象接口,所有頂層的圖形操作和輸入處理都建立在抽象接口上,而用于實(shí)現(xiàn)該抽象接口的底層代碼稱為“圖形引擎”或“輸入引擎”,類似操作系統(tǒng)中的驅(qū)動(dòng)程序,這實(shí)際是一種面向?qū)ο蟮某绦蚪Y(jié)構(gòu)。利用該抽象接口,嵌入式GUI可以非常方便的移植到其他POSIX系統(tǒng)上,只需要根據(jù)抽象層接口實(shí)現(xiàn)新的引擎即可。
3.2嵌入式GUI基本性能需求
嵌入式GUI應(yīng)在基于操作系統(tǒng)的基礎(chǔ)上,為用戶提供豐富的圖形編程接口,使其能夠方便快速的編制界面友好的應(yīng)用程序。
GUI模塊的性能指標(biāo)為單位時(shí)間實(shí)例化個(gè)數(shù),如下所列:
基本圖形繪制速度,即點(diǎn)、線、框、塊、圓、弧、橢圓等圖形單元繪制速度。在顯示設(shè)備可見(jiàn)范圍內(nèi)任意位置產(chǎn)生隨機(jī)大小的基本圖形。量化指標(biāo)為單位時(shí)間內(nèi)繪制的個(gè)數(shù),并以較長(zhǎng)測(cè)試時(shí)間中取得的單位時(shí)間平均值為準(zhǔn)。
窗口創(chuàng)建速度。在顯示設(shè)備可見(jiàn)范圍內(nèi)任意位置創(chuàng)建隨機(jī)大小的窗口。量化指標(biāo)為單位時(shí)間內(nèi)成功創(chuàng)建及繪制完畢的窗口個(gè)數(shù),并以較長(zhǎng)測(cè)試時(shí)間中取單位時(shí)間平均值為準(zhǔn)。
控件創(chuàng)建速度。在顯示設(shè)備可見(jiàn)范圍內(nèi)任意位置創(chuàng)建隨機(jī)大小、包含隨機(jī)內(nèi)容的窗口。量化指標(biāo)為單位時(shí)間內(nèi)成功創(chuàng)建及繪制完畢的控件個(gè)數(shù),并以較長(zhǎng)測(cè)試時(shí)間中取單位時(shí)間平均值為準(zhǔn)。
事件驅(qū)動(dòng)機(jī)制反應(yīng)速度。針對(duì)窗口及不同控件的典型事件及耗時(shí)事件,測(cè)試其完成時(shí)間。窗口及控件的大小、復(fù)雜程度隨機(jī)產(chǎn)生。量化指標(biāo)為單位時(shí)間內(nèi)成功處理完畢的事件數(shù),并以較長(zhǎng)測(cè)試時(shí)間中取單位時(shí)間平均值為準(zhǔn)。
3.3輸入引擎移植
在基于Linux的嵌入式系統(tǒng)中,輸入設(shè)備可能只有觸摸屏和為數(shù)不多的按鍵,相對(duì)圖形引擎來(lái)說(shuō),輸入設(shè)備的處理沒(méi)有統(tǒng)一接口,在此情況下,提供一個(gè)抽象的輸入層,顯得尤為重要。
這里我們參考MiniGUI,并結(jié)合實(shí)際工程機(jī)械控制系統(tǒng)來(lái)實(shí)現(xiàn)輸入引擎的移植工作。MiniGUI簡(jiǎn)單可分為三層,最頂層為API,即編程接口;中間層是 MiniGUI的核心層,其中包括了窗口系統(tǒng)必不可少的各個(gè)模塊,如消息事件處理模塊、圖形設(shè)備接口等;而最底層則是GAL和IAL。
該實(shí)際工程機(jī)械控制系統(tǒng)擬采用觸摸屏作為主要的輸入設(shè)備,需要編寫自己的輸入引擎。首先定義一個(gè)結(jié)構(gòu)體用來(lái)從觸摸屏設(shè)備(/dev/ts)中接受數(shù)據(jù),結(jié)構(gòu)體定義如下:
typedef struct
{
unsigned short b; //觸摸屏狀態(tài)(是否被點(diǎn)擊)
unsigned short x; //觸摸屏x坐標(biāo)
unsigned short y; //觸摸屏y坐標(biāo)
unsigned short pad; //32位填充域,無(wú)實(shí)際意義
} POS;
接下來(lái)定義輸入引擎的初始化函數(shù),該函數(shù)打開(kāi)觸摸屏設(shè)備文件:/dev/ts,類似PC上的/dev/psaux設(shè)備。在成功打開(kāi)設(shè)備文件后,該函數(shù)通過(guò) mouse_getxy和mouse_getbutton等函數(shù)將獲得的狀態(tài)信息通過(guò)INPUT結(jié)構(gòu)體傳遞給GUI應(yīng)用程序。
BOOl InitPADInput (INPUT*input,const char*mdev,const char*mtype)
{
ts = open(“/dev/ts”, O_RDONLY);
if (ts<0) {
fprintf (stderr, “PAD:Can not open touch screen! ”);
return FALSE;
}
……
input->get_mouse_xy=mouse_getxy;
input->get_mouse_button=mouse_getbutton;
……
}
static void mouse_getxy(int* x, int* y)
{
*x=mousex;
*y=mousey;
}
static int mouse_getbutton(void)
{
return pos.b;
}
[!--empirenews.page--]
最后通過(guò)wait_event函數(shù)調(diào)用select系統(tǒng)調(diào)用,當(dāng)select系統(tǒng)調(diào)用返回值大于0時(shí),該函數(shù)檢查是否有可讀的數(shù)據(jù)等待讀取,如果是,則從該文件描述符中讀取觸摸屏數(shù)據(jù)。
限于篇幅原因,這里只列出了其中輸入引擎的移植代碼中較為關(guān)鍵的部分。代碼編寫完成后,還需要在“/src/ial/ial.c”中添加自定義的輸入引擎的入口項(xiàng)。
static INPUT inputs [] =
{ ……
#ifdef _PC104_IAL
{"pc104", InitYKInput, TermYKInput},
#endif
……
}
4.結(jié)束語(yǔ)
本文具體介紹了Linux作為嵌入式操作系統(tǒng)的實(shí)現(xiàn)方法,結(jié)合嵌入式GUI技術(shù),在PC104主板上利用Linux創(chuàng)建了一個(gè)擁有用戶界面的微型操作系統(tǒng),并通過(guò)對(duì)抽象層接口及相關(guān)技術(shù)的分析,自定義輸入引擎,實(shí)現(xiàn)了設(shè)備的可定制,在實(shí)際工程機(jī)械項(xiàng)目中有較大的實(shí)用價(jià)值和市場(chǎng)前景。
創(chuàng)新點(diǎn):利用Linux在嵌入式主板上搭建了一個(gè)微型操作系統(tǒng),在此基礎(chǔ)上實(shí)現(xiàn)了針對(duì)觸摸屏的輸入引擎的移植。