嵌入式Linux的MiniGUI研究和移植

摘要:分析嵌入式操作系统下典型的图形用户界面MiniGUI的结构和特点,并提出将其移植到SUNPLUS的DVD720上的方案。
关键词:图形用户界面(GUI) 嵌入式系统 Frame Buffer
引 言
1 嵌入式Linux下的GUI概况
1.1 GUI在嵌入式系统中的地位
  随着嵌入式系统的广泛应用,PDA、机顶盒、DVD/VCD播放机及WAP手机已经迅速普及。图形用户界面(GUI)的广泛流行,是当今计算机技术的重大成就之一。它极大地方便了非专业用户的使用,因此实时嵌入式系统对GUI的需求越来越明显,而这一切均要求有一个高性能、高可靠的GUI 的支持。
  由于嵌入式系统实时性要求非常高,对GUI的要求也更高。这些系统一般不希望建立在庞大累赘的、非常消耗系统资源的操作系统和GUI之上,比如Windows或X Window,太过庞大和臃肿。这样,这些系统对轻型GUI的需求更加突出。另外嵌入式系统往往是一种定制设备,它们对GUI的需求也各不相同。有些系统只要求一些图形功能,而有些系统要求完备的GUI支持,因此,GUI也必须是可定制的。嵌入式系统对GUI的基本要求包括轻型、占用资源少、高性能、高可靠性及可配置[1]。
1.2 目前嵌入式系统中GUI的实现
  尽管实时嵌入式系统对GUI的需求越来越明显,但目前GUI的实现方法各有不同[1]:
  ① 某些大型厂商有能力自己开发满足自身需要的GUI系统。
  ② 某些厂商没有将GUI作为一个软件层从应用程序中剥离,GUI的支持逻辑由应用程序自己来负责。
  ③ 采用某些比较成熟的GUI系统,比如 Mini GUI、MicroWindows 或者其它GUI系统。
  比较常用的有如下几种GUI系统:紧缩的X Window 系统、MiniGUI、MicroWindows、OpenGUI及QT/Embedded 等。下面简单介绍这些系统。
  (1)MiniGUI
  MiniGUI[2]由原清华大学教师魏永明先生开发,是一种面向嵌入式系统或者实时系统的图形用户界面支持系统。它主要运行于Linux控制台,实际可以运行在任何一种具有POSIX线程支持的 POSIX兼容系统上。MiniGUI同时也是国内最早出现的几个自由软件项目之一。稍后将对它作详细的介绍。
  (2)MicroWindows
  MicroWindows[3]是一个著名的开放源码的嵌入式GUI软件。MicroWindows提供了现代图形窗口系统的一些特性。MicroWindows API接口支持类Win32 API,接口试图和Win32完全兼容。它还实现了一些Win32用户模块功能。MicroWindows采用分层设计方法,以便不同的层面能够在需要的时候改写,基本上用 C 语言实现。MicroWindows已经支持 Intel 16位和32位CPU、MIPS R4000 以及 ARM 芯片;但作为一个窗口系统,该项目提供的窗口处理功能还需要进一步完善,比如控件或构件的实现还很不完备,键盘和鼠标等的驱动还很不完善。
  (3)OpenGUI
  OpenGUI[4]在Linux系统上存在已经很长时间了。这个库是用C++编写的,只提供C++接口。OpenGUI基于一个用汇编实现的x86图形内核,提供了一个高层的C/C++图形/窗口接口。OpenGUI提供了二维绘图原语、消息驱动的API及BMP文件格式支持。OpenGUI功能强大,使用方便。OpenGUI 支持鼠标和键盘的事件,在Linux上基于Frame buffer或者SVGALib实现绘图。由于其基于汇编实现的内核并利用MMX指令进行了优化,OpenGUI运行速度非常快。正由于其内核用汇编实现,可移植性受到了影响。通常在驱动程序一级,性能和可移植性是矛盾的,必须找到一个折衷。
  (4)QT/Embedded
  QT/Embedded[5]是著名的QT库开发商Trolltech 的面向嵌入式系统的QT版本。这个版本的主要特点是可移植性较好,许多基于QT的X Window程序可以非常方便地移植到嵌入式系统;但是该系统不是开放源码的,如果使用这个库,可能需要支付昂贵的授权费用。
2 MiniGUI的特点和体系结构
2.1 MiniGUI的特点
  MiniGUI的主要特点有[1]:
  ◇ 遵循GPL条款的纯自由软件。
  ◇ 提供了完备的多窗口机制,包括:
  多个单独线程中运行的多窗口;
  单个线程中主窗口的附属;
  对话框和预定义的控件类(按钮、单行和多行编辑框、列表框、进度条及工具栏等);
  消息传递机制。
  ◇ 多字符集和多字体支持,目前支持 ISO8859-1、GB2312及Big5 等字符集,并且支持各种光栅字体和 TrueType、Type 1 等矢量字体。
  ◇ 全拼和五笔等汉字输入法支持。
  ◇ BMP、GIF、JPEG及PCX 等常见图像文件的支持。
  ◇ Windows的资源文件支持,如位图、图标、光标、插入符、定时器及加速键等。
  ◇ 小巧。包含全部功能的库文件大小为300 KB左右。
  ◇ 可配置。可根据项目需求进行定制配置和编译。
  ◇ 高稳定性和高性能。MiniGUI已经在Linux发行版安装程序、CNC系统及蓝点嵌入式系统等关键应用程序中得到了实际应用。
  ◇ 可移植性好。目前,MiniGUI可以在X Window 和Linux控制台上运行。中科院EEOS开发组已经成功地将MiniGUI移植到了他们的POSIX兼容系统上。蓝点软件(北京)研发中心也已经成功地将 MiniGUI移植到了两款基于StrongARM的嵌入式系统上。
