当前位置: 首页 > news >正文

RK3568双屏同显配置全攻略:从设备树修改到内核调试

1. 项目概述:为什么要在RK3568上折腾双屏同显?

最近在做一个基于瑞芯微RK3568的工控项目,客户要求在同一个操作界面上,一块屏幕给操作员看,另一块屏幕给现场的工程师或者质检员同步查看。说白了,就是需要“双屏同显”。这个需求在数字标牌、工业控制台、互动展示柜里其实挺常见的,但真动手去配,才发现从硬件连接到软件配置,中间有不少细节需要捋清楚。RK3568这颗芯片本身支持多路显示输出,硬件底子没问题,但怎么把系统配置成我们想要的样子,就是另一回事了。

所谓“双屏同显”,专业点叫“克隆显示”(Clone Display)或“镜像显示”(Mirror Display),指的是两个或多个物理显示器上呈现完全相同的图像内容。这和“扩展显示”(Extended Display)是两码事,扩展显示是把桌面空间拉大,每个屏幕显示不同内容。同显的核心价值在于信息同步和展示冗余,比如在零售店,收银台和顾客屏显示同样的金额;在工厂,控制室大屏和现场工位屏同步展示生产状态,确保信息传递零误差。

选择RK3568来实现这个功能,看中的就是它集成的强大显示子系统。它内置了三个独立的视频输出端口(Video Port,简称VP),理论上能同时驱动三块屏幕。我们这次的目标,就是利用其中两个VP,让两块屏幕亮起来,并且显示一模一样的东西。整个过程会涉及到设备树(DTS)的修改、内核的配置与编译,以及一些显示参数的调试。下面,我就把这次从零开始配置RK3568双屏同显的完整过程、踩过的坑和最终验证有效的方案,详细拆解一遍。

2. 核心思路与硬件方案选型

在动手改代码之前,得先把硬件连接和软件层面的实现路径想明白。RK3568的多显示能力,核心在于其VOP(Video Output Processor)模块和后端的Video Port。

2.1 RK3568显示架构浅析

你可以把VOP想象成一个功能强大的“视频调度中心”。它的工作是,从内存里拿到要显示的图像数据(帧缓冲区),然后进行一系列处理,比如叠加图层、色彩空间转换、缩放等,最后把处理好的视频流送出去。关键点在于,这个“调度中心”后面接了多个“出站通道”,这就是Video Port。RK3568有三个VP:VP0, VP1, VP2。每个VP都是独立的,可以连接不同的物理显示接口,比如HDMI、LVDS、MIPI-DSI、eDP,甚至RGB接口。

对于“同显”,在软件上有两种主流实现思路:

  1. 帧缓冲复制:应用程序向一个帧缓冲区(fb0)写入数据,驱动层自动将这份数据复制到另一个帧缓冲区(fb1),分别由两个VP输出。这种方式对应用透明,但可能增加内存带宽和功耗。
  2. 单一帧缓冲多VP输出:更高效的方式是,让两个VP直接指向内存中同一块帧缓冲区。两个VP同步地从同一块内存区域读取数据并输出。RK3568的驱动通常支持这种模式,也是我们本次采用的目标方案。

2.2 硬件连接方案确定

你的开发板具体有哪些显示接口,决定了你的双屏组合。常见的RK3568开发板(比如迅为、Firefly的型号)通常会引出多个接口。你需要查阅你的开发板原理图或用户手册,确认哪两个接口是连接到不同的VP上的。

注意:非常重要的一点是,要实现双屏输出,两块屏幕必须连接到不同的Video Port上。你不能把两个HDMI显示器都插在同一个VP衍生的两个HDMI口上(如果板子有多个HDMI的话),因为它们底层可能共享同一个VP,无法独立驱动。务必确认你的硬件连接对应不同的VP。

举个例子,假设你的板子有如下接口:

  • HDMI0:通常固定在VP0或VP1。
  • LVDSMIPI-DSI:通常占用另一个VP。
  • eDP:可能占用第三个VP。

那么,一个典型的双屏同显组合就是:HDMI + LVDS或者HDMI + MIPI。你需要根据手头实际的屏幕类型(HDMI显示器、LVDS屏、MIPI屏)来决定。我这次使用的环境是:一块普通的1080P HDMI显示器,和一块1024x600分辨率的LVDS屏。

