引言
什么是嵌入式系统
嵌入式系统一般指以嵌入式微处理器为核心,有别于PC系统,有计算机的部分功能但又不称之为计算机的设备或器材。它主要是以应用为目的,系统软硬件于一体,通常要求具有代码小、响应速度快、可靠性高、低功耗、集成度高等特点。嵌入式系统遍布于各个行业以及人们的日常生活当中,比如掌上PDA、移动计算设备、电视机顶盒、手机、汽车、数字相机、家庭自动化系统、安全系统、自动售货机、工业自动化仪表与医疗仪器等。
什么是嵌入式系统中的GUI
随着后PC时代的到来,嵌入式系统的性能有了大幅度的提高,应用范围也越来越广,当初的一些简单的人机交互接口已经无法满足人们的要求。而与此同时,在台式PC机上图形交互界面早已普及并成熟,于是在嵌入式系统中也逐渐出现了图形用户界面(GraphicUserInterface,GUI),特别是在一些消费类产品中。嵌入式系统中的GUI就是在嵌入式系统中为特定的硬件设备或环境而设计的图形用户界面系统。由于受到当前嵌入式系统本身特点的影响,并受其发展限制,所以嵌入式系统中的GUI应该有如下特点:
占用的存储空间以及运行时占用资源少;运行速度以及响应速度快;可靠性高;便于移植和定制。
Linux有开放的源码、高效稳定的内核、良好的开发环境以及支持多种硬件平台等特点,而且由于Linux的可配置性和可模块化,一个Linux内核经过配置和裁减可以只占用几百K左右的存储空间,使其在嵌入式系统中也得到广泛应用。然而,在嵌入式系统中有严格的资源限制,台式机Linux平台下成熟的GUI无法直接移植到嵌入式设备上。因此,嵌入式系统中基于Linux的GUI愈发成为开发基于Linux的嵌入式系统所必须面对的问题。目前,随着嵌入式行业分工的细化,出现了专门的公司致力开发Linux下的GUI并给其它公司提供授权,从而缩短了嵌入式系统的开发周期。本文就旨在于对这样的几种嵌入式GUI进行研究,列出表1进行比较,并介绍这几种GUI在基于ARMLinux上的移植。
几种比较成熟的嵌入式GUI的研究
Microwindows
Microwindows是由美国CenturySoftware公司开发的开放源码的嵌入式GUI项目。它不需要其他图形系统的支持,可以充分利用Linux提供的FrAMEbuffer机制来进行图形显示。同时在底层提供了对多种芯片的支持,并基本上用C语言实现,因此移植性很强。国内也有人参与了这个项目的开发,并编写了GB2312等字符集的支持。
Microwindows是基于分层式设计的,它允许不同的层可以被重新设计以满足系统实现的需要,目前总共分为三层。最底层是屏幕、鼠标或触摸屏和键盘的驱动程序,用于实现系统的显示功能以及满足用户特有的输入需求。中间层实现了一个可移植的图形引擎,以提供对画线、填充、剪切和着色的支持。在最上层,则提供了多种的API给应用程序设计者。Microwindows支持两种API:ECMAAPIW(类Win32API)和Nano-XAPIs。这些API对Win32和XWindow系统有很好的兼容性,使程序可以很容易地从其它系统上移植过来。其中比较完备的是Nano-XAPI。Nano-X设计成是一个客户端/服务器的环境,在此模式下应用程序与一个客户端的库相连,而这个库则通过一个UNIXsocket与Nano-X服务器相连。每个应用程序都通过UNIXsocket来传递各种参数,并由服务端来完成客户端的各种请求。当为了满足运行速度以及调试的需求时,还可以通过共享的内存空间来完成传播数据。
由于Microwindows为了与XWindow的兼容,它采用了传统的基于UNIXsocket的客户端/服务器结构。此是,客户端的画图、窗口建立等操作都是通过套接字与服务器通信。在这种情况下,系统就变得非常依赖于UNIXsocket,而UNIXsocket的传递都需要通过内核,这样在一些对实时性要求比较高的系统里就不太有利。而且Microwindows基本上用C语言实现的,虽然增强了可移植性,但也同样导致了系统的运行效率不高。同时Microwindows的开发工具FLNX也还不够成熟,有待进一步提高。
MiniGUI
MiniGUI是我国国内自主开发、比较成熟的一个图形用户界面系统,面向基于Linux的实时嵌入式系统,使用现有成熟的图形引擎(SV2GALib/LibGGI),采用类似WinCE的线程机制(目前MiniGUILite版本改用微客户端/服务器模式来提供对多进程的支持),集成了多字体和多字符集,支持硬件加速能力,充分使用显示内存。
从整体来看,MiniGUI也是属于分层结构设计(见图1)。在最底层,GAL和IAL提供了Linux控制台和底层图形接口的支持以及输入设备比如鼠标、键盘等的驱动,PThread则是提供了内核级线程支持的函数库;中间层MiniGUIKernel则包括了窗口系统的各个模块,MiniGUI本身是运行在多线程模式下,它的各个模块都是以单独的线程运行,同时它也利用线程来实现多窗口;最上层,则是提供给各种应用程序使用的API函数。MiniGUI中利用线程之间的同步操作,实现了客户线程和服务线程之间的微客户端/服务器结构,因为它的客户和服务器是同一进程的两个不同线程。它的核心实现主要体现在消息队列数据结构的使用上。
多线程有其一定的好处,但弱点则在于不同的线程共享了同一个地址空间,因此,客户线程可能会破坏系统服务器线程的数据,导致系统健壮性不够健全。虽然目前的MiniGUILite版本抛弃LinuxThread库而改用微客户端/服务器模式提供对多进程的支持,但是仍然存在着对多进程支持弱、图形功能不完善、窗口剪切不完备等问题。
QT/Embedded和Qtopia
QT/Embedded是著名的QT库开发商TrollTech开发的基于framebuffer、面向嵌入式系统的QT版本。它的特点主要有界面美观、色彩配比好,使用与QT/Windows和QT/X11完全一致的API接口,许多基于QT的程序可以非常方便地移植到嵌入式系统;同时它具有丰富的模块,用户可以根据需要选择QT/Embedded的特性集合。Qtopia是TrollTech专门为嵌入式Linux设备所定制终端用户平台,它包括了Qtopia库和Qtopia的服务器及客户端应用程序。
QT/Embedded和Qtopia的结构如图2所示。QT/Embed2ded实现了对下层输入设备的驱动和底层图形接口以及各基类和API。Qtopia也是以客户/服务器的方式,通过消息机制来管理各种应用程序。QT的资源相当丰富,基于QTAPI开发的应用程序相当多,像KDE这种应用范围极广的GUI也是使用QTAPI开发出来的;而且OPIE组织也开发了并改进了许多专门基于QT/Embedded上的Qtopia应用程序及函数库。
不过QT/Embedded对于系统的资源要求非常高,需要在较大的存储空间和运行空间上才可以运行;而且它是基于C++来实现的,而这种C++接口对于嵌入式系统中的某些应用来说就显得比较臃肿;另外如若需要修改QT/Embedded并在商业产品中发布,则需要分别购买开发授权及运行时授权,所需费用太昂贵。
基于ARMLinux平台的移植
编译环境的建立
GUI的编译通常都是在PC机上执行的,也就是说,编译器本身能够在PC机上执行,同时编译源代码生成的二进制文件必须能在目标机上执行,这类编译器通常称为交叉编译器。对于ARM平台,我们安装了cross-arm-binutils-*.i386.rpm、cross-arm-gcc-*.i386.rpm、cross-arm-glibc-*.i386.rpm这三个包。这些包都可以从网上免费获取,“*”通常代表版本号。arm-binutils这个包一般包含了一些针对ARM平台的二进制工具,比如arm-STrip、arm-ar等命令;arm-glibc这个包包含的是标准C的函数库的ARM的版本以及对应的头文件;arm-gcc中包含的则是生成ARM平台代码的x86上的交叉编译器。执行rpm命令将这些包安装到PC机上,若不在系统默认搜索目录下,比如安装在/opt/cross目录下,则必须将/opt/cross/bin目录加到系统的PATH环境变量中,这样在每次编译时系统才能找得到编译器。另外需要注意的是,编译时所用的函数库版本要与目标版上运行时所用的函数库版本一致。经过上述步骤,就已经建立了交叉编译环境,接下来的就是选择或修改GUI的编译选项,从而生成所需要的GUI系统。
Microwindows的移植
Microwindows的定制和编译主要是通过修改它源程序根目录下的cONfig这个文件中的选项来实现,而在configs这个目录下已经有一些针对不同平台的config文件,若目标平台与之定义的相符,可直接将其拷贝到根目录下覆盖掉原有的config文件,然后输入命令make来开始编译。另外还可以执行根目录下的xconfigure文件,它提供了一个可视化的窗口来方便用户进行编译选项配置。下面介绍一下其中主要的一些选项:
目标平台选项。ARCH表示目标机的平台,比如ARCH=LINUX-ARM,BIGENDIAN表示目标平台是否为大数端;
图像支持选项。HAVE-BMP-SUPPORT=Y、HAVEJPEG-SUPPORT=Y两项表示对BMP和JPEG格式图像的支持(还有其它格式选项)。设置JPEG图像选项时必须给出外部jpeg解压缩库的位置,例如LIBJPEG=/usr/lib/libjpeg.a;
字体支持选项。HAVE-FREETYPE-SUPPORT=Y、HAVE-T1LIB-SUPPORT=Y表示支持TrueType和AdobeType1字体,这些库也必须预先编译并在配置文件中指定其位置,Microwindows的网站上提供了许多字库函数的下载。另外,Microwindows还提供了中文BIG5、GB2312以及日文和韩文的支持;
输出显示选项。FRAMEBUFFER=Y表示使用Linux上的framebuffer来实现显示,当然Microwindows也支持X11显示;
输入设备选项。Microwindows提供了一系列的鼠标(包括触摸屏)和键盘的支持,可以根据不同的系统选择适当的选项。
配置完成后,执行make命令开始编译。编译完成后,将生成的库以及可执行文件打包下载到目标板上。如果库文件没有放在目标系统的默认搜索库的路径中,那么还需将此目录加到LD-LIBRARY-PATH环境变量中,然后即可以运行nano-X服务器及各应用程序。
MiniGUI的移植
下载MiniGUI的库文件源代码包libminigui-3.tar.gz和资源文件包minigui-res-3.tar.gz以及演示程序包mde-3.tar.gz后,将它们分别解压到各自的目录下。首先介绍库文件的编译,它的编译配置主要通过执行源程序根目录下configure这个文件,并给它传递相关的参数来实现。比如:CC=arm-linux-gcc./configure———host=i386-linux———target=arm-linux。其中,CC参数表示所使用的编译器名,host表示编译环境所在的主机类型,target表示编译生成后目标系统的主机类型,当前默认编译生成的是MiniGUIThread版本,如果要生成MiniGUILite版本需再加上参数———enable-lite,更多参数可以通过执行。/configure-help来查询。在执行configure之前,根据硬件特性可以修改根目录下的etc目录下的Minigui-3d.cfg和Minigui-flat.cfg两个文件中的选项。比如,如果目标系统的framebuffer大小是320X240,每像素占12bits,则将上述两个文件中[fbcon]组中的defaultmode的值就应设置为320X240-12bpp。配置完成以后执行make命令开始编译,编译结束后执行makeinstall命令,在/usr/local/lib下面会生成交叉编译出来的动态库和静态库文件。其次,资源文件的安装比较简单,解压以后在其根目录下有一个名叫config.linux的文件,修改其中的TOPDIR一项,这样执行makeinstall安装命令以后,所有资源文件会被安装到TOPDIR所定义的目录下的usr/local/lib/minigui下。最后演示程序包的编译与库文件编译类似,也是执行其根目录下的configure文件并传递相关参数,然后执行make命令来编译。若编译库文件时选择———enable-lite参数,由于MiniGUI-Lite采用的是微客户端/服务器架构,要运行应用程序必须先启动服务器程序mginit,然后才能运行其它的应用程序;若编译库文件时没有添———enable-lite参数,则mginit目录根本不会编译进去,演示程序可以直接执行。
QT的移植
QT的编译步骤比较复杂。Qtopia的根目录下有README.html文件介绍了PC机上编译的步骤及参数。因此,本文主要描述在编译成以ARM为目标平台时有所区别的几个步骤及参数。下载Qt/Embedded、Qt/X11和Qtopia三个包并分别解压。这三者的编译配置都是通过执行相应根目录下的configure文件并传递相关参数来实现,另外在Qtopia目录下src/qt/qconfig-qpe.h文件中要定义一些相关的宏,这样在编译时编译器会根据所定义的宏选择需要的代码来进行编译。比如,目标系统所使用的触摸屏实现方式与IPAQ类似,若要使QT将所支持的代码编译进来,则需在qt2config-qpe.h中定义宏QT-QWS-IPAQ。首先,我们在执行configure对QT/Embedded进行配置时,传递了三个参数-xplatformlinux-arm-g++、-qconfigqpe和-no-qvfb。其中第一个参数表示,编译后二进制文件执行时所在的目标平台类型;第二个参数告诉编译器配置头文件是在src/tools/目录下叫做qconfig-qpe.h,通常这个文件就是Qtopia目录下src/qt/qconfig-qpe.h的一个拷贝;第三个参数表示在编译时不需要编译qvfb工具,当目标系统不支持Framebuffer时,在执行启动Qtopia之前先通过执行qvfb来产生一个虚拟的Framebuffer,这时再启动Qtopia相应的内容就会显示在qvfb上。在对Qtopia进行配置时,只传递了一个参数:-platformarm-linux-g++,表示目标平台是ARM平台。当然在上述配置过程中还可以使用其它一些参数,这些参数可以通过传递-help参数给configure来查询。在配置并编译完之后,将Qtopia目录下的运行时相关目录全部打包并下载到目标系统上,设置了相应的环境变量(比如QPEDIR、QTDIR和LD-LIBRARY-PATH等)后,就可以执行。当然目标系统上的特殊硬件的支持需要通过修改QT/Embedded下的对应源程序来完成。