Chinaunix首页 | 论坛 | 博客
  • 博客访问: 390767
  • 博文数量: 107
  • 博客积分: 2536
  • 博客等级: 少校
  • 技术积分: 783
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-14 15:19
文章分类

全部博文(107)

文章存档

2017年(11)

2016年(8)

2015年(14)

2014年(32)

2012年(1)

2011年(1)

2010年(7)

2009年(33)

我的朋友

分类: 嵌入式

2010-06-02 16:07:38

图形用户接口---MiniGUI在ECOS上的移植

[size=2]有了操作系统、TCP/IP协议栈、文件系统,再加上GUI就比较全面了。本节讲述MiniGUI在ecos上的移植。

MiniGUI是一款开源的GUI中间件,它将鼠标、键盘等设备驱动抽象为输入抽象层IAL引擎,将各种显示设备驱动抽象成图形抽象层GAL引擎,用户基于MiniGUI接口开发的程序可以跨平台使用。本来,最新版本的MiniGUI已经支持ecos了,但我使用的是MiniGUI学习版软件(MiniGUI-STR),它是MiniGUI的精简版本,只支持Linux和uClinux操作系统,此外还缺少许多高级特性。我用的开发板是SMARTARM2200,LCD驱动可以直接拿来使用,但我要玩挖雷,需要自己写鼠标和键盘驱动,为此,在移植上下了一番功夫。
   
MiniGUI属于中间件,它屏蔽了各种操作系统平台的差异,目前可以在Linux、uClinux、ecos、VxWorks、ThreadX、uC/OS-II等操作系统上运行,可以配置成三种运行模式:

1、MiniGUI-Threads  程序可以在不同线程中建立多个窗口,但所有窗口在同一个地址空间中运行。ecos、uC/OS-II、VxWorks就适合使用这种模式,根据MiniGUI作者的实际应用经验,ecos操作系统在一定程度上可以用来替代传统实时嵌入式操作系统。
   
2、MiniGUI-Lite  C/S结构,每个程序是单独的进程,每个进程也可以建立多个窗口,适合于具有完整UNIX特性的嵌入式操作系统,例如:Linux。MiniGUI作者特别指出,要清楚嵌入式Linux/uClinux的方案并不是万能的。由于Linux/uClinux在实时性等方面的缺陷,使得它还不能用来开发对实时性、性能、成本等因素非常敏感的嵌入式产品。
   
3、MiniGUI-Standlone  不需要多线程/多进程的支持,独立运行,有些操作系统,例如uClinux,因某种原因缺少线程库支持,或者发现其线程库存在缺陷时适用这种模式。(MiniGUI作者就为uClinux的库缺陷头疼不已,某些调用就是不能正确运行,没办法,想出这么一招解决问题,呵呵。)
   
现在,我们已经知道ecos使用MiniGUI-Threads运行模式,下面就可以动手移植了,不过在移植前很有必要了解一下MiniGUI的工程组织方式。MiniGUI工程(MiniGUI库本身及示例程序包)是通过GNU的Automake/Autoconf脚本组织的。现在的各种自由软件,如:Apache、MySQL等都是利用Automake/Autoconf实现自动配置和编译的。用户只需要./configure、make、install这三条命令就可以把程序或函数库编译并安装到系统中。其中,configure是自包含的,也就是说用户不需要安装Automake/Autoconf环境就可以直接运行,就象用rar生成的自解压文件解压时不需要rar软件一样。configure是用脚本语言写的,可以独立运行,只有开发者生成configure文件时才需要Automake/Autoconf环境。
   
也许上面的论述令你感到复杂,其实核心思想就是要得到各个目录下的Makefile文件和一个config.h配置头文件。Makefile文件描述了各个文件之间的依赖关系、编译规则、编译选项和配置参数。config.h使用宏定义的方法给出了具体的配置参数。知道这么多足够了,就是这么简单,如果你对工程组织方式不感兴趣,现在就可以跳过这一段。因为MiniGUI要运行在各种平台上,所以不可能写一个固定的Makefile和配置文件,为了能自动探测平台环境,自动生成Makefile和config.h,需要编写configure脚本,但是手工写configure脚本太累了,有人就发明了自动生成工具Autoconf。

使用者只要书写config.h.in和Makefile.in就可以自动生成configure脚本,工作量减轻了不少。但是手工写.in文件还是嫌累,那么可以用Autoscan从源文件中抽取与函数调用和头文件有关的信息,生成configure.scan,以此为框架手写configure.in,避免疏漏,然后用Autoheader读入configure.in生成config.h.in。编写Makefile.am,使用Automake生成Makefile.in。通过这么一系列的自动化过程,开发人员只要写很少的代码就可以生成复杂的Makefile和自动化配置软件。综上,复杂化的原因是软件自动化配置引起的,好在我们只是针对SMARTARM2200板子上的ecos做MiniGUI移植,环境是固定的,第一次configure配置生成Makefile和config.h后只需关心这几个文件就行了。
   
