首先说明一下我的开发平台,我用的是Samsung S3C44B0X芯片的开发板,已经移植好的uClinux操作系统和FrameBuffer驱动。我的uClinux安装在"/s3c44b0fu/uClinux-dist"目录下,交叉编译工具安装在"/usr/local/arm-elf"目录下。
具体步骤:
一. 从网站下载 libminigui-1.3.3.tar.gz, mde-1.3.0.tar.gz, mg-samples-1.3.0.tar.gz和minigui-res-1.3.3.tar.gz四个压缩文件,并将这四个文件保存到交叉编译环境的目录下,因为我的arm-elf-gcc交叉编译工具安装在"/usr/local/arm-elf"目录下,所以将minigui的四个压缩包同样拷贝到"/usr/local/arm-elf"目录下.
二. 在终端中输入"cd /usr/local/arm-elf",进入minigui的四个压缩文件所在目录,然后分别执行"tar zxvf xxxxx.tar.gz"将这四个压缩包解压缩.解压后生成libminigui-1.3.3, mde-1.3.0, mg-samples-1.3.0和minigui-res-1.3.3四个文件夹.
三. 1) 进入minigui-res-1.3.3文件夹内,修改config.linux,在prefix = $(TOPDIR)/usr/local/后添加我们的交叉编译安装目录arm-elf,即prefix = $(TOPDIR)/usr/local/arm-elf.
2) cd minigui-res-1.3.3
3) make install
四. cd mde-1.3.0
./configure
make
cd mg-samples-1.3.0
./configure
make
五. 1) 编写交叉编译minigui函数库的配置脚本domain.sh.
domain.sh的具体内容为:
#!/bin/sh
rm config.cache config.status -f
CC=arm-elf-gcc /
CFLAGS="-I/s3c44b0fu/uClinux-dist/uClibc/include -Dlinux -D__linux__ -D__uClinux__ -Dunix " /
LDFLAGS="-Wl,-elf2flt -static -Wl,-move-rodata -Wl,-L/s3c44b0fu/uClinux-dist/lib/uClibc/lib -Wl,-L/s3c44b0fu/uClinux-dist/linux-2.4.x/lib -Wl,-lc -Wl,-lm" /
./configure --prefix=/usr/local/arm-elf /
--build=i686-pc-linux-gnu /
--host=arm-elf-linux /
--target=arm-elf-linux /
--disable-shared /
--disable-lite /
--disable-standalone /
--enable-incoreres /
--disable-flatstyle /
--enable-newgal /
--disable-nativegal /
--disable-galcommlcd /
--enable-galfbcon /
--enable-adsial /
--disable-micemoveable /
--disable-cursor /
--disable-fblin1r /
--enable-fblin8 /
--disable-fblin16 /
--disable-fblin32 /
--disable-textmode /
--enable-dummyial /
--disable-mc68x328ial /
--disable-nativeial /
--disable-qvfbial /
--disable-qpfsupport /
--disable-ttfsupport /
--disable-type1support /
--disable-latin9support /
--disable-gbksupport /
--disable-big5support /
--disable-unicodesupport /
--disable-savebitmap /
--disable-imegb2312 /
--disable-imegb2312py /
--disable-aboutdlg /
--disable-savescreen /
--disable-grayscreen /
--enable-tinyscreen /
--enable-video-fbcon /
--disable-video-qvfb /
--disable-nativegalqvfb /
--with-osname=uclinux
编写好后拷贝到libminigui-1.3.3下.
2) cd libminigui-1.3.3
3) sh domain.sh
4) make
5) make install
6) ldconfig
上面六步即完成了用arm-elf-gcc对minigui的函数库的交叉编译.可以进入/usr/local/arm-elf目录中,你会看到新增加了etc和lib两个文件夹,这两个文件夹就是我们刚才用arm-elf-gcc交叉编译minigui的函数库所产生的结果,以后编译在目标板中运行的应用程序时,就会对这两个文件夹里的内容进行编译,从而产生适合于在arm开发板中运行的应用程序.
六. 编写测试minigui的应用程序
1) 测试程序miniguidemo.c其实就是从mg-samples-1.3.0中拷贝过来的helloworld.c程序,不过要根据具体的LCD做一点修改,如我的LCD是640x480的256色STN彩色屏,所以要将
#ifdef _LITE_VERSION
SetDesktopRect(0, 0, 1024, 768);
#endif
修改为:
#ifdef _LITE_VERSION
SetDesktopRect(0, 0, 640, 480);
#endif
根据你的不同的LCD修改这个参数,还可以修改这个窗体显示的位置,根据你的喜好修改即可.最后将编写好的miniguidemo.c保存到/s3c44b0fu/uClinux-dist/user/guidemo中(注:guidemo是我在user目录中新建的文件夹)
2) 在/s3c44b0fu/uClinux-dist/user/guidemo中编写Makefile文件,具体内容为:
EXEC = miniguidemo
OBJS = miniguidemo.o
LDFLAGS=-L/s3c44b0fu/uClinux-dist/uClibc/lib
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) -lminigui -lmgext $(LIBPTHREAD) $(LIBM) $(LDLIBS) -elf2flt
romfs:
$(ROMFSINST) /bin/$(EXEC)
clean:
-rm -f $(EXEC) *.elf *.gdb *.o
3) 修改user/Makefile
为了让编译器编译上述添加的内容,在user/Makefile中添加一句(一般按照字母排列):
dir _$(CONFIG_USER_GUIDEMO_MINIGUIDEMO) +=guidemo
4) 修改config/config.in
config/config.in文件中添加的内容会在对用户选项进行配置时反映出来。在文件的最后,增加一条:
###################################################################
mainmenu_option next_comment
comment 'My MINIGUI Application'
bool 'demo' CONFIG_USER_GUIDEMO_MINIGUIDEMO
endmenu
###################################################################
七. 现在可以编译minigui的应用程序了,这里罗嗦一点,minigui应用程序的编写有两种方法,一种是将应用程序添加到uClinux-dist目录中,在uClinux-dist编译和链接,直至生成最后的映象文件;第二种方法是先单独编译minigui的应用程序,生成可执行文件,然后放到uClinux-dist的romfs目录中,执行make image命令生成映象文件.很显然这里采用的是第一种方法, 也正因为采用的是第一种方法,所以第五步中交叉编译得到的配置文件MiniGUI.cfg实际上在这里没有用处;第二种方法我尝试过,似乎有点问题,你可以尝试尝试.
编译步骤:
make mrproper
make menuconfig(记住将FrameBuffer和你的应用程序编译到内核去)
make dep
make lib_only
make user_only
make ronfs
make image
make
将编译生成的映象文件下载到目标板中,执行程序,出现错误
/bin> helloworld
No available video device.
NEWGAL: Does not find matched engine: qvfb.
GDI: Can not get graphics engine information!
InitGUI failure when using incore resource.
pid 30: failed 256
这个错误恰好和61IC工程师社区中的“风雨”写的一篇文章完全一样!所以我就按照他的步骤一步一步的修改,网址是 http://www.61ic.com/club/bbs/dispbbs.asp?boardID=26&ID=691&page=1
具体修改步骤是:
经过跟踪,进入sysres/mgedt.c
#include "common.h"
typedef struct _ETCSECTION
{
int key_nr; /* key number in the section */
char *name; /* name of the section */
char **keys; /* key string arrays */
char **values; /* value string arrays */
} ETCSECTION;
typedef ETCSECTION* PETCSECTION;
typedef struct _ETC_S
{
int section_nr; /* number of sections */
PETCSECTION sections; /* pointer to section arrays */
} ETC_S;
#ifdef _INCORE_RES
static char *SYSTEM_KEYS[] = {"gal_engine", "ial_engine", "mdev", "mtype"};
#ifdef __ECOS
static char *SYSTEM_valueS[] = {"ecoslcd", "ipaq", "/dev/ts", "none"};
#else
//static char *SYSTEM_valueS[] = {"qvfb", "qvfb", "/dev/ts", "none"}; //这是我注释掉的原来的, 你们看看程序结构,不管我怎么配置NEWGAL,
//这里都将不可避免的进入QVFB
static char *SYSTEM_valueS[] = {"fbcon", "dummy", "none", "none"}; //我新加的。
#endif
static char *FBCON_KEYS[] = {"defaultmode"};
static char *FBCON_valueS[] = {"640x480-8bpp"}; //原来的是240X320-16bpp
static char *QVFB_KEYS[] = {"defaultmode", "display"};
static char *QVFB_valueS[] = {"640x480-16bpp", "0"};
static char *SYSTEMFONT_KEYS[] =
{"font_number", "font0", "font1", "font2", "default", "wchar_def", "fixed", "caption", "menu", "control"};
static char *SYSTEMFONT_valueS[] =
{
"3","rbf-fixed-rrncnn-6-12-ISO8859-1", "*-fixed-rrncnn-*-12-GB2312", "*-SansSerif-rrncnn-*-12-GB2312",
"0", "1", "1", "1", "1", "1"
};
static char *CURSORINFO_KEYS[] = {"cursornumber"};
static char *CURSORINFO_valueS[] = {"2"};
static char *ICONINFO_KEYS[] = {"iconnumber"};
static char *ICONINFO_valueS[] = {"5"};
static char *BITMAPINFO_KEYS[] = {"bitmapnumber"};
static char *BITMAPINFO_valueS[] = {"3"};
/*
static char *BGPICTURE_KEYS[] = {"position"};
static char *BGPICTURE_valueS[] = {"center"};
static char *MOUSE_KEYS[] = {"dblclicktime"};
static char *MOUSE_valueS[] = {"300"};
static char *EVENT_KEYS[] = {"timeoutusec", "repeatusec"};
static char *EVENT_valueS[] = {"300000", "50000"};
*/
static ETCSECTION mgetc_sections [] =
{
{4, "system", SYSTEM_KEYS, SYSTEM_valueS},
{1, "fbcon", FBCON_KEYS, FBCON_valueS},
{2, "qvfb", QVFB_KEYS, QVFB_valueS},
{10,"systemfont", SYSTEMFONT_KEYS, SYSTEMFONT_valueS},
{1, "cursorinfo", CURSORINFO_KEYS, CURSORINFO_valueS},
{1, "iconinfo", ICONINFO_KEYS, ICONINFO_valueS},
{1, "bitmapinfo", BITMAPINFO_KEYS, BITMAPINFO_valueS},
/* optional sections */
/*
{1, "bgpicture", BGPICTURE_KEYS, BGPICTURE_valueS},
{1, "mouse", MOUSE_KEYS, MOUSE_valueS},
{2, "event", EVENT_KEYS, EVENT_valueS},
*/
};
ETC_S MGETC = { 7, mgetc_sections };
#endif /* _INCORE_RES */
修改后编译并运行。仍然提示错误。
/bin> helloworld
MAP_SHARED not supported (cannot write mappings to disk) //这条一看就知道在MMAP使用了不适合uClibc库的参数, 此项应该设置为0
NEWGAL: Does not find matched engine: fbcon. GDI: Can not get graphics engine information!
InitGUI failure when using incore resource.
Unable to memory map the video hardwarepid 30: failed 256
后来经过跟踪。在/libminigui-1.3.3/src/newgal/fbcon/fbvideo中找到OPEN及MMAP引用。
将mapped_mem = mmap(NULL, mapped_memlen,
PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0);
改为
#ifdef __uClinux__
mapped_mem = mmap(NULL, mapped_memlen,
PROT_READ|PROT_WRITE, 0, console_fd, 0);
#else
mapped_mem = mmap(NULL, mapped_memlen,
PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0);
#endif
将mapped_io = mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE,
MAP_SHARED, console_fd, mapped_memlen);
改为
#ifdef __uClinux__
mapped_io = mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE,
0, console_fd, mapped_memlen);
#else
mapped_io = mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE,
MAP_SHARED, console_fd, mapped_memlen);
#endif
编译后运行。发现出现代码崩溃,
/bin/helloworld
Unhandled fault: external abort on linefetch (F4) at 0x00000001
fault-common.c(97): start_code=0xcd00040, start_stack=0xcdfff84)
pid 32: failed 7
经过艰苦的跟踪分析。在/home/libminigui-1.3.3/src/kernel/desktop.c中。
将if (!InitSystemRes ()) {
fprintf (stderr, "DESKTOP: Can not initialize system resource!/n");
return FALSE;
}注释掉。
编译运行。 显示OK,终于可以显示出Helloworld的窗体,至此,全部移植完成,可以发挥自己的想象力,编写漂亮的GUI界面程序了!