2.2 MiniGUI的体系结构
  从整体结构上看,MiniGUI是分层设计的,层次结构如图1所示。在最底层,GAL和IAL提供底层图形接口以及鼠标和键盘的驱动;中间层是MiniGUI 的核心层,包括窗口系统必不可少的各个模块;最顶层是API,即编程接口。GAL和IAL为 MiniGUI提供了底层的Linux控制台或者X Window 上的图形接口以及输入接口,而Pthread用于提供内核级线程支持的C函数库。

利用GAL和IAL,大大提高了MiniGUI的可移植性,并且使程序的开发和调试变得更加容易。可以在X Window上开发和调试自己的MiniGUI程序,通过重新编译就可以让MiniGUI应用程序运行在特殊的嵌入式硬件平台上。
3 MiniGUI的移植
  笔者的项目DVD720工作在μC/OS嵌入式操作系统下,核心CPU为MIPS芯片。该平台是SUNPLUS公司提供的一个多媒体平台,不仅仅实现DVD的播放,还包含一些附加功能,例如游戏、卡拉OK、VOD及上网等功能,并为用户提供了编程接口,使用户可以在DVD上对Lego公司的机器人进行控制。为了给用户提供一个友好的界面,以及从易用性和通用性方面考虑,将MiniGUI移植到我们的DVD720平台。DVD720平台的体系结构如图2[6]所示。由于MiniGUI的分层实现,需要考虑的只是HAL接口下的各驱动程序:鼠标驱动程序、键盘驱动程序及图形驱动程序。

3.1 鼠标和键盘驱动程序
  鼠标驱动程序非常简单。抽象意义上讲,初始化鼠标后,每次用户移动鼠标,就可以得到一个X 和 Y 方向上的位移值。驱动程序内部维护鼠标的当前位置,用户移动鼠标后,当前位置被加上位移值,并通过上层Cursor支持,反映到屏幕上,用户就会认为鼠标被正确地“移动”了。现在有各种各样的鼠标,例如MS鼠标、PS/2鼠标、总线鼠标及GPM鼠标等,其主要差别在于初始化和数据包格式上。键盘驱动程序的实现也比较简单,在此不作详细的介绍。
3.2 图形驱动程序
  HAL提供的接口函数大多与图形相关,主要就是通过调用图形驱动程序来完成任务的。图形驱动程序屏蔽了底层驱动的细节,实现底层驱动相关的功能,而不是硬件相关的一些功能,如一些画圆和画线的GDI函数、普通的剪切,可直接在HAL接口层实现。
  DVD720的显示驱动是基于Frame buffer的驱动程序的。通过对SDRAM中的frame buffer和video bitstream buffer写入,就可以实现对TV和显示器的刷新。像素的写入方式和顺序如图3所示[6]。

下面介绍各接口函数:
  Open,Close
  基本的初始化和关闭函数。在Open函数里要选择子图形驱动程序,将其实现的函数赋给本PSD 结构的函数指针。这里只考虑基于Frame buffer的图形引擎的初始化。
  SetPalette,GetPalette
  当使用8位或以下的图形模式时,要使用系统调色板。这里是调色板处理函数,它们和Windows API中的概念类似。Linux系统利用ioctl 提供了处理调色板的接口。
  AllocateMemGC,MapMemGC,FreeMemGC
  内存屏幕是一个伪屏幕。在对屏幕图形操作过程中,比如移动窗口,先生成一个内存屏幕,将物理屏幕的一个区域拷贝到内存屏幕,再拷贝到物理屏幕的新位置,这样就减少了屏幕直接拷贝的延时。AllocateMemGC用于给内存屏幕分配空间,MapMemGC做一些初始化工作,而FreeMemGC则释放内存屏幕。
  DrawPixel、ReadPixel、DrawHLine、DrawVLine及FillRect
  这些是底层图形函数。分别是画点、读点、画水平线、画竖直线及画一个实心矩形。之所以在底层实现这么多函数,是为了提高效率。图形函数支持多种画图模式,常用的有直接设置或Alpha混合模式,从而可以支持各种图形效果。
  PutHLine、GetHLine、PutVLine、GetVLine、PutBox、GetBox及PutBoxMask
  Get* 函数用于从屏幕拷贝像素到一块内存区,而Put*函数用于将存放于内存区的像素画到屏幕上。PutBoxMask 与PutBox的唯一区别是,如果要画的像素是白色,就不会被画到屏幕上,从而达到一种透明的效果。
4 总结与展望
  到目前为止,我们的移植工作已经顺利完成。MiniGUI已经能成功运行在我们的DVD720平台上。作为底层支持的GUI系统,MiniGUI也应该像操作系统一样是开放源码的自由软件,并应该得到开发商的共同推动。到目前为止,已经有多家嵌入式系统开发商采用MiniGUI开发嵌入式系统,并且已经开发出了许多重要的应用程序。我们期望能够有更多的人加入MiniGUI的开发,共同促成MiniGUI成为嵌入式 Linux系统上的标准GUI。尽管MiniGUI目前的功能已经非常强大,并且已经成功应用于许多嵌入式系统,但还需要在如下领域进行开发:
  ◇ 建立一个 C++ 类库来封装MiniGUI的API;
  ◇ 建立基于传统进程级客户/服务器体系结构的 MiniGUI,以便能够让MiniGUI适合于一些较大的嵌入式系统,比如支持全功能浏览器的机顶盒。
  随着MiniGUI不断推广和功能的加强,它也将在实际应用中不断走向成熟。实时嵌入式系统上的GUI开发正处于开始阶段。在这个领域,有许多技术难题等待自由软件程序员去解决。

你可能感兴趣的:(其他嵌入式操作系统)