首先,我们要准备ecos库,选择net模板(其支持posix兼容层),添加ROMFS和RAMFS包,为后面的编译工作准备*.h文件。从学习版光盘中拷贝或者从[url=][/url]网站下载以下文件:

        libminigui-str-1.6.2.tar    源程序库
        minigui-res-str-1.6.tar     资源文件:图标、光标、BMP图片、字体库、输入法
        mg-samples-str-1.6.2.tar    示例程序
        mde-str-1.6.2.tar           小游戏:挖雷等
   
将以上文件解压缩到同一个目录下,如:/t。修改各个configure配置选项,为了避免每次重复输入,可以把命令写入build文件。
   
#!/bin/sh
rm config.cache config.status -f
ECOS_DIR=/tmp/untitled_install
CC=arm-elf-gcc \
CFLAGS="-g -D__ecos__ -DEMBED -I ${ECOS_DIR}/include -I /tmp/minigui_lib/include" \
LDFLAGS="-L ${ECOS_DIR}/lib -Ttarget.ld -nostdlib -L /tmp/minigui_lib/lib" \
./configure \
    --prefix=/tmp/minigui_lib \
    --build=i386-elf \
    --host=arm-elf \
    --target=arm-elf \
    --with-osname=ecos
  
配置相应的头文件位置、库文件位置、编译前缀等。操作系统选择ecos。然后运行make,根据出错情况修改源文件,主要是头文件没找到,函数不存在等错误。如果头文件不存在就注释掉对应的include,没有getpwuid函数,直接用“/”目录替代,没有random和srandom函数就用下面的方法替代:

    #define  srandom  srand
    #define  random   rand

总之就是调试,然后发现问题逐一解决。没有想象中的复杂,MiniGUI组织得很好,基本上只是一些小改动,或者删除,或者调整配置,本来MiniGUI就支持ecos嘛!
   
然后加入GAL和IAL,刚开始调试程序先把图像显示出来再说,IAL先不移植,直接使用dummy驱动。其实也不用移植,SmartARM板子的LCD驱动已经写好了,拿来就能用。不过不符合ecos规范,还可以进一步优化,基于ecos的线程效率高些,命名规则和移植性好,多少改改吧。
   
为了运行MiniGUI应用程序,我们还需要准备文件系统和运行时配置文件以及资源文件。一般,需要将这些文件存放到ROMFS文件系统里。我们配置的ecos支持romfs,ROMFS文件系统有两种实现方法:1、用程序头文件实现,作成数组放到H文件里,由编译器决定地址;2、用ROM映像实现,使用固定的flash地址。ecos提供了三个ROM文件系统制作工具:

    mk_romfs.exe    将romfs目录转化成BIN
    file2c.tcl      将BIN转化成H文件
    gen             批处理,从目录直接生成H文件
   
先准备好文件目录:

    /etc
          MiniGUI.cfg      MiniGUI运行时配置文件
    /res
          app              MiniGUI应用程序资源
          bmp              BMP图片
          cursor           光标图形
          font             字体库
          icon             图标
          imetab           输入法

res资源文件直接由minigui-res-str-1.6安装,app应用程序资源由用户指定,MiniGUI.cfg中要配置相关项:
   
[system]
# GAL engine
gal_engine=commlcd   使用commlcd的LCD驱动图形引擎
# IAL engine
#ial_engine=dummy    使用dummy输入引擎,即无输入设备
ial_engine=pcsim     使用pcsim键盘鼠标仿真输入引擎
[rawbitmapfonts]     指定字体资源路径
fontfile0=/res/font/8x16-iso8859-1.bin
[varbitmapfonts]
fontfile0=/res/font/Courier-rr-10-15.vbf
[cursorinfo]         指定光标资源路径
cursorpath=/res/cursor/
[iconinfo]           指定图标资源路径
iconpath=/res/icon/
[bitmapinfo]         指定BMP图形资源路径
bitmappath=/res/bmp/
[imeinfo]            指定输入法资源路径
imetabpath=/res/imetab/
[appinfo]            指定应用程序资源路径
apprespath=/res/app

