RK3568嵌入式Linux双屏同显配置实战:从VOP原理到设备树调试
2026/6/16 3:55:08 网站建设 项目流程

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

最近在搞一个基于瑞芯微RK3568芯片的工控项目,客户提了个挺有意思的需求:他们希望在一块主控板上同时驱动两块屏幕,并且两块屏幕显示一模一样的内容。这个需求在行业内有个专业的叫法,叫“双屏同显”或者“镜像显示”。乍一听,你可能觉得这有什么难的,不就是复制一份画面输出吗?但真上手在嵌入式Linux系统里配置,尤其是针对RK3568这种集成了复杂显示子系统的SoC,你会发现里面门道不少。

RK3568这颗芯片在嵌入式圈子里热度一直很高,它性能均衡,接口丰富,特别适合做各种带屏的终端设备,比如自助点餐机、工业HMI、广告机、智能家居中控等等。我手头这块开发板,一个HDMI接口,一个MIPI-DSI接口,正好可以用来验证双屏输出。双屏同显的应用场景其实非常广泛,比如在展览展示中,主屏和副屏同步播放宣传视频;在会议室,主讲人的屏幕内容可以实时镜像到更大的投影或电视上;在零售店,收银台和顾客屏显示相同的订单信息,提升交互体验。

要实现这个功能,核心在于理解RK3568的显示框架。它内部有一个叫做VOP(Video Output Processor)的显示控制器,负责从内存里抓取图像数据,处理后送出去。关键点是,RK3568的VOP支持多个独立的Video Port(视频端口),官方资料显示最多有三个。这意味着,理论上它可以同时驱动三块屏幕。我们的任务,就是配置系统,让两个不同的Video Port输出相同的帧缓冲(Framebuffer)数据。听起来简单,但配置过程涉及到内核设备树(Device Tree)的修改、显示驱动的理解,以及可能遇到的各种时序、分辨率匹配问题。接下来,我就把这次从零开始配置RK3568双屏同显的完整过程、踩过的坑和最终稳定的方案,详细拆解一遍。

2. RK3568显示系统架构深度解析

在动手修改配置之前,我们必须先搞清楚RK3568的显示子系统是怎么工作的。如果连基本的信号流都理不清,后面修改设备树就是盲人摸象,出了问题也不知道从何查起。

2.1 VOP与Video Port:显示输出的核心引擎

RK3568的显示核心是VOP。你可以把它想象成一个功能强大的“视频分发中心”。它的上游连接着GPU、视频解码器或者CPU,这些模块把处理好的图像数据写入内存中的一块特定区域,叫做帧缓冲区(Framebuffer)。VOP的任务就是定时、按顺序地从这块内存里读取像素数据。

而Video Port(简称VP)是VOP后端的实际输出通道。每个VP在物理上和电气上是独立的,可以配置不同的输出参数(比如分辨率、刷新率、像素格式),并连接到不同的物理接口控制器,比如HDMI TX、MIPI DSI TX、LVDS TX等。根据我查阅的RK3568 TRM(技术参考手册)和实际开发板的原理图,常见的分配关系是:

  • VP0:通常分配给HDMI接口。
  • VP1:可能分配给MIPI DSI接口或LVDS接口。
  • VP2:可能作为第二个MIPI DSI或LVDS,或者eDP接口。

注意:这个分配关系不是绝对的,它取决于芯片的具体型号(比如RK3568和RK3568B可能略有不同)以及开发板设计时的引脚复用(Pin Mux)配置。最准确的信息来源是你所使用的开发板供应商提供的设备树源文件(.dts或.dtsi)。

对于“双屏同显”,我们的目标就是让两个VP(例如VP0和VP1)从同一个帧缓冲区读取数据。这样,无论应用程序在帧缓冲区里画了什么,两个VP都会同步地、一模一样地输出到各自的屏幕上。这与“双屏异显”(扩展桌面)有本质区别,异显需要两个独立的帧缓冲区,由窗口合成器(如Wayland/Weston或Android的SurfaceFlinger)来管理不同窗口在不同屏幕上的位置。

2.2 设备树(Device Tree)的关键作用

