
1. 项目概述从单屏到多屏的嵌入式显示进阶最近在折腾一块基于瑞芯微RK3568芯片的评估板核心目标是想把它变成一个能同时驱动多个显示器的“多面手”。无论是做数字标牌、自助终端还是工控HMI界面多屏显示能力都是个硬需求。我手头这块评估板原生支持丰富的显示接口正好拿来研究一下如何实现“三屏同显”三个屏幕显示一模一样的内容和“三屏异显”三个屏幕各自独立显示不同内容这两种经典模式。RK3568这颗芯片在嵌入式圈子里口碑不错四核A55加上独立的NPU和GPU应付多路显示解码和渲染理论上绰绰有余。但理论归理论从硬件连接到软件配置再到系统层面的调试每一步都有不少细节需要注意。网上关于单屏驱动的资料很多但系统性地讲解多屏配置尤其是像三屏这样相对复杂的场景往往语焉不详或者只给个命令了事背后的原理和踩坑经验很少提及。这篇文章我就结合自己的实操过程把RK3568评估板实现三屏同显、异显的完整方案拆解清楚。我会从硬件接口的识别与连接讲起深入到Linux内核特别是DRM/KMS框架的配置与调试最后通过具体的应用层案例来演示效果。无论你是正在评估该方案的项目工程师还是对Linux图形子系统感兴趣的开发者希望这些一手经验能帮你少走弯路。2. 硬件准备与接口特性解析实现多屏显示第一步永远是搞清楚硬件底子。RK3568的显示子系统能力决定了我们方案的“天花板”。2.1 RK3568显示子系统核心能力RK3568内部集成的是ARM Mali-G52 GPU但更关键的是它的视频处理单元VPU和显示控制器VOP。对于多屏输出我们需要重点关注VOPVideo Output Processor。根据官方数据手册RK3568通常包含两个独立的VOPVOPB和VOPL有些资料称VOP0和VOP1。每个VOP可以独立驱动一个显示管道这意味着在硬件层面它支持至少两路独立的显示输出。那么如何实现三路输出呢这里就涉及到一个重要概念显示接口复用与分配。RK3568的物理显示接口非常丰富一般包括2 x HDMI/eDP通常是功能完整的接口支持高分辨率。1 x MIPI DSI用于连接液晶屏。1 x LVDS常见于工控屏。1 x RGB/MCU较老的接口。关键点在于这些物理接口并不是直接、独占地连接到某个VOP的。它们是通过一个内部的“显示接口复用器”连接到VOP的输出端。因此我们可以将一个VOP的输出通过配置路由到不同的物理接口上。但是一个VOP在同一时间只能驱动一个物理接口。要实现三路同时输出就必须启用两个VOP并且将其中一个VOP的输出“拆分”或通过其他方式扩展。常见的三屏方案硬件连接思路VOPB VOPL 双路独立输出这是最直接的方式。例如VOPB驱动HDMI0VOPL驱动eDP。这样已经有两路独立信号了。第三屏的实现第三路信号通常需要一些“技巧”。方案A通过MIPI DSI如果评估板的MIPI DSI接口是独立的并且屏端支持这可以作为一个独立的显示通道。但需要确认该DSI控制器是挂载在哪个VOP下的或者它本身是否是一个独立的显示接口单元。方案B使用显示扩展芯片这是更通用和稳定的方法。例如使用一颗像龙迅Analogix的ANX7625或硅谷数模Synaptics的VMM视频多路复用器芯片将一路DP或eDP信号转换成两路HDMI。这样从SoC的一个eDP接口出来经过扩展芯片就能得到两个独立的HDMI显示。这在很多高端开发板上都有应用。方案C软件克隆同显对于“同显”需求可以在应用层或驱动层将同一个帧缓冲区framebuffer的内容发送给多个接口但这通常需要驱动和固件的特殊支持。在我的评估板上其设计是HDMI0和eDP作为主要接口另外通过一颗MIPI DSI转LVDS的芯片提供了一个LVDS接口。因此我的三屏连接方式是HDMI0接显示器A、eDP接显示器B、LVDS接屏幕C。注意在连接硬件前务必查阅你手中评估板的《硬件用户手册》或原理图确认各个显示接口的物理属性和电气标准如HDMI是1.4还是2.0eDP的通道数LVDS的电压以及它们与SoC内部VOP的映射关系。盲目连接可能导致接口不工作甚至损坏。2.2 系统环境与内核配置确认硬件连接好后上电启动系统。首先需要通过命令行确认系统是否正确识别了所有显示接口和对应的驱动。# 1. 查看内核中关于DRMDirect Rendering Manager的日志这是Linux图形显示的核心 sudo dmesg | grep -i “drm\|vop\|hdmi\|dsi” # 2. 使用lsmod查看已加载的显示相关内核模块 lsmod | grep rockchip # 通常会看到 rockchipdrm, dw_hdmi_rockchip, panel_simple 等模块 # 3. 使用DRM工具集需安装libdrm-tools查看当前连接的显示设备 sudo apt-get install libdrm-tools modetest -M rockchip -D # 这个命令会列出所有显示管道Planes、CRTCs、Connectors。Connectors的状态connected/disconnected直接反映了系统是否识别到物理连接。执行modetest -D后你会看到类似下面的输出简化版Connectors: id encoder status name size (mm) modes encoders 37 36 connected HDMI-A-1 509x286 7 36 modes: index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot) #0 1920x1080 60.00 1920 2008 2052 2200 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: preferred, driver 38 0 connected eDP-1 346x194 1 0 #0 1920x1080 60.00 ... 39 0 connected LVDS-1 217x135 1 0 #0 1024x600 60.00 ...这个输出至关重要。它告诉我们系统识别到了三个连接状态为“connected”的接口HDMI-A-1, eDP-1, LVDS-1并且列出了它们各自支持的最佳显示模式。如果某个接口显示为disconnected但物理线缆已接好就需要排查硬件连接、线缆质量或供电问题。内核配置要点要实现多屏内核编译时必须确保相关驱动已内置或编译为模块。关键配置项位于make menuconfig中CONFIG_DRM_ROCKCHIPyCONFIG_DRM_DW_HDMI_ROCKCHIPy(用于HDMI)CONFIG_DRM_PANEL_SIMPLEy(用于eDP/LVDS面板)CONFIG_DRM_ROCKCHIP_DSIy(如果使用MIPI DSI)CONFIG_DRM_ROCKCHIP_LVDSy(如果使用LVDS)通常评估板提供的SDK或官方镜像已经配置好了这些。自行编译内核时需仔细核对。3. 显示模式配置设备树与DRM框架在Linux系统中显示设备的硬件资源分配和初始状态是由设备树Device Tree来描述的。而运行时管理则交给DRM/KMS框架。3.1 设备树DTS关键配置解析设备树文件.dts或.dtsi定义了VOP与物理接口的映射关系。这是多屏驱动的“蓝图”。我们需要找到对应评估板的dts文件如rk3568-evb.dtsi。关键配置节点通常包括vop节点定义VOPB和VOPL。display_subsystem节点这是Rockchip平台特有的节点用于管理显示子系统并在这里指定每个接口如hdmi, edp, lvds默认由哪个VOP驱动。各接口节点如hdmiedplvdsdsi等它们通过ports和remote-endpoint属性与vop的端口连接。一个简化的配置示例// 在 vop 节点中定义端口 vopb { status “okay”; assigned-clocks cru DCLK_VOP0_SRC; assigned-clock-parents pmucru PLL_HPLL; ports { vopb_out: port0 { reg 0; #address-cells 1; #size-cells 0; // HDMI0 连接在 VOPB 的端口0 vopb_out_hdmi: endpoint0 { reg 0; remote-endpoint hdmi_in_vopb; }; // eDP 也可以连接在 VOPB 的另一个端口如果支持 vopb_out_edp: endpoint1 { reg 1; remote-endpoint edp_in_vopb; }; }; }; }; hdmi { status “okay”; ports { hdmi_in: port0 { reg 0; hdmi_in_vopb: endpoint { remote-endpoint vopb_out_hdmi; }; }; }; };配置核心remote-endpoint像一根虚拟的导线将VOP的输出端口与物理接口的输入端口连接起来。要实现三屏就必须确保三个物理接口的endpoint都正确连接到了有效的VOP输出端口上并且没有冲突一个VOP端口不能同时驱动两个接口。实操心得修改设备树是底层开发常见操作。建议先备份原文件每次只修改一个地方编译成dtb后通过启动加载器如U-Boot单独加载测试确认无误后再烧录到固件中。使用fdtdump工具可以反编译dtb文件方便查看最终生效的设备树结构。3.2 DRM/KMS框架与用户空间工具内核驱动配置好后用户空间通过DRM的KMSKernel Mode SettingAPI来控制显示。但我们通常不直接写代码调用API而是使用工具。xrandr (X11环境)如果系统运行的是X Window System如带有桌面环境的系统xrandr是配置多屏的首选工具。它可以列出显示器、设置分辨率、刷新率以及布局同显/异显。# 列出所有显示输出 xrandr # 设置三屏扩展模式异显假设输出名为HDMI-1, eDP-1, LVDS-1 xrandr --output HDMI-1 --auto --pos 0x0 --output eDP-1 --auto --right-of HDMI-1 --output LVDS-1 --auto --right-of eDP-1 # 设置三屏克隆模式同显 xrandr --output HDMI-1 --auto --output eDP-1 --same-as HDMI-1 --output LVDS-1 --same-as HDMI-1Wayland环境更新的系统可能使用Wayland合成器如Weston KDE的KWin GNOME的Mutter。Wayland下多屏配置通常由合成器的配置文件或图形界面设置完成。例如Weston可以通过weston.ini配置文件来定义输出。DRM直接操作无桌面环境对于纯命令行或嵌入式GUI如Qt EGLFS需要直接操作DRM。这更复杂但灵活性最高。可以通过libdrm库编程实现或者使用modetest工具进行测试。# 使用modetest设置一个简单的显示模式示例实际命令更复杂 # 此命令通常用于测试和调试而非生产环境配置 modetest -M rockchip -s 3740:1920x1080 -s 3841:1920x1080 -s 3942:1024x600 # 其中37,38,39是connector ID40,41,42是CRTC ID需要根据实际查询结果替换。选择哪种方式有桌面直接用xrandr或系统设置界面最简单。无桌面运行Qt/Wayland应用配置Wayland合成器。无桌面裸跑应用或自研GUI需要集成libdrm到应用中直接管理CRTC、Plane和Framebuffer实现最大控制权。4. 三屏同显方案实现与演示“同显”即镜像模式三个屏幕显示完全相同的内容。这在数字广告牌、会议演示中很常见。4.1 基于X11/xrandr的克隆模式配置在带有X11桌面如Xfce, LXDE的系统上这是最快捷的方法。识别输出名称首先运行xrandr命令记下三个已连接输出的名称例如HDMI-1eDP-1LVDS-1。应用克隆模式# 假设以HDMI-1为主显示器将其他两个设置为与它克隆 xrandr --output HDMI-1 --auto --primary xrandr --output eDP-1 --auto --same-as HDMI-1 xrandr --output LVDS-1 --auto --same-as HDMI-1或者用一条命令xrandr --output HDMI-1 --auto --output eDP-1 --same-as HDMI-1 --output LVDS-1 --same-as HDMI-1分辨率处理克隆模式下所有屏幕必须使用相同的分辨率。系统通常会选择所有显示器都支持的最高通用分辨率。如果某个显示器如LVDS屏原生分辨率较低1024x600而HDMI显示器是1080p直接克隆会导致LVDS屏无法正常显示或显示缩放异常。解决方案A在xrandr命令中强制指定一个大家都能支持的分辨率。xrandr --output HDMI-1 --mode 1024x768 --output eDP-1 --same-as HDMI-1 --output LVDS-1 --same-as HDMI-1解决方案B让X Server进行缩放。但这可能带来性能开销和模糊。可以使用--scale或--transform参数但兼容性不佳。注意事项X11下的克隆模式实际上是由X Server将同一个屏幕的图形内容复制多份分别发送给不同的驱动。这可能会增加GPU的负载尤其是当分辨率很高时。如果出现卡顿可以尝试降低分辨率和刷新率。4.2 基于DRM底层框架的克隆实现在没有X11的嵌入式环境中需要在应用层或中间件层实现克隆。原理是创建一个帧缓冲区Framebuffer然后将这个Framebuffer同时绑定到多个CRTC每个CRTC对应一个显示管道上。简化后的逻辑伪代码// 1. 打开DRM设备 drm_fd open(“/dev/drm/card0”, O_RDWR); // 2. 获取资源包括connector, encoder, crtc drmModeRes *res drmModeGetResources(drm_fd); // 3. 找到三个已连接的connector及其对应的crtc // 4. 创建一个FramebufferFB drmModeAddFB2(...); // 创建FB关联到一块图形缓冲区GEM Buffer // 5. 将同一个FB设置给三个CRTC for (每个crtc) { drmModeSetCrtc(drm_fd, crtc_id, fb_id, 0, 0, connector_id, 1, mode); } // 6. 后续渲染内容到与FB关联的图形缓冲区三个屏幕就会同步更新。性能考量这种方式下GPU只需要渲染一次然后将渲染结果Framebuffer同时喂给多个显示控制器效率比X11的软件复制更高。但需要确保SoC的显示控制器的带宽和内存访问能力能承受同时读取同一块缓冲区的压力。4.3 同显方案演示与验证为了验证效果我写了一个简单的测试程序使用OpenGL ES通过Mesa库在Framebuffer上绘制一个移动的彩色方块。环境准备确保Mesa库和OpenGL ES开发包已安装。编译运行测试程序程序初始化DRM和GBMGeneric Buffer Management创建EGL上下文然后在一个循环中渲染并交换缓冲区。观察现象三个屏幕应同步显示完全相同的动画内容无肉眼可见的延迟差异。常见问题排查同显问题只有两个屏幕亮第三个黑屏。排查检查modetest -D输出确认第三个connector状态是否为connected。检查设备树中第三个接口的status是否为“okay”以及remote-endpoint连接是否正确。问题克隆后屏幕闪烁或撕裂。排查可能是刷新率不同步。确保在drmModeSetCrtc时为每个CRTC设置完全相同的drmModeModeInfo尤其是时钟、时序参数。在X11下尝试使用--rate参数指定统一的刷新率如60Hz。问题性能低下动画卡顿。排查使用top或htop观察CPU和GPU负载。同显时GPU负载应接近单屏。如果过高检查是否在X11下并尝试切换到DRM直接渲染模式。也可能是分辨率过高尝试降低分辨率测试。5. 三屏异显方案实现与演示“异显”即扩展模式每个屏幕是桌面空间的一部分可以独立显示不同应用窗口。这对多任务操作、监控大屏非常有用。5.1 基于X11/xrandr的扩展桌面配置在X11下配置扩展桌面相对直观。# 假设我们希望三台显示器水平排列 # HDMI-1在左边eDP-1在中间LVDS-1在右边 xrandr --output HDMI-1 --auto --pos 0x0 xrandr --output eDP-1 --auto --pos 1920x0 --right-of HDMI-1 xrandr --output LVDS-1 --auto --pos 3840x0 --right-of eDP-1 # 这里3840 1920(HDMI) 1920(eDP)。LVDS屏分辨率是1024x600但它的“桌面空间”起始位置在3840x0。布局逻辑--pos参数设置了该显示器左上角在虚拟桌面坐标系中的位置。--right-of/--left-of/--above/--below参数可以辅助定位但最终由--pos的坐标决定。你可以创建复杂的布局比如L形、上下排列等。分辨率混合在扩展模式下每个显示器可以使用其最佳分辨率这是相比同显的一大优势。系统会自动管理一个大的虚拟桌面窗口管理器负责将应用窗口在合适的显示器上显示。5.2 基于Wayland合成器的多屏管理以Weston为例需要在配置文件weston.ini中定义输出[output] nameHDMI-A-1 mode1920x108060 pos0,0 [output] nameeDP-1 mode1920x108060 pos1920,0 [output] nameLVDS-1 mode1024x60060 pos3840,0重启Weston合成器后就会按照配置创建扩展桌面。Wayland协议本身对多屏有更好的原生支持避免了X11下一些奇怪的指针跨越问题。5.3 应用层多窗口管理实战异显模式下如何让应用程序的窗口显示在指定的屏幕上这里以常见的应用为例。SDL2应用SDL2提供了设置窗口显示位置的功能。// 在创建窗口前设置窗口位置 SDL_SetWindowPosition(window, screen_x, screen_y); // 其中screen_x, screen_y是目标屏幕在虚拟桌面中的坐标。 // 例如要显示在中间的eDP-1屏幕起始x1920可以设置x1920100留点边距。Qt应用对于Qt Widgets应用可以使用QWidget::move()。// 假设知道第二个屏幕的几何信息 QScreen *secondScreen QGuiApplication::screens().at(1); // 索引从0开始 QRect screenGeometry secondScreen-geometry(); myWindow-move(screenGeometry.topLeft() QPoint(50, 50)); // 移动到第二个屏幕并偏移对于Qt Quick应用可以使用Window元素的screen属性或x,y属性。命令行工具像mpv这样的播放器可以使用--geometry参数指定窗口位置。mpv --geometry 1920x108019200 video.mp4 # 在第二个屏幕(起始x1920)全屏播放多屏信息获取编程时需要动态获取屏幕信息。在X11下可以通过Xinerama或XRandR扩展查询。在Wayland下通过wl_output全局对象。Qt和SDL等高级框架已经封装了这些接口使用QGuiApplication::screens()或SDL_GetNumVideoDisplays()即可。5.4 异显方案演示与系统优化我设计了一个演示场景在HDMI屏幕上运行一个硬件解码的视频播放器测试VPU在eDP屏幕上运行一个3D旋转立方体测试GPU在LVDS屏幕上显示系统资源监控如htop。演示步骤配置好三屏扩展模式。在终端1通过SSH或CtrlAltF2切换到另一个tty在HDMI屏幕对应的DISPLAY上启动视频播放。在终端2在eDP屏幕对应的DISPLAY上启动OpenGL ES测试程序。在终端3将htop或其他监控工具窗口移动到LVDS屏幕。性能监控与优化内存带宽同时渲染三个不同场景对内存带宽压力较大。使用sudo cat /sys/kernel/debug/dri/0/vopb/state路径可能不同可以查看VOP的状态和带宽使用情况。CPU/GPU负载使用mpstat和gpustat如果支持工具监控。确保没有核心达到100%占用否则会出现卡顿。热管理长时间高负载运行RK3568可能会发热降频。观察/sys/class/thermal/thermal_zone*/temp文件确保温度在可控范围内通常80°C。必要时可以加装散热片或风扇。常见问题排查异显问题鼠标无法从一个屏幕移动到另一个屏幕。排查在X11下检查xrandr输出的虚拟桌面总尺寸是否正确覆盖了所有屏幕的区域。使用xrandr --prop查看每个输出的panning属性。在Wayland下这通常不是问题。问题某个屏幕上的应用渲染异常或黑屏。排查确认该应用是否支持多屏环境以及是否正确地指定了显示设备或窗口位置。检查应用日志或使用strace跟踪其系统调用看是否有打开错误的DRM设备节点或设置错误的显示参数。问题系统启动后异显布局不生效或混乱。排查将xrandr命令写入启动脚本如~/.xprofile或/etc/X11/Xsession.d/下的自定义脚本。在Wayland下确保合成器配置文件正确。对于无桌面的系统需要编写一个守护进程在启动时通过libdrm API配置CRTC布局。6. 高级话题与疑难杂症处理在基本功能调通后我们可能会遇到一些更深入的问题。6.1 混合分辨率下的UI适配与缩放当三个屏幕分辨率不一致时如1080p, 1080p, 1024x600UI适配成为挑战。Wayland环境Wayland协议和现代合成器如GNOME的Mutter KDE的KWin对HiDPI和混合DPI有较好的支持。可以在合成器设置中为每个显示器单独设置缩放比例scale factor。例如将1080p屏幕缩放设为1.0将高分辨率4K屏幕缩放设为2.0。但应用需要支持Wayland的viewport协议才能完美适配。X11环境X11的全局缩放支持很差。通常的变通方案是使用所有显示器中最低的公共分辨率。在应用层面处理。例如Qt应用可以通过设置QT_SCREEN_SCALE_FACTORS环境变量为每个屏幕指定不同的缩放因子如QT_SCREEN_SCALE_FACTORSHDMI-1:1;eDP-1:1;LVDS-1:0.8。但这需要应用使用Qt的高DPI支持。使用xrandr --scale进行整体缩放但这会导致模糊不推荐。建议对于嵌入式产品尽量在设计阶段统一显示器的分辨率。如果无法统一建议在UI设计时采用响应式布局或者为低分辨率屏幕设计专门的界面版本。6.2 显示旋转与特殊显示模式某些场景下屏幕可能需要旋转90度竖屏显示。DRM/KMS层面可以在drmModeSetCrtc时在drmModeModeInfo的flags中设置DRM_MODE_FLAG_ROTATE_90等标志。但需要硬件和驱动支持旋转。X11层面使用xrandr --rotate left|right|inverted。xrandr --output LVDS-1 --rotate left应用层面如果硬件不支持可以在应用渲染时进行矩阵变换来实现旋转但这会消耗GPU资源。特殊模式如低刷新率节能、高动态范围HDR等需要显示器、线缆、驱动、应用全链路支持。RK3568的HDMI接口如果版本是2.0理论上支持4K60和HDR但需要仔细核对内核驱动配置和设备树中的PHY配置。6.3 稳定性测试与长期运行建议多屏显示系统对稳定性要求较高。热插拔测试在系统运行时拔插HDMI线缆观察系统日志dmesg -w和应用反应。良好的驱动应该能检测到连接状态变化并通知桌面环境或应用。长时间压力测试让系统连续运行24-72小时播放视频或运行图形演示。监控是否有内存泄漏free -h、GPU驱动是否崩溃查看内核日志dmesg | grep -i gpu\|drm\|error、显示是否出现花屏或闪烁。电源与干扰多屏同时工作尤其是高分辨率屏幕功耗较大。确保评估板电源适配器功率充足建议12V/3A以上。强电磁干扰可能导致LVDS或eDP信号异常注意线缆屏蔽和走线。固件与驱动更新关注Rockchip官方GitHub仓库或芯片供应商的SDK更新有时会修复显示相关的Bug或提升性能。折腾RK3568评估板的三屏显示从硬件查看到软件调试是一个典型的嵌入式系统集成过程。最大的体会是“硬件是基础文档是关键调试靠耐心”。官方数据手册和内核文档Documentation/devicetree/bindings/display/rockchip/是解决问题的第一手资料但往往需要结合源码和实际调试信息来理解。对于想快速上手的开发者我的建议是先从官方提供的标准镜像和配置开始确保单屏、双屏工作正常。然后再根据自己的硬件逐步修改设备树每次只动一个地方并用modetest工具验证。遇到问题时善用dmesg、kernel log以及DRM的debugfs接口如/sys/kernel/debug/dri/0/下的文件来获取底层信息。最后多屏显示的最终体验不仅取决于驱动更取决于上层应用和图形框架的适配。在项目规划早期就需要将多屏交互逻辑和UI布局纳入设计考虑这样才能做出真正好用的产品。