CFE文件内嵌bmp图像并显示

来源:互联网 发布:webmethod 返回json 编辑:程序博客网 时间:2024/04/30 06:33

1. CFE中的splash

CFE启动后,初始化各种设备,然后初始化显示相关的寄存器,从flash中读取图片splash.bmp并绘制到surface memory区域。

由于splash存放在flash的分区中,所以必须要等待flash驱动完成初始化后,读取出图像splash.bmp才能显示。

那如果想CFE一启动就显示splash呢?显然最好是将splash.bmp嵌入到代码中。

本文基于机顶盒上使用的CFE v15.2版本将splash.bmp编译嵌入到cfe.bin中,并在启动时显示图像。

2. 生成可连接的目标文件splash.bmp.o

GNU binutilsobjcopy工具用途比较广泛,其中一项就是各种目标文件之间的转换。
因此使用objcopy可以将任意文件转换为可以连接的目标文件,参与生成最终的可以执行文件。

2.1 sde-objcopy

CFE编译使用MIPS提供的工具套件MIPS SDE v5.03,这是一个相当老的工具套件了,gcc版本只有2.96objcopy版本为2.9,如下:

ygu@ubuntu:/opt/cfe_v15.2$ sde-gcc -vReading specs from /opt/toolchains/sde-v5.03/bin/../lib/gcc-lib/sde/2.96-mipssde-031117/specsgcc version 2.96-mipssde-031117ygu@ubuntu:/opt/cfe_v15.2$ sde-objcopy -VGNU objcopy 2.9-mipssde-031003Copyright 1997, 98, 99, 2000 Free Software Foundation, Inc.This program is free software; you may redistribute it under the terms ofthe GNU General Public License.  This program has absolutely no warranty.

对于sde-objcopy甚至还不支持-B选项,我曾经尝试用sde-objcopy去转换splash.bmp,但最终都失败了。最后手动用编译应用的mipsel-linux-objcopysplash.bmp转换为可连接的目标文件splash.bmp.o后,再将这个可连接文件用于最终CFE的生成。

2.2 使用mipsel-linux-objcopy工具进行转换

2.2.1 -B mipsisa32选项

转换命令如下(此处使用的是stbgcc-4.5.4-2.9包中的objcopy):

ygu@ubuntu:/opt/cfe_v15.2$ mipsel-linux-objcopy -I binary -O elf32-tradlittlemips -B mipsisa32 splash.bmp splash.bmp.o

file命令查看生成的可连接文件:

ygu@ubuntu:/opt/cfe_v15.2$ file splash.bmp.o splash.bmp.o: ELF 32-bit LSB  relocatable, MIPS, MIPS32 version 1 (SYSV), not stripped

再用file查看下cfe编译生成的其它文件,如cfe_main.o

ygu@ubuntu:/opt/cfe_v15.2/build/7584$ file cfe_main.ocfe_main.o: ELF 32-bit LSB  relocatable, MIPS, MIPS32 version 1 (SYSV), not stripped

可见手动生成的splash.bmp.ocfe_main.o格式是一致的。

2.2.2 -B mips选项

如果objcopy使用-B mips而不是-B mipsisa32选项进行转换,则由于指定cpu架构不一致而存在问题。

ygu@ubuntu:/opt/cfe_v15.2$ mipsel-linux-objcopy -I binary -O elf32-tradlittlemips -B mips splash.bmp splash.bmp.oygu@ubuntu:/opt/cfe_v15.2$ file splash.bmp.o splash.bmp.o: ELF 32-bit LSB  relocatable, MIPS, MIPS-I version 1 (SYSV), not stripped

仔细查看file命令的输出,这里生成的是MIPS-I version 1的格式,跟CFE原生编译生成的格式不一样。

2.3 使用nm工具检查符号

使用objcopy工具生成的可连接文件objfile会内置三个位置相关的符号变量_binary_objfile_start, _binary_objfile_end_binary_objfile_size,可以用nm工具查看。

这里使用mipsel-linux-nm检查生成文件splash.bmp.o中的符号:

ygu@ubuntu:/opt/cfe_v15.2$ mipsel-linux-nm -a splash.bmp.o  00000000 d .data0006b892 D _binary_splash_bmp_end0006b892 A _binary_splash_bmp_size00000000 D _binary_splash_bmp_start

可见生成了三个符号变量,名字也很直观:
+ _binary_splash_bmp_start指示bmp数据开始的位置
+ _binary_splash_bmp_end指示bmp数据结束的位置
+ _binary_splash_bmp_size指示bmp数据的大小

3. CFE链接splash.bmp.o

