天天看点

在blackfin上移植minigui

最近由于项目需要,要在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.
在blackfin上移植minigui
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.
在blackfin上移植minigui
mg-samples-1.6.10.tar.gz The samples for MiniGUI V1.6.10.
在blackfin上移植minigui
mde-1.6.10.tar.gz MDE is a demonstration package for MiniGUI V1.6.10.
在blackfin上移植minigui

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

说明一下:

  1. 我在Fedora 9上直接编译的时候编译是通不过的,原因是minigui即使是最新的版本,仍然在使用较旧的autoconf / automake套件,因此无法正确的交叉编译blackfin的程序。需要将本机的automake所带的config.sub拷贝到libminigui目录下替换原来的文件。
  2. 还是minigui对blackfin的支持不够好,不能正确识别CPU的大小端。因此需要加上-D__LITTLE_ENDIAN__来显式的指明其为小端,否则在读取资源文件时会出现文件不能正确读取的问题。

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中读取符号信息:

[[email protected] 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;

重新编译,运行,还有多处类似的错误出现,同样的方法全部改正后运行,终于出现了预期的图形用户界面了。

此外,在输入法模块中也有未对齐的内存访问,主要是在读文件时有未对齐的内存访问,暂时禁用输入法模块解决,留待以后解决。