嵌入式Linux下使用 Plymouth 實(shí)現(xiàn)開(kāi)機(jī)畫(huà)面示例
1). 簡(jiǎn)介
嵌入式 Linux 下傳統(tǒng)實(shí)現(xiàn) Splash Screen 的方式是通過(guò)替換 kernel 默認(rèn)的 TUX 小企鵝 logo 為定制的開(kāi)機(jī)畫(huà)面圖片來(lái)實(shí)現(xiàn)嵌入式設(shè)備開(kāi)機(jī)圖片,雖然比較成熟且可以保證開(kāi)機(jī)畫(huà)面加載比較早,但是存在的問(wèn)題首先是對(duì)嵌入式設(shè)備不同顯示接口的兼容性不好,另外每次修改適配都需要重新編譯內(nèi)核,維護(hù)起來(lái)不是很方便,然后就是只能支持靜態(tài)圖片無(wú)法支持動(dòng)畫(huà)。基于上述原因,使用專(zhuān)門(mén)的 Splash Screen 工具來(lái)實(shí)現(xiàn)開(kāi)機(jī)畫(huà)面逐漸成為嵌入式設(shè)備的主流方向,本文就簡(jiǎn)單演示使用 Plymouth 工具來(lái)實(shí)現(xiàn)動(dòng)態(tài)開(kāi)機(jī)畫(huà)面的示例。
本文所演示的平臺(tái)來(lái)自于Toradex Verdin iMX8MM 嵌入式平臺(tái),基于 NXP iMX8M Mini 系列 ARM 處理器,主要核心架構(gòu)為 Cortex-A53 。
2). 硬件準(zhǔn)備
a).
核心版配合 載板,并通過(guò) DSI-LVDS Adapter 連接 以及調(diào)試串口以便測(cè)試。3). 關(guān)于 Plymouth
a). Plymouth 是一個(gè)實(shí)現(xiàn) Linux 啟動(dòng)過(guò)程中開(kāi)機(jī)畫(huà)面的工具軟件,其啟動(dòng)的時(shí)間非常早,通過(guò) initramfs 幫助可以在 Linux 內(nèi)核加載同時(shí)啟動(dòng),甚至要早于 Linux rootfs 文件系統(tǒng)掛載。Plymouth 可以方便的實(shí)現(xiàn)開(kāi)關(guān)機(jī)圖片或者動(dòng)畫(huà)。
b). 關(guān)于 Plymouth 更多詳細(xì)介紹以及源代碼請(qǐng)自行參考如下資料。
./ Plymouth 官方頁(yè)面
./ Plymouth 源代碼
./ Plymouth 深入配置使用說(shuō)明
4). 通過(guò) Ycoto 環(huán)境配置 Plymouth 并編譯 Ycoto Linux BSP Image
a). 配置 Ycoto Project 編譯環(huán)境
./ 參考這里配置基本的 Ycoto Project 編譯環(huán)境
./ 參考如下文章配置定制化 layer
b). 在定制化 layer meta-customer-demos 下面添加 layer 配置文件
---------------------------------------
$ mkdir -p ../oe_core/layers/meta-customer-demos/conf
$ cd .../oe_core/layers/meta-customer-demos/conf
### create layer.conf file ###
# We have a conf and classes directory, append to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "customer-demos"
BBFILE_PATTERN_customer-demos = "^${LAYERDIR}/"
BBFILE_PRIORITY_customer-demos = "24"
# Let us add layer-specific bbappends which are only applied when that
# layer is included in our configuration
BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bbappend' % layer \
for layer in BBFILE_COLLECTIONS.split())}"
# Add layer-specific bb files too
BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bb' % layer \
for layer in BBFILE_COLLECTIONS.split())}"
LAYERDEPENDS_customer-demos = " \
core \
yocto \
openembedded-layer gnome-layer multimedia-layer networking-layer \
"
LAYERSERIES_COMPAT_customer-demos = "hardknott honister kirkstone"
---------------------------------------
c). 在定制化 layer meta-customer-demos 下面添加 Plymouth 相關(guān)配置文件
./ 增加 Plymouth bb file
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-core/plymouth
$ cd recipes-core/plymouth
### cteate plymouth_%.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI += " \ file://toradexlogo-white.png \ file://spinner.plymouth \ " PACKAGECONFIG = "pango drm" EXTRA_OECONF += "--with-udev --with-runtimedir=/run" do_install:append () { install -m 0644 ${WORKDIR}/toradexlogo-white.png ${D}${datadir}/plymouth/themes/spinner/watermark.png install -m 0644 ${WORKDIR}/spinner.plymouth ${D}${datadir}/plymouth/themes/spinner/spinner.plymouth }
---------------------------------------
./ 添加 Plymouth 使用的 theme 文件 和 background logo 圖片文件,這里使用的是一個(gè)配合屏幕分辨率的白色背景圖片,因此 spinner 圖標(biāo)會(huì)被遮蓋,實(shí)際使用可以根據(jù)需要修改圖片文件和 theme 配置。
---------------------------------------
$ mkdir files
$ cp .../toradexlogo-white.png files
$ cd files
### cteate spinner theme file spinner.plymouth ###
[Plymouth Theme]
Name=Spinner
Description=Adoption of official Spinner Theme for Toradex.
ModuleName=two-step
[two-step]
Font=Cantarell 12
TitleFont=Cantarell Light 30
ImageDir=/usr/share/plymouth/themes/spinner
DialogHorizontalAlignment=.5
DialogVerticalAlignment=.382
TitleHorizontalAlignment=.5
TitleVerticalAlignment=.382
HorizontalAlignment=.5
VerticalAlignment=.7
WatermarkHorizontalAlignment=.5
WatermarkVerticalAlignment=.45
Transition=none
TransitionDuration=0.0
BackgroundStartColor=0x000000
BackgroundEndColor=0x000000
ProgressBarBackgroundColor=0x606060
ProgressBarForegroundColor=0xffffff
MessageBelowAnimation=true
---------------------------------------
d). 由于 Plymouth 是文件系統(tǒng)組件,通過(guò) Linux kernel 加載完成后在使能systemd 來(lái)啟動(dòng),這樣就會(huì)導(dǎo)致比較大的延遲;為了盡可能使 Plymouth 在系統(tǒng)啟動(dòng)過(guò)程中盡早啟動(dòng),可以添加包含 Plymouth 的 Initramfs 鏡像使得 Plymouth 在 Linux Kernel 加載過(guò)程中即同步啟動(dòng)了。
./ 添加 Initramfs bb 定義以及相關(guān)文件,對(duì)應(yīng)需要 files 目錄下的相關(guān)文件請(qǐng)參考
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/recipes-core
$ mkdir -p initramfs-framework/files
$ cd initramfs-framework
### cteate initramfs-framework_1.0.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI += "\
file://plymouth \
file://kmod \
file://0001-Mount-run-with-tmpfs.patch \
file://0002-only-scan-for-block-devices.patch \
"
PACKAGES:append = " \
initramfs-module-plymouth \
initramfs-module-kmod \
"
SUMMARY:initramfs-module-plymouth = "initramfs support for plymouth"
RDEPENDS:initramfs-module-plymouth = "${PN}-base plymouth ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd-udev-rules', '', d)}"
FILES:initramfs-module-plymouth = "/init.d/02-plymouth"
SUMMARY:initramfs-module-kmod = "initramfs support for loading kernel modules"
RDEPENDS:initramfs-module-kmod = "${PN}-base"
FILES:initramfs-module-kmod = "\
/init.d/01-kmod \
/etc/modules-load.d/* \
"
do_install:append() {
install -m 0755 ${WORKDIR}/plymouth ${D}/init.d/02-plymouth
install -m 0755 ${WORKDIR}/kmod ${D}/init.d/01-kmod
}
# Adding modules so plymouth can show the splash screen during boot
SRC_URI:append:mx8-nxp-bsp = " file://50-imx8-graphics.conf"
RDEPENDS:initramfs-module-kmod:append:mx8-nxp-bsp = " \
kernel-module-display-connector \
kernel-module-lontium-lt8912b \
"
do_install:append:mx8-nxp-bsp() {
install -d ${D}/etc/modules-load.d/
install -m 0755 ${WORKDIR}/50-imx8-graphics.conf ${D}/etc/modules-load.d/50-imx8-graphics.conf
}
---------------------------------------
./ 添加 initramfs image 定義文件
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/recipes-core
$ mkdir images
$ cd images
### cteate initramfs-plymouth-splash-image.bb file ###
DESCRIPTION = "Toradex plymouth splash demo initramfs image"
PACKAGE_INSTALL = "initramfs-framework-base initramfs-module-udev \
initramfs-module-rootfs initramfs-module-debug \
initramfs-module-plymouth ${VIRTUAL-RUNTIME_base-utils} base-passwd \
initramfs-module-kmod"
SYSTEMD_DEFAULT_TARGET = "initrd.target"
# Do not pollute the initrd image with rootfs features
IMAGE_FEATURES = "splash"
export IMAGE_BASENAME = "initramfs-plymouth-splash-image"
IMAGE_LINGUAS = ""
LICENSE = "MIT"
IMAGE_FSTYPES = "cpio.gz"
IMAGE_FSTYPES:remove = "wic wic.gz wic.bmap wic.vmdk wic.vdi ext4 ext4.gz teziimg"
IMAGE_CLASSES:remove = "image_type_torizon image_types_ostree image_types_ota image_repo_manifest license_image qemuboot"
# avoid circular dependencies
EXTRA_IMAGEDEPENDS = ""
inherit core-image nopackages
IMAGE_ROOTFS_SIZE = "8192"
# Users will often ask for extra space in their rootfs by setting this
# globally. Since this is a initramfs, we don't want to make it bigger
IMAGE_ROOTFS_EXTRA_SPACE = "0"
IMAGE_OVERHEAD_FACTOR = "1.0"
BAD_RECOMMENDATIONS += "busybox-syslog"
---------------------------------------
e). 由于增加了 initramfs image,就需要修改 distroboot 啟動(dòng)文件 boot.scr 來(lái)調(diào)整啟動(dòng)進(jìn)程,這里通過(guò)修改 u-boot-distro-boot 文件來(lái)適配,對(duì)應(yīng)的 files 目錄下的文件完整內(nèi)容請(qǐng)參考
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-bsp/u-boot/files
$ cd recipes-bsp/u-boot
### cteate u-boot-distro-boot.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " \
file://boot.cmd.in \
"
---------------------------------------
f). 另外,對(duì)于 Verdin iMX8M Mini,由于顯示部分是通過(guò) DSI-LVDS Bridge 來(lái)實(shí)現(xiàn)的,為了使得在 initramfs 階段就可以加載相關(guān)驅(qū)動(dòng),需要修改 Linux Kernel 配置,而對(duì)于其他 iMX8/iMX8X/iMX8MP 如果是原生 LVDS/HDMI 接口則無(wú)需修改。
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-kernel/linux/files
$ cd recipes-kernel/linux
### cteate linux-toradex%.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
# Prevent the use of in-tree defconfig
unset KBUILD_DEFCONFIG
SRC_URI += "\
file://defconfig \
"
---------------------------------------
./ files 目錄下的完整 defconfig 文件請(qǐng)見(jiàn)
,主要修改了如下幾個(gè)驅(qū)動(dòng)的配置---------------------------------------
-CONFIG_DRM_PANEL_LVDS=m
+CONFIG_DRM_PANEL_LVDS=y
-CONFIG_DRM_SEC_MIPI_DSIM=m
+CONFIG_DRM_SEC_MIPI_DSIM=y
-CONFIG_DRM_TI_SN65DSI83=m
+CONFIG_DRM_TI_SN65DSI83=y
-CONFIG_DRM_IMX_SEC_DSIM=m
+CONFIG_DRM_IMX_SEC_DSIM=y
---------------------------------------
g). 最后配置完成的 meta-customer-demos 文件結(jié)構(gòu)如下
---------------------------------------
$ tree meta-customer-demos/
meta-customer-demos/
├── conf
│ └── layer.conf
├── recipes-bsp
│ └── u-boot
│ ├── files
│ │ └── boot.cmd.in
│ └── u-boot-distro-boot.bbappend
├── recipes-core
│ ├── images
│ │ ├── initramfs-ostree-torizon-image.bb
│ │ └── initramfs-plymouth-splash-image.bb
│ ├── initramfs-framework
│ │ ├── files
│ │ │ ├── 0001-Mount-run-with-tmpfs.patch
│ │ │ ├── 0002-only-scan-for-block-devices.patch
│ │ │ ├── 50-imx8-graphics.conf
│ │ │ ├── kmod
│ │ │ ├── plymouth
│ │ │ └── rootfs
│ │ └── initramfs-framework_1.0.bbappend
│ └── plymouth
│ ├── files
│ │ ├── spinner.plymouth
│ │ └── toradexlogo-white.png
│ └── plymouth_%.bbappend
└── recipes-kernel
└── linux
├── files
│ └── defconfig
└── linux-toradex%.bbappend
13 directories, 17 files
---------------------------------------
h). 為了將 initramfs 集成到編譯生成的 Image 壓縮包內(nèi),需要修改如下 image_type 配置文件
---------------------------------------
--- a/layers/meta-toradex-bsp-common/classes/image_type_tezi.bbclass
+++ b/layers/meta-toradex-bsp-common/classes/image_type_tezi.bbclass
@@ -8,7 +8,7 @@
WKS_FILE_DEPENDS:append = " tezi-metadata virtual/dtb"
DEPENDS += "${WKS_FILE_DEPENDS}"
IMAGE_BOOT_FILES_REMOVE = "${@make_dtb_boot_files(d) if d.getVar('KERNEL_IMAGETYPE') == 'fitImage' else ''}"
-IMAGE_BOOT_FILES:append = " overlays.txt ${@'' if d.getVar('KERNEL_IMAGETYPE') == 'fitImage' else 'overlays/*;overlays/'}"
+IMAGE_BOOT_FILES:append = " overlays.txt initramfs-plymouth-splash-image-${MACHINE}.cpio.gz;initramfs-plymouth-splash-image.img ${@'' if d.getVar('KERNEL_IMAGETYPE') == 'fitImage' else 'overlays/*;overlays/'}"
IMAGE_BOOT_FILES:remove = "${IMAGE_BOOT_FILES_REMOVE}"
RM_WORK_EXCLUDE += "${PN}"
---------------------------------------
i). 修改 build/conf/bblayer.conf 文件添加相關(guān) layer
---------------------------------------
--- a/build/conf/bblayers.conf 2023-03-30 11:13:22.946533642 +0800
+++ b/build/conf/bblayers.conf 2023-11-17 16:03:01.666129480 +0800
@@ -35,6 +35,7 @@
${TOPDIR}/../layers/meta-freescale-distro \
${TOPDIR}/../layers/meta-toradex-demos \
${TOPDIR}/../layers/meta-qt5 \
+ ${TOPDIR}/../layers/meta-customer-demos \
\
\
${TOPDIR}/../layers/meta-toradex-distro \
---------------------------------------
j). 修改 build/conf/local.conf 文件,增加 Plymouth 和 initramfs 相關(guān)定義
---------------------------------------
# add plymouth support
CORE_IMAGE_EXTRA_INSTALL += "plymouth"
INITRAMFS_IMAGE = "initramfs-plymouth-splash-image"
INITRAMFS_FSTYPES = "cpio.gz"
---------------------------------------
k). 重新編譯生成 Ycoto Linux BSP Image
---------------------------------------
$ MACHINE="verdin-imx8mm" PARALLEL_MAKE="-j 4" BB_NUMBER_THREADS="4" bitbake tdx-reference-multimedia-image
---------------------------------------
l). 參考
的說(shuō)明將上述修改下重新編譯生成的 Ycoto Linux Image 通過(guò) Toradex Easy Installer 更新到 Verdin iMX8MM 模塊。
5). Plymouth Splash 部署測(cè)試
a). 安裝好上述編譯的 Image 后,參考
說(shuō)明配置合適的 Device-tree Overlay 文件來(lái)適配屏幕;然后配置如下 U-boot 環(huán)境變量來(lái)顯示 Splash,且縮短加載時(shí)間---------------------------------------
# setenv tdxargs ‘quiet logo.nologo vt.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3’
# setenv bootdelay 0
# saveenv && reset
---------------------------------------
b). 為了保證 Plymouth Splash和 Qt Demo App切換更自然,且中間不會(huì)被 Weston Desktop 中斷,需要修改一下一些 Systemd Service 文件
---------------------------------------
--- a/lib/systemd/system/plymouth-quit.service
+++ b/lib/systemd/system/plymouth-quit.service
@@ -1,6 +1,6 @@
[Unit]
Description=Terminate Plymouth Boot Screen
-After=rc-local.service plymouth-start.service systemd-user-sessions.service
+After=rc-local.service plymouth-start.service systemd-user-sessions.service waylan
d-app-launch.service
[Service]
ExecStart=-/bin/plymouth quit --retain-splash
--- a/lib/systemd/system/serial-getty@.service
+++ b/lib/systemd/system/serial-getty@.service
@@ -12,7 +12,7 @@
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
BindsTo=dev-%i.device
-After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service getty
-pre.target
+After=dev-%i.device systemd-user-sessions.service getty-pre.target
After=rc-local.service
# If additional gettys are spawned during boot then we should make
--- a/lib/systemd/system/weston.service
+++ b/lib/systemd/system/weston.service
@@ -13,7 +13,7 @@
After=systemd-user-sessions.service
# If Plymouth is used, we want to start when it is on its way out.
-After=plymouth-quit-wait.service
+#After=plymouth-quit-wait.service
# D-Bus is necessary for contacting logind. Logind is required.
Wants=dbus.socket
--- a/etc/xdg/weston/weston.ini
+++ b/etc/xdg/weston/weston.ini
@@ -6,6 +6,7 @@
repaint-window=16
#enable-overlay-view=1
modules=screen-share.so
+shell=kiosk-shell.so
#[shell]
#size=1920x1080
---------------------------------------
b). 最后部署完成的測(cè)試效果如下,實(shí)測(cè)從開(kāi)機(jī)到出現(xiàn) Splash 畫(huà)面大約5秒,另外 Plymouth splash 默認(rèn)除了支持開(kāi)機(jī)畫(huà)面,在 reboot 重啟和 poweroff 關(guān)機(jī)的時(shí)候也會(huì)同樣顯示 splash 畫(huà)面
動(dòng)畫(huà)演示如下
6). 總結(jié)
本文基于嵌入式 Linux 簡(jiǎn)單演示了 Plymouth splash 開(kāi)機(jī)畫(huà)面的部署和測(cè)試。
提交
Verdin AM62 LVGL 移植
基于 NXP iMX8MM 測(cè)試 Secure Boot 功能
隆重推出 Aquila - 新一代 Toradex 計(jì)算機(jī)模塊
Verdin iMX8MP 調(diào)試串口更改
NXP iMX8MM Cortex-M4 核心 GPT Capture 測(cè)試