将生成的splash.bmp.o放到splash目录下,然后在编译系统中添加对splash.bmp.o的编译引用:

3.1 链接splash.bmp.o生成ssbl

cfe_link.mk文件中修改ssbl的生成规则,让其链接splash.bmp.o:

ssbl ssbl.bin:  $(DEV_OBJS) $(COMMON_OBJS) $(ECM_OBJS) $(LIBCFE) splash.bmp.o    $(GLD) -o ssbl -Map ssbl.map $(SSBL_LDFLAGS) -L.  $(DEV_OBJS) $(COMMON_OBJS) $(ECM_OBJS) splash.bmp.o -lcfe  $(LDLIBS)

3.2 复制splash.bmp.o到编译目录

3.1节中指定的splash.bmp.o默认的位置在build/7xxx下,即跟编译生成的文件在同一个地方,但我们预先生成了splash.bmp.o,所以还需要添加规则将splash.bmp.osplash目录复制到当前目录来。
cfe.mk中添加这个规则:

# copy splash/splash.bmp.o to build dirsplash.bmp.o : ../../splash/splash.bmp.o    @echo 'copy $(notdir $<)'    @cp -rf $< $@

添加以上两个规则后,就可以顺利将splash.bmp.o嵌入到生成的cfe.bin中了。

3.3 编译时生成`splash.bmp.o

如果预先设置了mipsel-linux-objcopy的路径也可以在编译时才生成splash.bmp.o,则cfe.mk中生成splash.bmp.o的规则如下:

splash.bmp.o : splash.bmp   @echo 'mipsel-linux-objcopy $(notdir $<)'   @mipsel-linux-objcopy -I binary -O elf32-tradlittlemips -B mipsisa32 $^ $@

4. CFE中引用splash.bmp.o的数据

默认情况下,CFEcfe_splash函数会先从flash中读取图片,然后再显示。
这里我们对这个函数稍作修改,使其直接显示cfe.bin中内嵌的图片,修改如下:
(cfe_main.c中的cfe_splash函数)

/* 声明splash.bmp.o中的位置相关的外部变量 */extern unsigned long _binary_splash_bmp_start;extern unsigned long _binary_splash_bmp_end;extern unsigned long _binary_splash_bmp_size;void cfe_splash(){    BMP_HEADER_INFO bmpinfo[2];    int x,y;    void *surfaceMemory[2];    void *bmpMemory[2];    int ii;    /* PORT POINT: if you have more than 2 surfaces */    surfaceMemory[0] = (void *)PHYS_TO_K0(SURFACE_MEM_ADDRS);    surfaceMemory[1] = (void *)PHYS_TO_K0(SURFACE_MEM_ADDRS_1);    /* 直接引用bmp数据的起始地址 */    bmpMemory[0] = (void *)&_binary_splash_bmp_start;;    bmpMemory[1] = (void *)&_binary_splash_bmp_start;;    for(ii=0; ii<g_ulNumSurface; ii++)    {        /* 解析bmp头部结构,获取bmp图片信息 */        if(splash_bmp_getinfo(bmpMemory[ii], &bmpinfo[ii]) != 0 ||            bmpinfo[ii].header.size > SPLASH_IMAGE_SIZE ||            bmpinfo[ii].header.offset > SPLASH_HDR_SIZE)        {            if (ii == 0)            {                xprintf("No valid image found in " SPLASH_IMAGE_FILE " - disabling splash\n");                return ;            }            else            {                bmpinfo[ii] = bmpinfo[0];            }        }        /* 输出bmp的一些调试信息 */        xprintf("Found splash image %d - Width = %d Height = %d at: [0x%08x - 0x%08x, %d bytes]\n",                ii, bmpinfo[ii].info.width, bmpinfo[ii].info.height,                (unsigned long *)&_binary_splash_bmp_start,                (unsigned long *)&_binary_splash_bmp_end,                (unsigned long)&_binary_splash_bmp_size);#ifdef SPLASH_SURFACE_SELECT_ENABLED        surfaceMemory[ii] = g_pvSplashSurfaceAddr[ii];#endif        BMEM_ConvertAddressToOffset(NULL, surfaceMemory[ii], &g_SplashInfo.aulSurfaceBufOffset[ii]);    }    splash_bvn_init(NULL, &g_SplashInfo);    /* 以下部分没有修改,同原函数 */    ...}

修改后编译生成cfe.bin,烧写到机顶盒上就可以在开机启动时显示内嵌到cfe里面的图像数据。

5. 其它

不仅可以转换图片数据,objcopy还可以将任何格式的文件转换为可连接的目标文件,如字体、固件等,比较灵活也比较方便。

0 0
原创粉丝点击