飞凌RK3588开发板同显/异显模式切换
一、核心概念:同显(sync) vs 异显(async)
这是嵌入式多屏系统最基础的两种显示模式,RK3588硬件最多支持3路独立显示输出(HDMI0、HDMI1、MIPI-DSI/LVDS/eDP任意组合)。
| 模式 | 英文标识 | 工作原理 | 典型应用场景 |
|---|---|---|---|
| 同显 | sync | 所有显示接口共享同一个帧缓冲区(FrameBuffer),输出完全相同的画面 | 广告机、教学演示屏、工业现场多工位同步显示 |
| 异显 | async | 每个显示接口分配独立的帧缓冲区,输出完全独立的不同画面 | 车载中控(仪表盘+中控屏)、收银机(主屏+客显)、工业HMI(操作屏+监控屏) |
二、操作步骤详解(U-Boot命令行)
所有操作必须在U-Boot启动阶段 执行,不能在Linux系统终端中运行(Linux的setenv是shell命令,与U-Boot环境变量无关)。
1. 进入U-Boot命令行
开发板上电后,在串口终端看到以下倒计时提示时,立即按下Ctrl+C:
Hit key to stop autoboot('CTRL+C'): 0
成功进入后会出现U-Boot命令提示符 =>。
2. 查看当前显示模式
bash
print disp_type
- 默认出厂配置:
disp_type=sync(同显模式) - 命令作用:打印U-Boot环境变量
disp_type的当前值
3. 切换为异显模式(永久生效)
bash
# 1. 设置环境变量(临时生效,重启丢失)
setenv disp_type async
# 2. 将配置写入eMMC/NAND永久存储
saveenv
# 3. 重启开发板使配置生效
reset
-
执行
saveenv后会看到以下输出,表示写入成功:Saving Environment to ENV_BLK... Writing to mmc(0)... done
4. 切回同显模式(补充PPT未提及内容)
bash
setenv disp_type sync
saveenv
reset
三、底层原理
- 环境变量的作用 :
disp_type是飞凌在瑞芯微官方U-Boot基础上封装的自定义环境变量,专门用于控制显示驱动的初始化模式。 - 内核继承机制 :RK3588的显示驱动初始化从U-Boot阶段就已启动,Linux内核会直接继承U-Boot传递的
disp_type参数,无需在系统内重新配置。 - 驱动实现差异 :
sync模式:驱动将单个FB设备映射到所有显示通道,GPU只需渲染一份画面async模式:驱动为每个显示通道创建独立的FB设备(如/dev/fb0、/dev/fb1),GPU需同时渲染多份画面
四、关键注意事项
- saveenv不可省略 :仅执行
setenv只会修改内存中的临时变量,重启后会恢复默认值;必须执行saveenv写入非易失性存储。 - 硬件前提 :异显模式需要开发板至少连接2个正常工作的显示设备,且分辨率、刷新率在RK3588支持范围内。
- 性能影响:异显模式会显著增加GPU和内存带宽消耗,尤其是在同时播放4K视频或运行3D应用时。
- SDK兼容性 :该配置仅适用于飞凌官方提供的Linux/Android SDK;自行移植内核时,需确保驱动代码中正确解析了
disp_type环境变量。
五、扩展知识
-
查看所有显示相关环境变量:
bashprint | grep disp可查看显示分辨率、刷新率、接口使能等更多配置项。
-
Linux系统内动态切换 :
U-Boot配置的是开机默认模式,系统运行时可通过DRM接口动态切换同显/异显,常用工具:
modetest(libdrm工具集)- Weston/Wayland合成器
- Qt/GTK多屏显示框架
-
常见问题排查:
- 切换后黑屏:检查显示设备连接、分辨率匹配度、内核驱动加载状态
- saveenv失败:检查eMMC是否正常、是否开启写保护
- 重启后模式未变:确认执行了
saveenv,或检查是否有启动脚本覆盖了环境变量
飞凌RK3588 Linux系统内动态切换双屏同显/异显完整指南
前提条件 :必须先在U-Boot中执行过setenv disp_type async && saveenv && reset,确保内核已初始化所有显示通道的DRM设备。动态切换无需重启开发板,实时生效。
一、必备工具与环境检查
1. 安装基础工具(飞凌SDK默认已集成)
bash
apt update && apt install -y libdrm-tests weston
modetest:DRM底层调试工具,直接操作内核显示驱动weston:Wayland合成器,嵌入式最常用的多屏显示管理工具
2. 确认系统显示资源
执行以下命令查看所有可用的显示接口、分辨率和CRTC(显示控制器):
bash
modetest -M rockchip
关键输出解读(飞凌RK3588标准配置):
| 连接器名称 | 对应物理接口 | 可用CRTC编号 | 最大分辨率 |
|---|---|---|---|
| HDMI-A-1 | HDMI0(靠近电源) | 32, 33, 34 | 8K@60Hz |
| HDMI-A-2 | HDMI1(靠近网口) | 32, 33, 34 | 4K@60Hz |
| DSI-1 | MIPI-DSI/LVDS接口 | 32, 33, 34 | 4K@60Hz |
RK3588有3个独立CRTC(32/33/34),每个CRTC可驱动任意一个显示接口,支持任意组合的同显/异显。
二、方法一:DRM底层直接切换(无桌面环境)
适用于无桌面的纯嵌入式系统,直接通过modetest命令操作硬件,延迟最低。
1. 双屏异显配置(HDMI0+HDMI1)
bash
# 语法:modetest -M rockchip -s <CRTC编号>:<分辨率>@<刷新率> -o <连接器名称>
# 示例:HDMI0(CRTC32)输出1920x1080@60,HDMI1(CRTC33)输出1920x1080@60
modetest -M rockchip -s 32:1920x1080@60 -o HDMI-A-1 -s 33:1920x1080@60 -o HDMI-A-2 -f AR24
-f AR24:指定像素格式为32位ARGB,兼容性最好- 执行后两个屏幕会显示不同的彩色测试条,说明异显成功
- 按
Ctrl+C退出测试
2. 双屏同显配置(HDMI0+HDMI1)
bash
# 让两个连接器共享同一个CRTC(32),输出完全相同的画面
modetest -M rockchip -s 32:1920x1080@60 -o HDMI-A-1 -o HDMI-A-2 -f AR24
3. 三屏异显(RK3588硬件极限)
bash
# HDMI0(32)+HDMI1(33)+MIPI(34)同时输出不同画面
modetest -M rockchip \
-s 32:1920x1080@60 -o HDMI-A-1 \
-s 33:1920x1080@60 -o HDMI-A-2 \
-s 34:1280x800@60 -o DSI-1 \
-f AR24
# 三、方法二:Weston合成器切换(带桌面环境)
飞凌官方Linux SDK默认使用Weston作为桌面合成器,支持更灵活的多屏布局和应用窗口管理。
# 1. 双屏异显启动(左右扩展)
bash
# 停止默认Weston服务
systemctl stop weston
# 启动双屏异显:HDMI0在左,HDMI1在右,分辨率均为1920x1080
weston --backend=drm-backend.so --drm-device=/dev/dri/card0 \
--output=HDMI-A-1 --mode=1920x1080@60 --pos=0,0 \
--output=HDMI-A-2 --mode=1920x1080@60 --pos=1920,0
- 启动后鼠标可以在两个屏幕之间自由移动,应用窗口可以拖到任意屏幕
- 支持不同分辨率组合,例如HDMI0用4K,HDMI1用1080P
# 2. 双屏同显启动(克隆模式)
bash
weston --backend=drm-backend.so --drm-device=/dev/dri/card0 \
--output=HDMI-A-1 --mode=1920x1080@60 --pos=0,0 \
--output=HDMI-A-2 --mode=1920x1080@60 --same-as=HDMI-A-1
--same-as=HDMI-A-1:指定HDMI1完全克隆HDMI0的画面
3. 永久配置(开机自动生效)
编辑Weston配置文件/etc/xdg/weston/weston.ini:
ini
[core]
backend=drm-backend.so
drm-device=/dev/dri/card0
[output]
name=HDMI-A-1
mode=1920x1080@60
pos=0,0
[output]
name=HDMI-A-2
mode=1920x1080@60
# 异显模式(左右扩展)
pos=1920,0
# 同显模式(注释上面一行,取消下面一行注释)
# same-as=HDMI-A-1
保存后重启Weston服务:
bash
systemctl restart weston
四、Qt应用双屏显示实战
1. 异显模式下指定应用运行屏幕
bash
# 运行在第一个屏幕(HDMI0)
QT_QPA_PLATFORM=wayland-egl ./your_app -platform wayland --screen 0
# 运行在第二个屏幕(HDMI1)
QT_QPA_PLATFORM=wayland-egl ./your_app -platform wayland --screen 1
2. 一个应用同时显示两个不同窗口在不同屏幕
cpp
// Qt代码示例
#include <QApplication>
#include <QWidget>
#include <QScreen>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 获取所有屏幕
QList<QScreen *> screens = QApplication::screens();
if (screens.size() >= 2) {
// 窗口1显示在屏幕0
QWidget w1;
w1.setWindowTitle("Screen 0");
w1.resize(800, 600);
w1.move(screens[0]->geometry().center() - w1.rect().center());
w1.show();
// 窗口2显示在屏幕1
QWidget w2;
w2.setWindowTitle("Screen 1");
w2.resize(800, 600);
w2.move(screens[1]->geometry().center() - w2.rect().center());
w2.show();
}
return a.exec();
}
五、常见问题排查
-
执行modetest提示"Permission denied"
bash# 切换到root用户 sudo su -
切换后某个屏幕黑屏
- 检查物理连接是否牢固
- 确认分辨率和刷新率在屏幕支持范围内
- 尝试更换CRTC编号(例如用34代替33)
-
Weston启动失败
- 确保已停止其他桌面服务(如Xorg)
- 检查
/var/log/weston.log日志文件 - 确认U-Boot中已设置
disp_type=async
-
只有一个屏幕有画面
- 执行
ls /dev/dri/确认存在card0和多个connector - 重新执行U-Boot异显配置并重启开发板
- 执行