2.3 软件准备:内核与设备树

RK3568的显示驱动主要在内核中,配置信息则集中在设备树(Device Tree)文件里。我们的核心工作就是修改设备树,告诉内核:“请启用VP0和VP1(举例),分别驱动HDMI和LVDS,并且让它们显示同样的内容。”

你需要准备:

  1. RK3568的Linux SDK:从芯片原厂或开发板供应商处获取,里面包含了内核源码、编译工具链等。确保版本相对较新,对显示驱动支持完善。
  2. 编译环境:一个Linux开发机(Ubuntu 20.04/22.04比较常见),安装好必要的编译工具。
  3. 串口调试工具:用于查看内核启动日志,这是排查问题的生命线。

3. 设备树(DTS)配置详解与修改

设备树是描述硬件拓扑和配置的文本文件,内核通过它来知道板子上有什么设备、怎么工作。RK3568的多屏配置,主要修改两个地方:一是选择启用哪些屏幕的“宏定义”文件,二是具体屏幕的参数文件。

3.1 定位关键设备树文件

在你的内核源码目录下(通常是kernel/arch/arm64/boot/dts/rockchip/),找到你的板级设备树文件,例如rk3568-evb.dtsrk3568-topeet.dts。这个文件会包含很多#include语句,引用其他.dtsi文件。我们需要关注的是与屏幕选择相关的文件。

根据网络资料和常见方案,通常会有一个类似topeet_screen_choose.dtsirk3568-lcd.dtsi的文件。这个文件的作用,就是用“宏定义”(其实是设备树的条件编译)来控制启用哪块屏幕。我们以迅为的方案为例,找到这个文件,内容结构通常如下:

// 示例:topeet_screen_choose.dtsi / { // HDMI 屏幕使能宏 #ifdef HDMI_ENABLE #include "rk3568-hdmi.dtsi" #endif // LVDS 屏幕使能宏 #ifdef LVDS_ENABLE #include "rk3568-lvds.dtsi" #endif // MIPI 屏幕使能宏 #ifdef MIPI_ENABLE #include "rk3568-mipi.dtsi" #endif // EDP 屏幕使能宏 #ifdef EDP_ENABLE #include "rk3568-edp.dtsi" #endif };

3.2 启用双屏宏定义

我们的目标是同时启用HDMI和LVDS。那么,就需要定义HDMI_ENABLELVDS_ENABLE这两个宏。关键点来了:你必须确保它们分配到了不同的Video Port!

怎么知道分配给了哪个VP?你需要打开对应的rk3568-hdmi.dtsirk3568-lvds.dtsi文件查看。在里面搜索vopports关键字。你会看到类似这样的配置:

// 在 hdmi.dtsi 中 &hdmi { status = "okay"; }; &hdmi_in_vp0 { // 注意这里:hdmi 输入源来自 VP0 status = "okay"; }; &hdmi_in_vp1 { status = "disabled"; }; &hdmi_sound { status = "okay"; };
// 在 lvds.dtsi 中 &lvds { status = "okay"; }; &lvds_in_vp1 { // 注意这里:lvds 输入源来自 VP1 status = "okay"; }; &lvds_in_vp0 { status = "disabled"; };

上面这段配置清晰地表明:HDMI使用VP0,LVDS使用VP1。这符合我们的要求(不同VP)。如果发现你想用的两个屏幕配置在了同一个VP上(比如都配置成了xxx_in_vp0),那么同显将无法实现,你必须修改其中一个,将其分配到空闲的VP(如VP1或VP2)。修改时需谨慎,要结合硬件连接(原理图)确认该物理接口是否真的连接到那个VP。

现在,我们修改屏幕选择文件。通常不是在原文件上改,而是在板级设备树文件(如rk3568-evb.dts)的开头,或通过编译系统的配置来定义这些宏。一个直接的方法是,在板级.dts文件的最前面添加宏定义:

// 在 rk3568-mybroad.dts 文件顶部,include语句之前 #define HDMI_ENABLE #define LVDS_ENABLE //#define MIPI_ENABLE // 注释掉不需要的屏幕

3.3 配置同显模式与显示参数

