嵌入式GUI为嵌入式系统提供了人机交互界面, 大大方便了嵌入式系统的人机交互,进而加速了嵌入式系统的流行。无论是智能手机、PDA还是MP4、PMP (个人媒体播放器)的流行,嵌入式GUI功不可没。嵌入式GUI为适应资源有限的嵌入式系统,往往要求界面简单、直观、可靠、占用资源小,并且反应迅速, 同时为了适应嵌入式系统硬件本身的多样性,嵌入式GUI需要具备高度可移植性与可裁减性,以适应不同的硬件条件和使用要求。因为对嵌入式GUI要求较高, 所以到现在为止,在嵌入式Linux 下可用的嵌入式GUI始终不多。本文将介绍的是目前应用较为广泛的嵌入式GUI——Qt/Embedded的一些开发知识。
基础知识 一个能够移植到多种硬件平台上的嵌入式GUI系统至少需要抽象出两类设备, 即负责显示图形界面的图形抽象层GAL (Graphic Abstract Layer)和负责接收及处理输入(一般输入设备为键盘、触摸屏)的输入抽象层IAL (Input Abstract Layer)。在GAL和IAL层完成对具体的显示设备和输入设备的具体操作,尽可能地对上层软件屏蔽各种不同硬件的技术实现细节,从而为上层应用程序开 发人员提供统一的编程接口。GAL层与IAL层的设计概念大大提高了嵌入式GUI的可移植性。
目前在Qt/EmbeddedGAL层技术使用的是FrameBufer。
Qt是一个跨平台C++应用程序开发框架。程序员利用其可以编写单一代码的应用程序,并可在Windows、Linux、Unix、MacOS X和嵌入式Linux等不同平台上进行本地化运行。目前,Qt已被成功应用于数以千计的商业应用程序。此外,Qt还是开放源代码KDE桌面环境的基础。
Qt/Embedded (下文中简称为qt/e)是Qt的嵌入式Linux版本。qt/e延续了Qt的强大功能,现在已经有大量的像KDE这样的重量级应用基于Qt开发,因此, 在嵌入式系统上通过使用qt/e可以方便地移植桌面应用到各式各样的嵌入式平台上,这使得嵌入式系统的应用软件开发工作大大简化了,qt/e由此获得了广 泛的支持。qt/e可以开发市场上多种类型的产品和设备,从消费电器(移动电话、PDA)到工业控制设备(如医学成像设备、移动信息系统等)。
在qt/e之上,Qtopia是第一个面向嵌入式Linux的全方位应用程序开发平台, 它可以并且已经应用于众多的基于Linux的PDA (个人数字助理)设备和智能电话。
与Qt类似,qt/e类库也完全采用C++ 封装, 但在底层舍弃了X-Window ,而是采用Frame Buffer作为底层图形接口。因此,qt/e具有丰富的控件资源和良好的可移植性。
从Trolltech公司的网站上可以下载到qt-embedded-opensource-4.0.0-b2.tar.gz和qtopia-core-opensource-src-4.1.1.tar.gz安装包。
编译安装 鉴于目前大量的Linux BSP(Linux板级支持包)是在Red Hat 9.0上开发的。所以为了方便起见, 笔者使用Red
Hat 9.0作为开发平台。另外,作为开发机,往往不需要考虑安全问题,为了防止不必要的麻烦就直接使用root登录。
在建立qt/e开发环境的过程中,使用的软件和代码都可以免费从Trolltech官方站点上获得,使用qt/e的3.3.4安装包。
现在很多公司仍然使用qt/e 2.x版本,因为2.x 出现的较早,所以各方面的支持比较完善和稳定。但新版本安装配置更加容易,无需手动配置tmake,无需安装配置Qt-X11也可以正常使用,所以这里推 荐大家使用较新的版本。笔者在使用过程中发现,很多公司提供的交叉编译环境在编译2.x版本时可以正常使用,但在编译3.x版本时会出现编译错误。对于这 样的问题,就只能退回到2.x版了。
1.安装qt/e 3.3.4
在Linux 命令模式下运行以下命令:
#tar xfz qt-embedded-eval-3.3.4.tar.gz
为了方便起见,把解压出来的文件夹重新命名为qt-3.3.4
#cd qt-3.3.4
按照INSTALL的提示,输入如下内容:
#export QTDIR=~/qt-3.3.4
#export LD_LIBRARY_PATH=~/qt-3.3.4/lib:$LD_LIBRARY_PATH
#./configure
然后按照出现的提示配置编译选项。需要注意的是,“./configure” 脚本默认编译的是针对当前Linux平台的版本, 如果希望编译出在嵌入式平台上运行的版本,则需要配置好交叉编译环境,然后使用如下命令来配置编译选项:
#./configure --embedded XXX
更多信息可以使用“./configure -help”脚本打印出所有可以使用的配置选项及具体用法。
这里就可以看到默认的一些配置信息(标注星号的部分)。如果要更改默认配置,则可在./configure后面直接加上对应的参数。配置完成后,就可以直接使用make命令来编译整个项目了。
2.运行Demo
编译完成后, 可以运行一个Demo来看看上面的工作是否做对了。这个时候需要检查一下计算机是否支持FrameBuffer (帧缓冲),最简单的方式就是使用命令:
# cat /dev/fbO
如果输出大段大段的乱码,就可以直接使用“Ctrl”+“Alt”+“F1”切换到控制台下去直接执行~/qt-3.3.4/examples/下的 Demo来看看效果了, 如果计算机并不支持FrameBuffer,即机器输出“找不到fb0这个文件或目录”。不支持也不用着急, 因为目前的发行版的内核编译的时候基本上都是支持Frame Buffer的,只是没有打开这个选项而已,这时需要打开/boot/grub下面的menu.lst文件, 找到操作系统对应的那个选项, 比如笔者的机器如下:
title Fedora Core(2.6.11-1.1369_FC4)
root(hd0,0)
kernel /vmlinuz-2.6.11-1.1369_FC4 ro root=/dev/VolGroup00/LogVol00 rhgb quiet
initrd /initrd-2.6.11-1.1369_FC4.img
将Kernel那一行修改成:
kernel /vmlinuz-2.6.11-1.1369_FC4 ro root=/dev/VolGroup00/LogVol00 rhgb
quiet vga=0x317。
其中vga=0x后面的数值可以从下表中查出。
{MOD}彩数
640 X 480
800X600
1024X768
1280X1024
256
0x301
0x303
0x305
0x307
32k
0x310
0x313
0x316
0x319
64k
0x311
0x314
0x317
0x31A
16M
0x312
0x315
0x318
0x31B
下面是笔者机器编译后运行的几个Demo输出。
# cd examples/laucher
# /launcher
# cd examples/hello
# ./hello -qws
#cd examples/demo
# ./demo -qws
在运行Demo的时候,请注意以下几点:
- qt/e嵌入式的应用程序要把显示结果输出到FrameBuffer,在命令行运行这个程序时,在程序名后加上-qws的选项。-qws选项的含义是使这个应用程序成为服务器。
- 当按照上述操作执行,在屏幕上qt/e的确正常运行并出现了应用程序界面,但当移动鼠标或者使用键盘输入命令时发现会有一些不正常的显示时,这是因为鼠标键盘没有配置好造成的,请针对找到鼠标键盘对应的设备文件,使用如下命令配置:
# export QWS_MOUSE_PROTO =:
例如,“Microsoft:/dev/ttyS0”或“MouseMan:/dev/input/mouse0” 等类似的格式。
# export QWS_KEYBOARD=如/dev/tty等。
Qvfb的安装与运行
如果内核编译的时候没有选择FrameBuffer模块,那么还可以通过Qvfb来看到qt/e的运行结果,这种方式需要安装Qt-X11。需要注意的 是,当qt/e移植到嵌入式平台上时,是无法使用Qvfb 的, 即QT_NO_QWS_VFB在产品库中应该是会被定义的。
虚拟帧缓冲(Qvfb)使用了共享存储区域来模拟帧缓冲(即一个虚拟的帧缓冲)并且在一个窗口中(Qvfb程序的主窗口)显示帧缓冲。显示的区域会被周期 性的改变和更新,所以看到的是帧缓冲的不连续快照,而不是每一个单独的绘画操作。因为这个原因,在绘画时出现的一些问题,比如闪烁,在程序使用真正的帧缓 冲运行就不会再出现了。
Qvfb目标刷新速度可以通过“View”-“Refresh Rate”选单项来设置。这样可以控制Qvfb检查和要被刷新的区域的速度。刷新速度仅仅只是一个指标而已。如果一个小的绘画操作已经完成了,帧缓冲将不 会再在绘画事件之间做出任何更新。如果一个应用程序正在显示一个动画, 更新将会更频繁,并且应用程序和Qvfb会争夺处理器时间。
鼠标和键盘事件将通过命名管道传递给qt/e嵌入式主程序处理。
虚拟帧缓冲只是一个开发工具。在虚拟帧缓冲设计中没有考虑任何安全问题,在产品环境中应该避免这个问题。
1.安装
Qvfb是一个Linux下的程序,无需考虑交叉编译和移植的问题, 只需要当作普通应用程序编译即可,步骤如下:
- 解压qt-x11-eval-3.3.4.tar.gz到/usr/local/ 目录下, 并重命名为qt。
- 执行如下命令:
#export QTDIR=/usr/local/qt
#export PATH=$QTDIR/bin:$PATH
#export MANPATH =$QTDIR/man:$MANPATH
#export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
- 配置、编译
# ./configure
# make
- 编译Qvfb
# cd tools/qvfb/
# make
然后就可以直接运行Qvfb了。
此时, 如果希望q/e的Demo可以在Qvfb中运行,需要在配置编译q/e时,加上Qvfb选项。
# ./conligure -qvfb
然后重新使用“make” 命令编译(如果之前已经编译过了,最好先运行make clean命令一下)。在运行Demo以前,先启动Qvfb,并做一下配置:
# ./qvfb
选择“File”-“Configure”选单。需要注意的是, 这里的 {MOD}彩位数要和编译qt/e时的选择一致。
qt/e上的程序在运行时,会自己查找Frame Bufer支持的分辨率等属性,虽然也可以获取Frame Buffer设备可以支持的 {MOD}彩位数,但是在编译qt/e的时候需要指定支持的 {MOD}彩位数,如果设备不支持对应的 {MOD}彩位数,程序将无法运行。
2.运行
配置完成后,就可以执行一下,来看看效果了。
#cd examples/launcher
#./launcher
# cd examples/hello
# ./hello -qws
#cd examples/demo
# ./demo -qws
所有工作均在笔者的PC机Fedora Core 4环境编译测试通过。
qt/e作为一个用户层的平台,仅仅通过输入输出设备以及Frame Bufer设备的设备文件与设备交互,在一个已经可以运行的嵌入式平台上,只要驱动已经完成了。qt/e几乎不用做多少调整既可以正常运行,qt/e上应 用程序的开发、调试都可以在开发者的PC 机上进行,能够在PC上正常执行的qt/e上的应用程序,在嵌入式平台上基本上不会出现什么问题(使用Qvfb虚拟帧缓冲的可能显示效果会有一些区别), 这大大降低了在嵌入式平台上开发的难度,从而为高效开发嵌入式程序提供了强有力的保障。