其他没有写出的项使用缺省值或进行类似设置。这样MiniGUI就可以知道各种资源被保存到了什么地方,使用什么输入输出引擎等等信息,此信息是运行时才确定的。
   
    在cygwin中使用$ mk_romfs -v ./romfs minigui.bin将romfs目录制作成ROMFS文件系统映像minigui.bin,
    在redboot中用lo -b 0x81010000 -r -h 192.168.0.1 minigui.bin下载映像到RAM中,
    在redboot中用fis create -b 0x81010000 -l 0x160000 minigui将RAM中的映像烧写到flash中,并命名为minigui,
    用fis list查看到redboot把此映像自动分配到了0x80020000地址。
    在程序中定义CYGNUM_FS_ROM_BASE_ADDRESS为0x80020000,就可以使用这个ROMFS了。
   
如果想用头文件的方式实现,只要用file2c.tcl就可以转换为C头文件,如下:

    sh file2c.tcl minigui.bin miniguifs.h(或者直接用gen从目录生成H文件)
    把这个头文件包含在C应用程序里,并将ROMFS挂装在这个数组上即可。不过这样每次更改目录/文件都要重新编译程序。
   
现在可以编译调试bomb程序了,可以看到液晶屏上显示出挖雷的图片,不过速度比较慢,刷屏的过程看得很清楚,可以看到一列一列摆放地雷的过程,不过这对于了解程序运行过程有好处。
   
图像显示正确后,就可以加入鼠标和键盘驱动了。一种方法是编写USB键盘和USB鼠标驱动;另一种是用PC机串口模拟。两种方法都支持,本讲只介绍后一种,另一个在USB host章节再说。
   
上位机:

    用PC机串口模拟鼠标键盘输入,上位机模拟程序用VC编写,在窗口内移动鼠标、按下/抬起按键或者有键盘输入时,模拟程序会从串口发送数据,格式为:

    鼠标:    1LMRxxyy   0xxxxxxx  0yyyyyyy
    键盘:    11111111   0000000k  0kkkkkkk
   
因为屏幕是240*320大小,所以用9位数就可以表示x、y坐标,L、M、R分别表示左中右按键情况,对应位为1表示按下,为0表示抬起,第一字节最高位为1,其他字节最高位为0,以便识别开始。键值用8位表示,第一字节为0xFF。

    为了防止鼠标移出窗口,使用ClipCursor(&Rect)将鼠标限制在窗口内。
    在CMainFrame::PreCreateWindow内修改窗口属性,使其显示240*320大小。
    在OnLButtonDown/OnLButtonUp/OnRButtonDown/OnRButtonUp/OnMouseMove内记录鼠标位置和鼠标按键状态。
    在OnCreate内打开串口,设置波特率等属性,创建一个50ms定时器。
    在OnChar里判断输入键值。
    在OnTimer里定时向串口发送经过编码的鼠标和/或键盘信息。
   
下位机:

MiniGUI等待鼠标键盘事件(中断),当发生事件时更新坐标值和/或读入键值。在ecos中使用select原语提供多个事件同时等待,select支持阻塞等待,等待期间不浪费系统资源。read原语使用非阻塞调用方式(non-blocking),因此ecos配置时要选:

    serial device drivers\
    support non-blocking read and write calls

注意:因为占用了串口0,所以printf在后面就不能使用了,超级中端也要关闭,以免冲突。使用open ("/dev/ser0", O_RDONLY|O_NONBLOCK)打开串口,read读串口,select等待事件,解码出x、y坐标,LMR状态和键盘键值,就能够实现MiniGUI输入引擎。因为窗口大小是240*320的,而且鼠标被锁定在窗口内,所以,可以不用看PC屏幕,直接参照LCD屏幕鼠标指针位置移动鼠标/键盘输入,实验证明,鼠标指针的反映是及时的,只是在初始化时有比较明显的延时。

执行示例程序painter,可以用鼠标画线,反映稍微有一点延迟,换个高速CPU就能解决问题。
   
所有的C文件都能编译通过后,就可以开始加到ecos组件仓库里了。去掉所有多余文件,只保留源文件、Makefile文件、config.h头文件,做个简单的CDL脚本,一个minigui模板,就可以开始编译库了。这样,MiniGUI就成了我们系统的一个组件,用的时候只要配置裁减一下就可以了,再也不必关心编译问题了。
   
MiniGUI模仿了Windows的消息驱动机制,对于理解Windows工作原理很有好处。MiniGUI的体积在嵌入式里有点偏大(有点偏向桌面系统的迹象),但经过裁减和在ecos上的移植,还是实用的轻量级GUI。加上BUG的不断减少,更多软件的加入(如浏览器等),MiniGUI还是值得使用的。[/size]
阅读(2237) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~