仅仅启用两个屏幕,默认可能是“扩展模式”。我们需要配置为“同显模式”。这通常在一个系统级的显示配置文件里,也可能是通过内核启动参数(cmdline)或特定的驱动参数设置。

方法一:通过内核驱动参数(常见于Rockchip平台)在设备树中,找到VOP(视频输出处理器)的节点,或者查找是否有全局的显示相关参数。Rockchip内核通常通过drm驱动的video命令行参数来配置。你可以修改bootloader(如U-Boot)的启动参数,或者在内核的设备树中设置chosen节点的bootargs

在设备树中添加或修改:

/ { chosen { bootargs = "...原有参数... drm_kms_helper.video=HDMI-A-1,LVDS-1:clone"; }; };

这里的HDMI-A-1LVDS-1是你的显示输出接口名称,启动后可以在/sys/class/drm/下看到。clone关键字就是指示克隆/同显。不过,参数格式可能因内核版本而异,这需要你查阅内核文档或驱动源码。

方法二:通过修改VOP绑定(更底层的方法)更直接的方式是强制让两个VP输出同样的数据。这可以通过修改设备树,让两个VP的输入源(vop_out)指向同一个端点,或者配置显示管道来实现。这需要对RK3568的显示架构有更深理解,一般板厂提供的SDK里可能会有预设的同显配置片段。你可以搜索SDK中是否有dual-displaymirror相关的.dtsi文件。

方法三:启动后通过软件配置(灵活,但非永久)如果上述方法复杂,可以先将双屏点亮(即使是扩展模式),然后在系统启动后,使用命令行工具配置同显。例如,使用xrandr(X Window系统)或weston(Wayland合成器)的命令。但这要求你的文件系统已经包含了这些工具和相应的桌面环境。

实操心得:对于嵌入式Linux,尤其是无桌面的系统,方法一(内核参数)是最干净、最彻底的方案。它在内核初始化显示子系统时就完成配置,不依赖用户态服务。我建议优先尝试这个方法。你可以先不设clone参数,确保两块屏都能独立点亮并显示内容(可能是控制台滚屏信息),然后再添加克隆参数。

3.4 调整屏幕分辨率与时序

两块屏幕的分辨率、刷新率可能不同。在同显模式下,输出分辨率通常会以第一个被初始化或指定的主屏幕为准。另一块屏幕会接受这个分辨率信号,如果它不支持,可能会黑屏或显示异常。

因此,你需要在对应的屏幕设备树文件(如rk3568-lvds.dtsi)中,检查并确认其display-timings节点配置是否正确。特别是LVDS屏幕,它的时序参数(像素时钟、前后肩、同步脉冲宽度)需要严格按照屏幕规格书来填写。HDMI通常是自适应的,问题不大。

例如,在LVDS的设备树节点中:

