基于荔枝派实现uboot到系统应用启动过程不间断logo显示

效果显示

在这里插入图片描述

原理说明

无论使用哪种芯片, 要实现uboot到系统应用启动过程不间断logo显示, 整个启动过程大概如下:

  • uboot启动
    • 初始化显示屏驱动(这里确定好framebuffer地址)
    • 从mmc(sd卡)读取bmp图片进行显示
    • 打开背光
  • 内核启动
    • 加载显示屏驱动, 取消初始化lcd控制器(时钟等配置), 使用uboot配置好的寄存器; 使用与uboot相同的framebuffer地址, 确保显示相同内容
  • 系统启动
    • 启动自己的qt界面, 刷新屏幕显示
  1. 内核显示屏驱动, 不能重新初始化lcd控制器, 否则会出现屏幕闪烁/黑屏灯情况, uboot已经配置好lcd相关的寄存器并且正常显示了, 使用uboot配置好的就行
  2. 内核framebuffer的地址要指定与uboot相同的地址, 因为uboot已经将图片数据加载到内存进行显示了, 内核使用相同的地址便能显示相同的图片
  3. 由于framebuffer占用的ddr地址是在uboot就决定好了, 所以不能让kernel把framebuffer占用的ddr当成普通的mem处理. 可以用reserved-memory机制预留一段kernel无法使用的内存地址, 也可以将framebuffer设计在ddr的最高位置, 然后通过uboot启动参数传内存大小"mem=..."时相应改小.
  4. 这里说明的只是一种实现方案, 如果芯片支持多图层显示, 可以有不同的实现方法, 这里不细讲

在lichee zero上的实现说明

这次实现基于以下环境实现

开发板荔枝派lichee zero
ubootU-Boot 2017.01-rc2
kernelLinux 4.10.15
文件系统由buildroot制作
QtQt5.9.1

内核修改

显示屏驱动

内核的显示屏驱动使用的是 Simple Framebuffer

源码: linux\arch\arm\boot\dts\sun8i-v3s.dtsi
在这里插入图片描述

内核doc说明如下
在这里插入图片描述

这是一种简单的显示屏驱动方式, lcd控制器相关的配置由firmware(类似于另外一个驱动)或者bootloader进行setup, 对该驱动来说, 只需要维护lcd对于的framebuffer就可以了, 不需要进行lcd控制相关的寄存器配置

对于lichee zero来说, lcd控制器是由uboot进行配置的, 内核显示屏驱动无需改动

fbcon

fbcon实现在内核启动过程中的基于framebuffer的终端显示, 也就是实现显示屏打印出启动的信息, 这个会影响启动logo的显示
lichee zero的内核配置中是强制使能了fbcon的, 无法通过配置关闭fbcon, 只能修改makefile.
不过也可以通过启动参数实现不显示fbcon, 在uboot修改中会讲到.


综上, 内核源码实际上无需改动.

uboot修改

启用splash

uboot提供了splash实现logo的读取与显示, 不过并没有使用到
这里进行修改实现从mmc(sd卡)读取图片显示

  • 添加splash宏

添加以下宏定义, 使能uboot的splash功能

源码: u-boot\include\configs\sun8i.h
在这里插入图片描述

  • 修改uboot默认环境变量, 添加splash参数

修改默认的uboot环境变量, 添加splash相关的环境变量

"splashfile=logo.bmp\0" \
"splashimage=0x41000000\0" \
"splashsource=mmc_fs\0" \

源码: u-boot\include\configs\sunxi-common.h
在这里插入图片描述

相关环境变量的含义如下:

splashfile指定logo图片的名称
splashimage指定将图片加载到内存的地址
splashsource指定从哪里读取图片, mmc_fs说明是mmc, 即sd卡, 默认是第一个分区

添加以上环境变量后, uboot启动后将在mmc(sd卡)的第一个分区(也就是boot分区)读取命名为logo.bmp的图片, 加载到内存地址并进行bmp图片的解析并显示.
所以更换logo只需要替换sd卡第一个分区的logo.bmp即可.
uboot支持显示24bpp的bmp图片, 大小保存于屏幕一致即可, 像我使用的是800x480的24bpp的bmp图片,

关闭uboot默认显示的企鹅logo

uboot默认显示了一个企鹅logo, 需要将其关闭
使能了splash的CONFIG_SPLASH_SCREEN这个宏后, 显示完logo后会直接返回, 不会再调用logo_plot显示企鹅logo了
所以这块其实不用改动

源码: u-boot\drivers\video\cfb_console.c
在这里插入图片描述

背光

uboot的lcd控制器初始化时, 会打开背光, 这样的效果其实不好, 会出现一小段白屏
改成显示完图片后再打开背光

  • 添加控制背光的接口

源码: u-boot\drivers\video\sunxi_display.c
在这里插入图片描述
源码: u-boot\include\video_fb.h
在这里插入图片描述

  • 去掉初始化时打开背光, 在显示完图片后打开背光

源码: u-boot\drivers\video\sunxi_display.c
在这里插入图片描述
源码: u-boot\drivers\video\cfb_console.c
在这里插入图片描述

修改启动参数

内核启动时, 会将启动信息打印到显示屏
这里通过修改uboot的启动参数, 关闭内核启动时的lcd打印
在这里插入图片描述
这里改动了两点:

  • 去掉 console=tty0, 这样内核启动过程, 显示屏就不会当成终端打印启动信息了
  • 添加 fbcon=map:1, 取消定向fb0, 同时关闭10分钟息屏

第二点改动可以参考内核关于fbcon的说明
源码: linux\Documentation\fb\fbcon.txt
在这里插入图片描述
fbcon=map:<0123>可以指定tty与fb的对应关系, logo使用的是fb0, 这里配置成1, fbcon就不会在fb0上作用, 实现关闭显示屏终端

关键代码解析

这里说明uboot如何将显示屏framebuffer的地址告诉kernel?

在内核设备树中, 有个framebuffer的节点, 它的status是"disable".
源码: linux\arch\arm\boot\dts\sun8i-v3s.dtsi
在这里插入图片描述

实际上, 在uboot加载内核设备树, 然后启动内核时, 会修改内核的设备树的framebuffer节点, 添加上显示屏framebuffer的地址并将其使能
因此, 内核加载显示屏驱动时能获取到正确的framebuffer地址

在uboot启动内核时, 会调用sunxi_simplefb_setup()函数将simple-framebuffer的设备节点添加到设备树中

关键代码如下:

源码: u-boot\drivers\video\sunxi_display.c

int sunxi_simplefb_setup(void *blob)
{
    ...
    // 这里填充内核设备树的 memory node, 声明内存的大小
    // 值的注意的是, ddr的尾部用来存放framebuffer
    // 因此内核可用的 内存大小 = ddr总大小 - framebuffer所需的大小
    // 即 gd->bd->bi_dram[0].size - sunxi_display.fb_size
	/*
	 * Do not report the framebuffer as free RAM to the OS, note we cannot
	 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
	 * and e.g. Linux refuses to iomap RAM on ARM, see:
	 * linux/arch/arm/mm/ioremap.c around line 301.
	 */
	start = gd->bd->bi_dram[0].start;
	size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
	ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
	if (ret) {
		eprintf("Cannot setup simplefb: Error reserving memory\n");
		return ret;
	}

    // 这里填充并使能内核设备树的 simple-framebuffer 节点
    // 第三个参数即为 framebuffer 的地址
    // 因此内核通过该节点获取 framebuffer 地址
	ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
			graphic_device->winSizeX, graphic_device->winSizeY,
			graphic_device->plnSizeX, "x8r8g8b8");

    ...
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值