最近由于项目需要,要在blackfin 的bf548上运行minigui的图形应用程序。因此将minigui移植到了blackfin的uclinux上。minigui对blackfin的支持并不好,因此移植过程还颇费周折。
首先上minigui的官方网站 http://www.minigui.org/res.shtml 上下载最新的GPL版本 1.6.10,需要的文件如下:
Package | Description | Download |
---|---|---|
libminigui-1.6.10.tar.gz | This is source code tarball of MiniGUI V1.6.10. | |
minigui-res-1.6.10.tar.gz | The resource tarball of MiniGUI V1.6.10, it contains the basic fonts, cursors, icons, and bitmaps used by MiniGUI V1.6.10. | |
mg-samples-1.6.10.tar.gz | The samples for MiniGUI V1.6.10. | |
mde-1.6.10.tar.gz | MDE is a demonstration package for MiniGUI V1.6.10. |
1、编译 libminigui-1.6.10
这是minigui的核心,编译过程如下:
CFLAGS=-D__uClinux__/ -D__LITTLE_ENDIAN__/ -I$HOME/devel/blackfin/uClinux-dist-2008R1.5-RC3/staging/usr/include / LDFLAGS=-L$HOME/devel/blackfin/uClinux-dist-2008R1.5-RC3/staging/usr/lib/ -ljpeg/ -lpng/ -lz / CC=/opt/uClinux/bfin-linux-uclibc/bin/bfin-linux-uclibc-gcc / ./configure / --host=i686-pc-linux-gnu / --build=bfin-linux-uclibc / --prefix=/tftpboot/bfin/usr/local / --enable-videofbcon / --with-targetname=bfin / --enable-pngsupport / --enable-jpgsupport / --enable-autoial
说明一下:
2、安装资源文件
将文件 minigui-res-1.6.10.tar.gz 解压出来后make install就可以了,要说明的是如果安装目录不是/usr/local/目录下的话(对于嵌入式系统似乎从来就不应该安装在/usr/loca目录下),就需要修改config.linux文件,将安装目录改正到需要的目录。
3、编译mde-1.6.10
$ tar -zvxf mde-1.6.10.tar.gz $ cd mde-1.6.10 $ CFLAGS=-D__uClinux__/ -D__LITTLE_ENDIAN__/ -I$HOME/devel/blackfin/uClinux-dist-2008R1.5-RC3/staging/usr/include/ -I/tftpboot/bfin/usr/local/include / LDFLAGS=-L$HOME/devel/blackfin/uClinux-dist-2008R1.5-RC3/staging/usr/lib/ -L/tftpboot/bfin/usr/local/lib/ -ljpeg/ -lz / CC=/opt/uClinux/bfin-linux-uclibc/bin/bfin-linux-uclibc-gcc / ./configure / --host=i686-pc-linux-gnu / --build=bfin-linux-uclibc / --prefix=/tftpboot/bfin/usr/local $ make $ make install
OK,编译完成。
3、运行
编译完成后在开发板上运行demo程序,并没有预期的图形用户界面出现,而是出现如下错误:
root:/> /usr/local/bin/bomb Data access misaligned address violation - Attempted misaligned data memory or data cache access. Defered Exception context CURRENT PROCESS: COMM=bomb PID=775 TEXT = 0x03620000-0x036273a8 DATA = 0x031383a8-0x0313e1c8 BSS = 0x0313e1c8-0x036a0000 USER-STACK = 0x036bfe80 return address: [0x030afbce]; contents of: 0x030afba0: 1005 b9f1 0c09 180a 201e b9f0 0c18 180e 0x030afbb0: b9f1 6020 0801 1814 2016 a138 acba 9b10 0x030afbc0: 2012 acba a138 9710 200e acba a138 [9710] 0x030afbd0: a0b8 3210 6c12 a138 4e80 9b10 2004 acba SEQUENCER STATUS: Not tainted SEQSTAT: 00060024 IPEND: 0030 SYSCFG: 0006 HWERRCAUSE: 0x18 EXCAUSE : 0x24 RETE: <0x00000000> /* Maybe null pointer? */ RETN: <0x0364a000> /* unknown address */ RETX: <0x030afbce> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbce ] RETS: <0x030b1960> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb1960 ] PC : <0x030afbce> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbce ] DCPLB_FAULT_ADDR: <0x036be768> [ bomb + 0x1e768 ] ICPLB_FAULT_ADDR: <0x030afbce> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xaf] PROCESSOR STATE: R0 : 00ffffff R1 : 00000003 R2 : 00ffffff R3 : 00000002 R4 : 00000020 R5 : 00000020 R6 : 00000060 R7 : 036cecd0 P0 : 007c1524 P1 : 030b18b8 P2 : 036cecd3 P3 : 03217b68 P4 : 007c3d94 P5 : 00000000 FP : 036be760 SP : 03649f24 LB0: 002a6181 LT0: 002a6174 LC0: 00000000 LB1: 038dcf7b LT1: 038dcf7a LC1: 00000000 B0 : 00000000 L0 : 00000000 M0 : 00000000 I0 : 00000000 B1 : 00000000 L1 : 00000000 M1 : 00000000 I1 : 00000000 B2 : 00000000 L2 : 00000000 M2 : 00000000 I2 : 00000000 B3 : 00000000 L3 : 00000000 M3 : 00000000 I3 : 00000000 A0.w: 00000078 A0.x: 00000000 A1.w: 00000078 A1.x: 00000000 USP : 036be75c ASTAT: 02003025 Hardware Trace: 0 Target : <0x00004944> { _trap_c + 0x0 } Source : <0xffa006ec> { _exception_to_level5 + 0xb4 } 1 Target : <0xffa00638> { _exception_to_level5 + 0x0 } Source : <0xffa00590> { _ex_trap_c + 0x5c } 2 Target : <0xffa00534> { _ex_trap_c + 0x0 } Source : <0xffa0078c> { _trap + 0x28 } 3 Target : <0xffa00764> { _trap + 0x0 } Source : <0x030afbcc> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbcc ] 4 Target : <0x030afbca> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbca ] Source : <0x030afbae> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbae ] 5 Target : <0x030afbaa> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbaa ] Source : <0x030afba0> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafba0 ] 6 Target : <0x030afb88> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafb88 ] Source : <0x030b195c> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb195c ] 7 Target : <0x030b1954> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb1954 ] Source : <0x030b194e> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb194e ] 8 Target : <0x030b1934> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb1934 ] Source : <0x030b1922> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb1922 ] 9 Target : <0x030b191a> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb191a ] Source : <0x030b196e> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb196e ] 10 Target : <0x030b1960> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb1960 ] Source : <0x030afbf0> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbf0 ] 11 Target : <0x030afbe4> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbe4 ] Source : <0x030afbdc> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbdc ] 12 Target : <0x030afbca> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbca ] Source : <0x030afbae> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbae ] 13 Target : <0x030afbaa> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbaa ] Source : <0x030afba0> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafba0 ] 14 Target : <0x030afb88> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafb88 ] Source : <0x030b195c> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb195c ] 15 Target : <0x030b1950> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb1950 ] Source : <0x030b1948> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xb1948 ] Stack from 03649f04: 00000000 ffa006f0 0028256c 0028256c 00282564 04000021 00000000 038cbd14 030afbce 00000030 00060024 00000000 0364a000 030afbce 030afbce 030b1960 00ffffff 02003025 038dcf7b 002a6181 038dcf7a 002a6174 00000000 00000000 00000078 00000000 00000078 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 036be75c 036be760 00000000 007c3d94 Call Trace: Bus error
从错误信息来看是由于未对齐访问内存所导致的。由于 blackfin 不允许未对齐的内存访问,对32位的blackfin bf548来说,未对齐的内存访问包括16位字操作时地址没有按2字对齐,32位的内存操作时没有按4字节对齐,而对于字节访问来说,就对地址没有什么要求。
知道了错误的原因,现在要找到出错的代码所在的行。上面的错误信息给出了出错误时的程序指针PC的值,因此可以根据该值来确定出错代码所在的位置。
错误信息
PC : <0x030afbce> [ /usr/local/lib/libminigui-1.6.so.10.0.0 + 0xafbce ]
指出出错代码位于/usr/local/lib/libminigui-1.6.so.10.0.0的偏移0xafbce处。
使用readelf命令在libminigui-1.6.so.10.0.0中读取符号信息:
[xhs@watsonxu lib]$ readelf -s libminigui-1.6.so.10.0.0 | grep 000afb
1122: 000afbf4 650 FUNC GLOBAL DEFAULT 10 __begin_fill_bitmap
9083: 000afb40 72 FUNC LOCAL DEFAULT 10 _MGUI_ReadLE16Mem
9084: 000afb88 106 FUNC LOCAL DEFAULT 10 __mem_set_pixel
10488: 000afbf4 650 FUNC GLOBAL DEFAULT 10 __begin_fill_bitmap
上面的代码可以看出,出错的代码应该位于 _mem_set_pixel 函数处,找到 _mem_set_pixel 函数的定义处 src/include/dc.h
static inline BYTE* _mem_set_pixel (BYTE* dst, int bpp, Uint32 pixel) { switch (bpp) { case 1: *dst= pixel; break; case 2: *(Uint16 *) dst = pixel; break; case 3: *(Uint16 *) dst = pixel; *(dst + 2) = pixel >> 16; break; case 4: *(Uint32 *) dst = pixel; break; } return dst + bpp; }
由于blackfin BF548-EZKIT开发板使用了24位的LCD显示屏,因此对应于此处的bpp就为3,即
case 3:
*(Uint16 *) dst = pixel; //此处使用了16位的内存访问,并导致了内存访问未对齐。
*(dst + 2) = pixel >> 16;
break;
很明显,按照24位显存的组织方式,dst这个地址是可能出现未对齐到16位字的。
找到了问题的所在,解决起来相对就容易了,将16位的内存访问改成两个8位的内存访问就可以了。修正如下:
case 3:
*dst = pixel & 0xFF;
*(dst + 1) = pixel >> 8;
*(dst + 2) = pixel >> 16;
break;
重新编译,运行,还有多处类似的错误出现,同样的方法全部改正后运行,终于出现了预期的图形用户界面了。
此外,在输入法模块中也有未对齐的内存访问,主要是在读文件时有未对齐的内存访问,暂时禁用输入法模块解决,留待以后解决。