在嵌入式Linux中,硬件描述不再硬编码在内核里,而是通过一种叫设备树(Device Tree)的配置文件来声明。它是一个“.dts”格式的文本文件,描述了CPU、内存、总线、外设等所有硬件信息。内核在启动时会解析这个文件,从而知道“我这个板子上有什么硬件,它们怎么连接的”。

对于显示系统,设备树里需要定义以下几个关键节点:

  1. vop节点:描述VOP控制器本身,包括它的寄存器地址、中断号、支持的特性等。
  2. vp子节点:在vop节点下,会有vp0vp1vp2这样的子节点,定义每个Video Port的属性。
  3. 显示接口节点:如hdmidsilvds等节点,描述具体的物理接口。
  4. route节点:这是实现多屏配置的灵魂!它定义了VOP的哪个VP(源)路由到哪个物理接口(目的)。比如,route_hdmi节点就负责把vp0的输出连接到hdmi控制器。
  5. 屏幕时序节点:通常以display-timings命名,定义了具体屏幕的分辨率、刷新率、前后肩等详细时序参数。

我们要实现双屏同显,主要功夫就下在修改和配置这些route节点以及对应的使能状态上。很多开发板厂商(比如资料中提到的迅为)会为了方便用户,把屏幕的使能做成了宏定义,在编译前通过修改一个头文件或配置项就能切换,其底层原理依然是修改设备树中对应节点的status属性(从disabled改为okay)。

3. 双屏同显配置实战:从设备树修改到系统启动

理论铺垫完毕,现在进入实战环节。我以手头这块同时具备HDMI和MIPI DSI接口的开发板为例,目标是让HDMI屏幕和MIPI屏幕显示相同内容。

3.1 环境准备与源码获取

首先,你需要一个完整的RK3568 Linux SDK开发环境。这通常包括:

  • 交叉编译工具链:比如aarch64-linux-gnu-
  • 内核源码:从开发板供应商或Rockchip官方Git仓库获取,确保版本与你的系统匹配。
  • 设备树源文件:位于内核源码的arch/arm64/boot/dts/rockchip/目录下,找到对应你开发板的.dts文件(例如rk3568-evb.dts)以及它包含的.dtsi头文件。

我使用的是供应商提供的SDK,内核版本是5.10。在开始修改前,强烈建议先备份原始的设备树文件。

# 进入内核目录 cd /path/to/your/kernel-source # 备份原始设备树文件 cp arch/arm64/boot/dts/rockchip/rk3568-your-board.dts arch/arm64/boot/dts/rockchip/rk3568-your-board.dts.backup

3.2 定位并修改显示相关设备树节点

这是最核心的一步。我们需要找到并修改两个地方:一是使能第二个屏幕接口,二是正确配置VOP的路由。

步骤一:使能MIPI DSI接口和屏幕节点