&lvds { status = "okay"; ports { port@1 { reg = <1>; lvds_out_panel: endpoint { remote-endpoint = <&panel_in_lvds>; }; }; }; }; panel: panel { compatible = "simple-panel"; status = "okay"; // 关键:显示时序 display-timings { native-mode = <&timing0>; timing0: timing0 { clock-frequency = <51200000>; // 像素时钟,单位Hz hactive = <1024>; // 有效水平像素 vactive = <600>; // 有效垂直像素 hfront-porch = <160>; // 水平前肩 hsync-len = <20>; // 水平同步脉冲宽度 hback-porch = <140>; // 水平后肩 vfront-porch = <12>; // 垂直前肩 vsync-len = <3>; // 垂直同步脉冲宽度 vback-porch = <20>; // 垂直后肩 hsync-active = <0>; // 同步极性 vsync-active = <0>; de-active = <1>; pixelclk-active = <0>; }; }; };

务必根据你的实际屏幕手册修改这些值!填错了轻则花屏,重则烧坏屏幕背光驱动(虽然概率低)。

4. 内核编译与系统烧录

配置好设备树后,下一步就是编译内核并打包系统镜像。

4.1 编译内核与设备树

进入你的内核源码目录。

  1. 指定编译工具链:确保环境变量已设置好,例如:
    export PATH=/path/to/your/gcc-aarch64-linux-gnu/bin:$PATH export CROSS_COMPILE=aarch64-linux-gnu- export ARCH=arm64
  2. 加载默认配置:通常使用板级配置。
    make rockchip_linux_defconfig # 或 make rk3568-evb-defconfig,具体看你的SDK
  3. (可选)进行内核图形配置:如果你不确定显示驱动是否选好,可以检查一下。
    make menuconfig
    确保以下选项被启用(通常默认已启用):
    • Device Drivers -> Graphics support -> Direct Rendering Manager (DRM) -> DRM Support for Rockchip
    • 对应的显示接口驱动,如Rockchip HDMIRockchip LVDSRockchip MIPI DSI等。
  4. 编译内核与设备树
    make -j$(nproc) Image dtbs
    编译完成后,在arch/arm64/boot/下得到Image(内核镜像),在arch/arm64/boot/dts/rockchip/下得到rk3568-your-board.dtb(设备树二进制文件)。

4.2 打包与烧录

不同的SDK和bootloader,打包方式不同。常见的是使用Rockchip提供的rkbin工具和mkimage脚本,将内核、设备树、根文件系统等打包成统一的固件(如update.img)。

或者,如果你的系统是使用U-Boot引导,并且已经有一个可运行的SD卡或eMMC系统,你可以只更新内核和设备树:

  1. 将编译好的Image重命名为kernel.img(根据你的U-Boot预期文件名)。
  2. 将编译好的rk3568-your-board.dtb放到boot分区的指定位置。
  3. 将这两个文件拷贝到开发板存储设备的对应分区。

更通用的方法是使用SDK提供的打包脚本,例如./build.shmkupdate.sh,生成完整的固件包,然后通过Rockchip的AndroidTool(Windows)或upgrade_tool(Linux)工具烧录到开发板。

5. 上电调试与问题排查实录

烧录完成,连接好HDMI和LVDS屏幕,上电启动。这时最紧张的时刻来了,大概率不会一次成功。串口终端是你的眼睛。

5.1 查看内核启动日志

通过串口工具(如minicom,picocom,PuTTY)连接开发板,查看启动信息。重点关注以下几点:

  1. VOP和VP初始化:搜索日志中的vopvp0,vp1,hdmi,lvds等关键字。

    • 成功迹象:看到类似rockchip-drm display-subsystem: vp0: HDMI-A-1 connectedvp1: LVDS-1 connected的日志,并且没有failederrortimeout
    • 失败迹象:某个接口显示disabledfailed to bindcannot find...
  2. DRM(Direct Rendering Manager)初始化:DRM是Linux内核的图形驱动框架。看到rockchip-drm display-subsystem bound之类的成功绑定信息是好的。

  3. 屏幕时序与EDID

    • 对于HDMI,会打印[drm] Supports[drm] Driver信息,显示检测到的分辨率。
    • 对于LVDS,会打印你设备树里配置的时序参数,核对是否正确。

5.2 常见问题与解决方案

下面是我在调试过程中遇到的一些典型问题及解决方法,整理成了速查表:

问题现象可能原因排查步骤与解决方案
只有一块屏幕亮,另一块黑屏1. 设备树中另一块屏的status未设为“okay”
2. 两个屏幕配置到了同一个VP。
3. 屏幕时序参数错误。
4. 屏幕背光未开启(针对LVDS/MIPI屏)。
1. 检查设备树,确认两个屏幕节点status = “okay”
2. 检查xxx_in_vpX节点,确保是vp0vp1(或vp2)的不同组合。
3. 仔细核对LVDS屏幕规格书,修正display-timings里的所有参数,特别是clock-frequency
4. 检查背光控制GPIO配置。在设备树中,LVDS屏节点下可能有enable-gpiosbacklight子节点,确保其指向正确的GPIO控制器和引脚,并且状态为启用。
屏幕花屏、闪烁、撕裂1. 时序参数错误(尤其是像素时钟clock-frequency)。
2. 内存带宽不足或显存分配问题。
3. 屏幕物理连接不良(LVDS线松动)。
1.这是最常见原因。使用屏幕厂商提供的精确时序参数。可以尝试微调hfront-porch,hsync-len,hback-porch等值。
2. 尝试在内核启动参数中增加cma(连续内存分配器)的大小,例如cma=128M。确保系统有足够连续内存供帧缓冲区使用。
3. 重新插拔并固定LVDS排线。
系统启动后,两块屏显示不同内容(扩展模式)未成功配置同显(克隆)模式。1. 确认内核启动参数是否包含drm_kms_helper.video=xxx:clone配置。
2. 如果没有,在U-Boot命令行或设备树chosen节点中添加。
3. 如果内核参数不生效,尝试在系统启动后,使用cat /sys/class/drm/card0-DP-1/status等命令查看连接状态,并使用echo clone > /sys/class/drm/card0-DP-1/desired_mode(路径和命令可能不同)进行动态设置。这需要内核和驱动支持sysfs接口。
内核启动卡住,或提示显示相关错误后停止1. 设备树语法错误。
2. 驱动编译进内核时冲突。
3. 关键资源(如时钟、电源)配置错误。
1. 使用dtc(设备树编译器)检查设备树文件语法:dtc -I dts -O dtb -o /dev/null your.dts
2. 尝试将显示驱动编译为模块(=m),而不是内置(=y),看看能否绕过初始化顺序问题。
3. 检查设备树中VOP、HDMI、LVDS节点的时钟(clocks)和电源(supplies)引用是否正确,这些节点的父节点(如i2c控制器)是否启用。
HDMI屏幕无信号,但LVDS正常1. HDMI的PHY(物理层)电源或时钟未正确配置。
2. HDMI的DDC(显示数据通道,用于读取EDID)I2C通信失败。
3. 热插拔检测(HPD)信号有问题。
1. 检查设备树中hdmi节点的avdd-0v9,avdd-1v8等电源 regulator 是否被正确引用和启用。
2. 查看启动日志中是否有ddc i2c transfer error。检查连接HDMI的I2C总线是否正常。
3. 测量HDMI接口的HPD引脚电压,或在设备树中尝试强制使能HPD(不推荐长期使用)。

5.3 验证同显成功

当两块屏幕都点亮后,如何确认是同显而非扩展?

  1. 视觉验证:在屏幕上运行一个简单的图形应用(比如用fbv显示一张图片,或者运行一个带界面的Qt程序),观察两块屏幕上的内容是否完全同步,包括鼠标指针(如果有的话)。
  2. 系统信息验证:在终端输入cat /sys/class/drm/*/status,查看所有显示接口的状态。输入cat /sys/kernel/debug/dri/0/state(需要内核开启DEBUG_FS)可以查看更详细的DRM状态信息,包括每个crtc(对应VP)驱动的模式。
  3. 帧缓冲区验证:使用ls -l /dev/fb*查看有几个帧缓冲设备。在标准的同显配置下,你可能只看到一个fb0,因为两个VP共享同一个缓冲。如果看到fb0fb1,则可能是扩展模式或复制缓冲模式。

6. 性能考量与进阶优化

双屏同显功能实现后,还需要关注其稳定性和性能。

6.1 内存带宽与CMA配置

同时驱动两块屏幕,尤其是高分辨率屏幕(如双1080P),对内存带宽有一定压力。帧缓冲区需要存储在连续的内存中。RK3568的Linux内核通常使用CMA来分配连续内存。如果遇到显示卡顿或内存分配失败,可以尝试增大CMA区域。

修改内核启动参数,在bootargs中添加或修改cma参数,例如:

cma=256M

这会将CMA区域设置为256MB。具体大小需要根据你的屏幕分辨率(宽x高x像素字节数x2估算双缓冲)和系统其他需求来定,不宜过大而挤占系统内存。

6.2 功耗管理

两块屏幕同时工作,功耗会显著增加。在电池供电的设备上需要特别注意。

  • 动态调频:确保CPU和GPU的频率调节策略(cpufreq, devfreq)是激活的,在负载低时能降频。
  • 屏幕背光控制:如果屏幕支持PWM调光,在不需要高亮度时,通过软件调低背光可以省很多电。可以通过sysfs接口(如/sys/class/backlight/)控制背光亮度。
  • VP时钟门控:在驱动层面,当屏幕显示静态内容时,理论上可以降低VP的时钟频率以省电,但这需要驱动支持,通常不是默认行为。

6.3 应用层适配

对于你自己编写的应用程序,在双屏同显环境下基本无需特殊处理,因为应用只向一个逻辑显示区域(主屏幕)绘制内容。但需要注意:

  • 全屏处理:确保应用的全屏窗口覆盖的是正确的显示区域。
  • 鼠标指针:如果运行了桌面环境,确保鼠标指针能在两个屏幕间同步显示(克隆模式下应该自动同步)。
  • 多显示信息查询:如果你的应用需要查询显示设备信息,使用如libdrm等库时,可能会枚举到多个显示器,逻辑上需要能正确处理。

配置RK3568双屏同显,是一个从硬件认识到软件配置的完整链路。核心在于理解Video Port的概念,并正确地在设备树中分配和启用它们。修改设备树是重中之重,每一个参数都可能影响最终显示效果。调试过程离不开串口日志,耐心分析日志中的每一行错误信息,是解决问题的关键。当两块屏幕终于同步亮起,显示着相同的内容时,那种成就感是对之前所有折腾的最佳回报。这个配置一旦稳定下来,就可以作为你项目的基础镜像,为各种需要双屏展示的场景提供可靠支持。

http://www.jsqmd.com/news/1022797/

相关文章:

  • 猫抓浏览器资源嗅探扩展:5步掌握网页媒体资源捕获的终极实战指南
  • 【细胞分割】基于Otsu大津法的细胞图像分割与计数系统附Matlab代码
  • GTA5线上小助手终极指南:5分钟掌握免费开源工具,彻底改变你的洛圣都游戏体验
  • 2026成都结婚钻戒回收怎么选?同城老牌钻石回收门店全方位测评 - 奢侈品回收评测
  • 2026哈尔滨名表回收怎么选?本地高口碑变现机构实测排行 - 名奢变现站
  • 2026年安徽省想学无人机应用技术专业推荐去哪所学校?如何报名? - 小张zc
  • 东莞莞城街道黄金回收指南:三个硬指标与6家服务机构 - 上门黄金回收
  • 【采用BPSK或GMSK的Turbo码】MSK、GMSK调制二比特差分解调、turbo+BPSK、turbo+GMSK研究附Matlab代码
  • WAIC技术落地十大趋势:从大模型轻量化到人机协同工作流
  • 西城微科胎压计PCBA流程方案开发
  • 2026年国内企业直播软件综合实力排行及避坑指南 - 互联网科技品牌测评
  • 北京西城区黄金回收行情警示与六家机构对比 - 上门黄金回收
  • WELearnHelper:3步打造你的英语网课终极智能助手
  • NVIDIA Profile Inspector深度解析:突破显卡性能瓶颈的底层配置技术
  • 告别包包积灰!2026昆明LV、Gucci正规回收变现全攻略 - 禹竞
  • 数字电子技术基础:从逻辑门到FPGA的实践指南与核心难点解析
  • 沈阳本地黄金回收避坑指南:知道这三步,轻松多回收几百上千元 - 奢侈品回收评测
  • 流量成本上涨 41%,AI 重构营销链路,合肥 GEO 优化行业现状与服务商盘点
  • 福州鼓楼区黄金回收行情分析及六家正规机构对比 - 上门黄金回收
  • 免费获得专业级AI视频生成能力:Wan2.2-TI2V-5B开源模型终极指南
  • DeepSeek-R1本地部署超详细实战指南:从零到法律级合同审查
  • 红米10X 5G刷机全攻略:从解锁BL到安全刷入第三方ROM
  • 2026渭南本地认可的 5 家排污许可废气废水监测机构实地测评汇总 废水废气 + 自行监测 + CMA 检测报告 附电话地址 - 科信检测
  • 2026合肥本地防雷检测哪家专业?TOP 正规机构榜单 + 防雷装置 + 接地电阻 + SPD 检测 附电话地址 - 中安检测集团
  • 2026论文神级降AI率软件大曝光:一键把AIGC率降至安全线!
  • MIPS-Linux-GNU交叉编译工具链:嵌入式开发的核心基础设施
  • TranslucentTB启动失败终极指南:深度解析Microsoft.UI.Xaml.2.8缺失问题与专业解决方案
  • 量化交易中的p值陷阱:识别与防范p-Hacking
  • 2026淮北本地防雷检测哪家专业?TOP 正规机构榜单 + 防雷装置 + 接地电阻 + SPD 检测 附电话地址 - 中安检测集团
  • 郴州零基础美业学员必读:2026年从迷茫宝妈到月入过万的真实进阶路线 - 企业名录优选推荐