• RK3568 kernel阶段播放开机动画方案实现



    方案介绍

    基于 RK3568 在 kernel 阶段显示开机 logo 动画,本质原理是将 logo 图片采用刷新的方式演示成为开机动画的效果。kernel 版本采用 4.19 版本(5.10 同样适用)。

    本文将首先描述如何将一张自定义的图片修改添加到 kernel 中称为 kernel 的开机动画(该方式将不仅仅是在 kernel 路径下替换 logo.bmp 这么简单)。本文主要内容如下:

    • kernel 层开机 logo 显示
    • 修改代码,实现开机动画效果
    • 基于 RK3568 SDK 下配置增加 logo 图片资源分区,实现后期简单可替换的 logo 开机动画方式

    kernel 层开机 logo 显示

    这里采用 Linux kernel 自身设定的开机 logo 方式,所以 logo 的文件名为 logo_linux_clut224.ppm,该文件一般会存放在 kernel/drivers/video/logo/ 路径下。采用 netpbm 工具生成想要替换的 logo(注意图片的尺寸大小,参考显示屏幕的尺寸)。

    1. logo 格式转换(Linux 只支持 ppm 格式的图片,需要将 png / bmp 格式转换成 ppm)
    # png 格式
    pngtopnm logo.png > logo.pnm
    # bmp 格式
    bmptopnm logo.bmp > logo.pnm
    # 下面步骤一致
    pnmquant 224 logo.pnm > logo224.pnm
    pnmtoplainpnm logo224.pnm > logo_linux_clut224.ppm
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    以上转换完成后,将生成的 logo_linux_clut224.ppm 放入 kernel/drivers/video/logo/ 路径下(会替换原有的 logo_linux_clut224.ppm),在编译时会生成对应的 .c 文件和 .o 文件,可能会出现如下错误:

    kernel/drivers/video/logo/logo_linux_clut224.ppm: Binary PNM is not supported
    Use pnmnoraw(1) to convert it to ASCII PNM
    
    • 1
    • 2

    以上错误是因为 ppm 图片是 bin 格式,需要转换成 ASCII 格式,方法如下:

    pnmnoraw logo_linux_no_ascii_clut224.ppm > logo_linux_clut224.ppm
    
    • 1

    替换目录中的文件重新编译即可。

    1. 调整显示位置
      默认是左上角对齐,调整为中心对齐的方法如下:
      修改 drivers/video/fbmem.c 文件的 fb_show_logo_line() 函数:
      在这里插入图片描述
      修改其中画住位置的代码如下:
    image.dx = (info->var.xres / 2) - (image.width / 2); //中心
    image.dy =  (info->var.yres / 2) - (image.height/ 2); //中心
    image.width = logo->width;
    image.height = logo->height;
    
    • 1
    • 2
    • 3
    • 4

    注意:info->var.xresinfo->var.yres 是分辨率大小,image.widthimage.height 是 logo 图片的大小。

    图片显示起点位置修改,修改 drivers/video/console/fbcon.c 文件的 fbcon_prepare_logo() 函数:
    在这里插入图片描述根据图片大小修改起点位置如下:

    logo_height = fb_prepare_logo(info, ops->rotate);
    logo_height += (info->var.yres / 2) - (logo_height / 2);
    
    • 1
    • 2
    1. 配置 kernel config ,启用 kernel logo:
    Device Drivers--->
    	Graphics support--->
    		[*]Boot logo--->
    			[*]Standard 224-color Linux logo
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述需要添加支持 kernel console,不选会看不到 logo:

    Device Drivers--->
    	Graphics support--->
    		Console display driver support--->
    			<*>Framebuffer Console support
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述全屏显示时,屏幕左上角会有光标闪烁的问题,解决方法如下:
    修改 drivers/video/fbdev/core/bitblit.c 中的 bit_cursor() 函数:
    在这里插入图片描述
    将这个判断注释掉,或者将 err 改为 0, 如下:
    在这里插入图片描述


    修改代码,实现开机动画效果

    通过分析代码,可以发现显示 logo 的位置在 drivers/video/fbdev/core/fbcon.c 文件中的 fbcon_switch() 函数中,具体位置如下:

    在这里插入图片描述可以看到其中的 fb_show_logo() 函数,进入这个函数,位置在 drivers/video/fbdev/core/fbmem.c ,代码如下:
    在这里插入图片描述通过以上函数可以发现,显示 logo 资源数据来自 fb_logo.logo,在这里,我们只需要修改 fb_logo.logo 资源就可以实现动态的 logo 显示。

    通过查找代码,发现加载 logo 资源的代码来自于 drivers/video/fbdev/core/fbcon.c 文件的 fbcon_prepare_logo() 函数中,参考流程如下:

    fbcon_prepare_logo()
    	--->fb_prepare_logo()
    		--->fb_find_logo() [这个函数位于 drivers/video/logo/logo.c 中]
    
    • 1
    • 2
    • 3

    通过上面的代码执行流程可以得到 fb_logo.logo 资源。所以,如果想要实现动态 logo 显示,只需要使用多个 logo 资源来循环显示就可以实现动画效果。因此,我们可以循环调用 fb_find_logo() 来实现。问题来了,现在我们 fb_find_logo(int depth) 的参数是 depth 这个值,本身 kernel 查找 logo 资源是通过这个值来找到不同颜色深度的图片资源,通常系统中使用 depth 这个值只会用到低 16 位,我们可以使用这个 depth 参数的高 16 位用于传递动态显示图片的图片序号值。

    drivers/video/logo/logo.c 文件中的 fb_find_logo() 函数修改如下:
    在这里插入图片描述可以看出,通过提取 depth 的高 16 位作为 num 来标识图片序号。至于后面的 logo 数据,参考这里的 logo_linux_clut224(上一章内容中添加 logo 资源的方式进行添加)。

    注意:编译配置为:Standard 224-color Linux logo 时,logo 资源数据文件一定要以 _clut224.ppm 结尾,否则 Makefile 识别不到,具体内容可以参考 drivers/video/logo/ 路径下的 Makefile 文件中关于 ppm 文件的编译规则:
    在这里插入图片描述
    到这里,我们就可以编写函数来实现循环获取 logo 资源用于动画显示了。这里我们不修改 fbcon_prepare_logo() 函数,重新实现一个获取 logo 资源的 fb_get_logo() 函数,这是因为在 fbcon_prepare_logo() 中有很多操作是不需要我们去修改的,所以仅仅在 fb_show_logo 之前更新 fb_logo.logo 资源即可。

    drivers/video/fbdev/core/fbmem.c 文件中添加如下的新函数:
    在这里插入图片描述需要注意我们使用该函数的位置是在 drivers/video/fbdev/core/fbcon.c 中,所以在这里还需要使用 EXPORT_SYMBOL(fb_get_logo); 将这个函数导出,否则编译的时候会提示未定义的引用。

    现在一切就绪,我们就可以做动态显示了。回到 logo 显示的 drivers/video/fbdev/core/fbcon.c 文件中的 fbcon_switch()函数中,做如下修改:

    static int fbcon_switch(struct vc_data *vc)
    {
    	... ...
    	if(logo_shown == FBCON_LOGO_DRAW) {
    		logo_shown = fg_console;
    		/* This is protected above by initmem_freed*/
    		for(i = 0; i <
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    基于NET 6.0 自研轻量级ORM框架
    JSqlParser生成修改表定义SQL语句
    【 java 面向对象之 Object 类】toString() 方法的重写
    基于Jeecgboot前后端分离的平台后端系统采用jenkins发布
    java中的深度复制和浅复制的BUG
    Django工具
    基于MFC和OpenCV实现人脸识别
    PAT乙级-B1011 A+B 和 C(15)
    关于调参技巧的问题
    NonlinearFactorGraph.h/NonlinearFactorGraph.cpp
  • 原文地址:https://blog.csdn.net/qq_37596943/article/details/127976078