默认配置可能只使能了HDMI。我们需要找到MIPI DSI相关的节点,将其状态改为“okay”。通常这些定义在.dtsi文件中。

  1. 打开你的板级设备树文件(如rk3568-your-board.dts),查看它包含了哪些头文件。常见的有rk3568.dtsi(芯片通用定义)和rk3568-xxx-lcd.dtsi(屏幕特定定义)。
  2. 搜索dsimipi_dsi关键词。你会找到类似下面的节点:
    &dsi { status = "disabled"; // 默认可能是关闭的 // ... 其他属性,比如时钟、电源等 };
    status = "disabled";修改为status = "okay";
  3. 接着,找到DSI接口连接的屏幕面板(panel)节点。它可能被定义在另一个文件里,并通过dsi节点的panel子节点引用。确保这个panel节点的status也是okay。同时,核对panel节点内的display-timings是否与你的MIPI屏幕规格书一致,特别是分辨率(hactive,vactive)、时钟频率等。

步骤二:配置VOP路由,实现同显

这是关键中的关键。我们需要配置路由,让两个VP都工作,并且指向同一个显示管线。在RK3568的Linux内核驱动中,通常通过route节点来实现。

  1. 在设备树中搜索route_hdmiroute_dsi(或类似的命名)。它们看起来像这样:
    &route_hdmi { status = "okay"; connect = <&vp0_out_hdmi>; // 表示vp0连接到hdmi }; &route_dsi { status = "disabled"; // 默认可能是关闭的 connect = <&vp1_out_dsi>; // 表示vp1连接到dsi };
  2. 要实现同显,我们需要确保两个VP都启用,并且从同一个VOP主通道获取数据。在RK3568的驱动框架里,通常有一个“主”VP负责获取帧缓冲数据,其他VP可以配置为“克隆”模式。但更常见的做法是在route节点上做文章。有时,你需要检查vop节点本身的配置,看它是否支持多VP输出。
  3. 重要技巧:根据我的实测和社区经验,最可靠的方法是让两个route节点都指向同一个vp_out端点。但这需要驱动支持。另一种更通用的方法是,确保两个VP都绑定到了正确的CRTC(内核显示框架中的显示控制器抽象),并在内核中使能“克隆显示”的功能。这可能需要在内核配置中开启CONFIG_DRM_ROCKCHIP_DUAL_CRTC或类似的选项(具体选项名需查询内核配置菜单)。
  4. 修改后,route_dsistatus应改为okay。最终效果是,系统启动后,vp0vp1都处于活动状态,并分别路由到HDMI和DSI。

步骤三:检查时钟和电源

多启用一个显示接口,可能会增加功耗并需要额外的时钟配置。检查DSI相关的时钟节点(如dsi_in_vp0dsi_in_vp1)是否被正确引用和使能。确保没有时钟冲突。电源域(power-domains)的配置一般由板级设备树处理好,但如果你是自己设计的底板,需要仔细核对。

3.3 编译内核与设备树

修改保存设备树文件后,需要重新编译内核和设备树。

# 设置环境变量,使用交叉编译工具链 export ARCH=arm64 export CROSS_COMPILE=aarch64-linux-gnu- # 加载你板子的默认配置 make rockchip_defconfig # 或你的板子特定defconfig,如 make rk3568-evb.config # 如果需要,可以通过 menuconfig 检查显示相关驱动是否选上 # make menuconfig # 编译内核镜像和设备树 make -j$(nproc) Image dtbs

编译完成后,新的设备树二进制文件(.dtb)会生成在arch/arm64/boot/dts/rockchip/目录下,文件名与你的.dts文件对应(如rk3568-your-board.dtb)。

3.4 烧录与上电测试

将新编译的Image(内核镜像)和.dtb文件更新到开发板的启动分区(如通过SD卡、USB烧录工具或网络TFTP)。具体烧录方法取决于你的开发板引导方式(U-Boot)。

上电启动,观察串口调试信息。在内核启动日志中,重点关注以下关键词:

  • drm: 这是Linux内核的直接渲染管理器,负责所有显示驱动。
  • vophdmidsi: 查看这些驱动是否成功探测(probe)。
  • [drm]: 寻找类似[drm] Initialized[drm] Enabled的信息,以及关于connectorencoderCRTC初始化的日志。
  • 成功标志:如果配置正确,你应该能看到两个显示接口都被成功识别并注册为DRM设备。例如,日志中可能会先后出现HDMI和MIPI-DSI的连接状态信息。

启动进入系统后,使用命令验证:

# 查看DRM设备信息 cat /sys/kernel/debug/dri/0/state # 或使用更直观的工具(如果已安装) fbset -i # 查看帧缓冲信息,但可能只显示主显 # 对于基于DRM的系统,可以尝试 modetest -M rockchip # 此工具需要编译并安装libdrm和modetest

如果一切顺利,两块屏幕应该都亮了,并且显示内容完全相同。

4. 常见问题排查与实战心得

在实际操作中,几乎不可能一次成功。下面是我遇到的一些典型问题及解决方法,希望能帮你快速排雷。

4.1 屏幕不亮或只有一块屏幕亮

这是最常见的问题。请按照以下顺序排查:

  1. 检查设备树语法:使用dtc(设备树编译器)检查修改后的.dts文件是否有语法错误。

    dtc -I dts -O dtb -o test.dtb your-modified.dts 2>&1 | head -20

    任何错误或警告都会在这里显示。

  2. 审查内核启动日志:这是最重要的调试信息源。仔细查看串口输出的内核日志。

    • 驱动未加载:如果根本没看到dsihdmi的probe日志,说明设备树中该节点的status未成功改为okay,或者依赖的父节点(如时钟、电源)有问题。
    • probe失败:如果看到了probe日志,但后面跟着错误(error)或失败(failed),通常是因为资源获取失败,如时钟、GPIO、电源。根据错误信息回溯设备树中相关配置。
    • [drm]日志:关注DRM子系统初始化日志。如果出现failed to bindcannot find crtc等错误,说明VOP路由配置有问题,VP和接口的连接关系不正确。
  3. 确认物理连接和屏幕供电:确保MIPI排线连接牢固,方向正确。有些屏幕需要额外的背光使能(BL_EN)或复位(RST)信号,这些GPIO配置也必须在设备树的panel节点中正确定义。

  4. 时序问题:屏幕点亮但花屏、闪烁或显示不全,大概率是display-timings节点中的参数不对。务必使用屏幕厂商提供的准确时序参数。特别是clock-frequency(像素时钟),hfront-porchhsync-lenhback-porchvfront-porchvsync-lenvback-porch这些值。

4.2 双屏不同步或性能问题

即使两块屏幕都亮了,也可能遇到问题。

  • 内容不同步:如果两块屏幕显示内容有细微撕裂或延迟不一致,这可能是因为两个VP的刷新率(vrefresh)没有完全同步。虽然它们共享帧缓冲,但输出时序是独立的。确保在设备树中为两个routepanel节点配置相同的clock-frequency和垂直刷新率参数。在某些情况下,可能需要在内核驱动层面确保VSync信号的同步。
  • 性能下降:双屏输出意味着VOP需要处理两倍的数据带宽,内存访问压力增大。如果出现动画卡顿,可以尝试:
    • 降低分辨率或刷新率。
    • 检查系统内存带宽是否充足。
    • 在图形应用中使用更高效的渲染方式(如硬件加速)。

4.3 关于“同显”与“异显”的配置区别

很多朋友会混淆。简单总结一下:

  • 同显(克隆): 如本文所述,核心是两个VP输出同一个帧缓冲。配置重点在设备树的VOP路由和VP使能,通常不需要上层合成器做特殊工作。
  • 异显(扩展): 需要两个独立的帧缓冲。这需要显示合成器(如Weston、KWin或Android的Display Manager)支持多输出管理。它负责将不同的应用窗口分配在不同的帧缓冲/CRTC上。在设备树层面,你需要正确配置两个独立的route,并将两个VP都使能。然后,在用户空间启动支持多显示器的桌面环境或合成器。

我的实操心得

  1. 善用调试文件系统/sys/kernel/debug/dri/目录下的文件是宝库。特别是0/state文件,它能打印出当前DRM设备的状态,包括CRTC、Encoder、Connector的绑定关系,一目了然。
  2. 从简入手:先确保单屏(比如HDMI)工作正常,然后再添加第二个屏幕。分步调试能极大降低复杂度。
  3. 版本至关重要:RK3568的显示驱动在不同内核版本(如4.19, 5.10, 6.1)间可能有较大差异。你从网上找到的配置片段,可能只适用于特定内核版本。最好以你当前SDK中的设备树为基准进行修改。
  4. 理解“连接”关系:设备树中的connect = <&vp0_out_hdmi>;这类语句,实际上是在描述一个物理连接图vp0_out_hdmi是一个预定义的端点(endpoint),它已经在芯片级的.dtsi文件中将VP0和HDMI控制器连接起来。你的板级设备树只是通过route节点选择启用这条通路。
  5. 功耗考虑:同时点亮两块屏幕,尤其是高分辨率的屏幕,会显著增加功耗和发热。在产品化设计中,需要做好电源规划和散热设计。

配置RK3568双屏同显的过程,是一个深入理解Linux DRM显示框架和芯片特定设计的绝佳机会。它不仅仅是改几个配置开关,更是对硬件链路、驱动模型和系统协同工作的一次梳理。当你看到两块屏幕同时亮起并完美同步时,那种成就感是对之前所有调试工作的最好回报。希望这篇详细的记录能为你扫清障碍,顺利实现你的多屏显示需求。如果在实践中遇到新的问题,不妨多查阅内核文档(Documentation/devicetree/bindings/display/rockchip/)和社区论坛,那里的讨论往往能带来意想不到的启发。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询