CFE文件内嵌bmp图像并显示

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 -v
Reading specs from /opt/toolchains/sde-v5.03/bin/../lib/gcc-lib/sde/2.96-mipssde-031117/specs
gcc version 2.96-mipssde-031117

ygu@ubuntu:/opt/cfe_v15.2$ sde-objcopy -V
GNU objcopy 2.9-mipssde-031003
Copyright 1997, 98, 99, 2000 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the 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.o
cfe_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.o
ygu@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 .data
0006b892 D _binary_splash_bmp_end
0006b892 A _binary_splash_bmp_size
00000000 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 dir
splash.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
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洛奇看世界

一分也是爱~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值