十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RK3568+OpenHarmony多路显示移植实战:从设备树到异显

RK3568+OpenHarmony多路显示移植实战:从设备树到异显 开头先交代背景。我这段时间一直在搞一块基于 RK3568 的商显方案主芯片选了瑞芯微 RK3568系统基于开源鸿蒙 OpenHarmony 标准系统做整机定制。需求倒不复杂一台设备要同时带一块 HDMI 大屏做广告/信息发布一块 MIPI 触摸屏给操作员本地交互后面还想通过 BT1120 往外送一路视频给后级处理设备。说白了就是要把 RK3568 的多路显示能力在 OpenHarmony 上真正“跑起来、亮起来、各干各的”。这类需求在工业 HMI、自助终端、会议平板、充电桩、楼宇对讲上都特别常见。这篇文章我会按实际移植顺序来写先把 RK3568 显示子系统和 OpenHarmony 显示架构的对应关系理清楚再讲内核 Kconfig 和设备树怎么配然后到 OpenHarmony 侧的多屏适配最后是联调和问题排查。全程会带上我实际操作的命令、改过的节点和踩过的坑尽量做到你拿一台 RK3568 开发板就能照着复现。这次移植适合谁看主要是做 OpenHarmony 系统适配、内核/设备树开发的工程师其次是做整机方案的软硬件工程师他们需要知道多屏时序、带宽、引脚复用这些硬约束。如果你是刚接触 OpenHarmony 的嵌入式开发者也可以从这里入手因为显示子系统是上手操作系统移植最好的“骨架”之一。1. 需求拆解RK3568OpenHarmony多路显示移植到底在移什么1.1 先搞清楚RK3568能输出哪几路画面RK3568 是瑞芯微一颗很典型的四核 A55 平台它的显示控制器不是单个 VOP 出口而是分成了两个独立的 Video Output Processor在 Rockchip 内核驱动里通常叫 VOPB 和 VOPL。这两个 VOP 可以独立使能、独立配时序各自挂不同的显示接口这是“多路显示”的硬件基础。RK3568 对外引出的显示接口大致有接口类型典型分辨率常见应用场景HDMI 2.0最高 4K60广告机、会议屏、电视机eDP 1.3最高 2560x1600笔记本模组、一体机、高端 HMIMIPI DSI两路每路常见 1080P60车载屏、门禁、平板LVDS1080P60工控屏、电梯面板BT1120/并行接口由外部转接芯片决定视频采集、工业相机、后级处理这也就意味着一块 RK3568 单芯片做“HDMI MIPI DSI BT1120”的三路输出在硬件管脚上是完全可以支撑的。关键是系统侧要能同时枚举出三个 connector并且在 OpenHarmony 的图形合成器里正确识别它们。多路显示通常分“同显”和“异显”两种模式。同显就是把同一画面复制到多个屏幕适合展览展示异显是每个屏幕显示不同内容适合“主屏放业务界面、副屏放操作面板”的整机设计方案。我在这个项目里要的是异显HDMI 出去的是面向客户的大屏内容MIPI 屏是本地运维操作界面BT1120 那一路则是给后端图像处理设备的原始视频源。1.2 从系统框架看移植的三个层级在 OpenHarmony 上做显示移植不是只改一个 dts 文件就完事。整个图形链路从底层到上层大致是内核 DRM 驱动 - HDF 显示适配层 - RenderService/Composer 合成 - 应用侧多屏接口。任何一个层级没对齐表现出的症状都是“屏幕不亮”或者“亮但没内容”但排查方向完全不同。内核 DRM 层是最先要打通的。VOPB/VOPL 驱动要能初始化HDMI、DSI、BT1120 这些 encoder/connector 要通过设备树被正确 probe最终在 /dev/dri/card0 上挂出对应的 DRM device。这一层如果没做好上层图片渲染得再好也送不出去。HDFHardware Driver Foundation显示适配层是 OpenHarmony 特有的。它相当于把内核 DRM 的能力封装成标准的 Display HDI 接口供系统的 RenderService 调用。RK3568 在 OpenHarmony 生态里比较成熟官方和一些开发板厂商已经把这层的通用驱动做好了我们移植的重点通常是确认它读到了哪个 connector、把哪一路作为主屏。最上层是 RenderService/Composer 的多屏管理。OpenHarmony 从 3.2 版本开始对多屏的支持逐渐完善系统可以通过 DisplayManager 的接口枚举所有显示设备设置主屏、副屏、扩展模式或镜像模式。做系统适配时我们一般会在 init 或者开机脚本里把默认主屏顺序固定住避免每次升级后 HDMI 和 MIPI 的显示顺序随机变化。1.3 平台选择与版本基线我这次用的基线是 OpenHarmony 4.1 Release 对应的 RK3568 标准系统代码内核是 Linux 5.10。选这个版本的原因很直接RK3568 在这条分支上被验证得最多Rockchip 官方 SDK 里关于 display 的 dts 和 Kconfig 可以直接参考踩坑资料也相对好找。如果你刚拿到一块新的 RK3568 开发板建议先别急着定制先把官方镜像烧进去确认单屏显示正常再去动设备树做多屏。多屏移植的难度不是“加起来”而是“排列组合”。HDMI 单独能亮、MIPI 单独能亮不代表两个同时开就能各显各的这和 VOP 分配、时钟、带宽、GPIO 复用都有关系。我后面会专门讲这些联动问题。2. 环境准备内核Kconfig与显示驱动依赖一个都不能漏2.1 编译环境与代码基线确认OpenHarmony 的编译环境和普通嵌入式 Linux 不太一样它走的是一套基于 illumos/clangGN 的构建系统。我习惯用一台 32GB 内存以上的 Ubuntu 22.04 服务器做全量编译RK3568 标准系统首次编译大概需要半小时到一小时和机器磁盘性能关系很大。代码拉取可以按 OpenHarmony 官方 release 文档操作用 repo 把 manifest 拿到手重点确认三个仓库vendor下的对应开发板工程、device/board下的板级配置、kernel/linux分支对应的内核版本。这三个仓库必须和同一个版本基线匹配否则很容易出现“内核起来了但 HDF 驱动版本对不上”的问题。一个很实用的验收习惯先不改任何代码直接编译烧录官方镜像用 HDMI 接一台 1080P 显示器确认系统能正常开机进桌面。如果这一步都起不来说明你的环境/烧录流程还有问题不要带着未知因素去改显示配置。2.2 显示相关的内核Kconfig逐项核对RK3568 显示移植最先踩的坑往往不是设备树写错而是内核 .config 里根本没编译对应的显示驱动。移植前请先确认下面这些配置项是打开的配置项作用漏配的现象CONFIG_DRM_ROCKCHIPRockchip DRM 主驱动/dev/dri 不出现CONFIG_ROCKCHIP_DW_HDMIHDMI 控制器驱动HDMI 无输出、dmesg 无 HDMI 相关日志CONFIG_ROCKCHIP_DW_MIPI_DSIMIPI DSI 控制器驱动DSI 屏黑屏、无 DSI 日志CONFIG_ROCKCHIP_ANALOGIX_DPeDP 控制器驱动eDP 屏不亮CONFIG_DRM_PANEL_SIMPLE通用 panel 支持dts 里的 simple-panel 节点无法 probeCONFIG_BACKLIGHT_PWMPWM 背光驱动屏幕能出画面但背光不亮修改方式有几种最干净的是直接改内核 defconfig。以 RK3568 为例路径通常在kernel/arch/arm64/configs/rockchip_linux_defconfig加上对应配置后重新编译内核。改完编译后务必在 ./out 内核产物里检查一遍.config确认配置真正生效了不要只看你改了 defconfig 就以为一定进了。我见过一些同事漏了 CONFIG_BACKLIGHT_PWM结果 HDMI 屏正常MIPI 屏亮度一直为 0黑漆漆一片。这个配置很容易被忽略因为表现上像背光硬件坏了。2.3 先跑通一组基线显示配置在配置全开之后我建议先做一次“最小显示验证”。不碰多屏不改复杂 panel先用默认 dts 把开发板原装的那块屏点亮。验证方法很简单烧录编译好的 boot 和系统镜像hdc shell连接开发板执行ls /sys/class/drm/确认能看到类似card0-HDMI-A-1或card0-DSI-0的节点执行dmesg | grep -iE drm|hdmi|dsi看有没有报错和链路建立日志。这一步通过后再进入多屏设备树改造。不要试图一步到位把三路显示同时配好那样出了问题根本不知道是哪个节点的问题。3. 设备树配置三路显示节点从零到亮屏3.1 先理清RK3568显示硬件的拓扑关系RK3568 的设备树里显示相关的节点拓扑可以用一句话概括display_subsystem是总目录下面挂 VOPB/VOPL 两个显示控制器每个 VOP 通过 port 与不同的 encoder 连接encoder 再接对应的 connector。以官方 Linux SDK 为例常见的节点有vopb、vopl、hdmi、dsi0、dsi1、edp、bt1120还有一大堆route_hdmi、route_dsi0这类路由节点。很多移植失败的根因是只开了hdmi { status okay; }却没开对应的route_hdmi。这在 Rockchip 的驱动设计里是专门的控制开关route_xxx节点决定某个显示接口和哪个 VOP 绑在一起status okay表示这个显示通路要被激活。二者缺一不可。不同 SDK 版本之间节点命名会有差异。比如有的版本是hdmi_in_vp0有的直接是route_hdmi { connect vp0_out_hdmi; };。我建议以你手头 SDK 里arch/arm64/boot/dts/rockchip/下现成的 evb dts 文件为参照不要盲目照抄社区里别的版本的写法。3.2 HDMI输出节点配置参考下面这段是我在这台设备上使用的 HDMI 相关节点配置基于常见 RK3568 SDK 整理节点名以你实际 SDK 为准hdmi { status okay; }; hdmi_in_vp0 { status okay; }; route_hdmi { status okay; connect vp0_out_hdmi; }; hdmi_sound { status okay; };这段配置的含义是把 HDMI 控制器挂到 VP0 上并激活 HDMI 路由。hdmi_sound开不开取决于你有没有用 HDMI 音频我用到的场景不需要音频但保留也没问题。如果 HDMI 插上后分辨率不对或者始终以低分辨率输出常见原因是显示器的 EDID 读取失败。可以在内核日志里看drm相关输出确认有没有EDID读取记录。也可以在 dts 里给 HDMI 节点加上固定的display-timings或者允许驱动使用video参数强制指定分辨率不过这是我后面推荐的“最后手段”正常情况应该优先让 EDID 自动识别。3.3 MIPI DSI屏的配置与背光控制MIPI DSI 屏的配置比 HDMI 复杂因为面板的时序、初始化序列、背光、复位 GPIO 全都要在设备树里描述清楚。我的 MIPI 屏是一块常见的 1080P IPS 屏驱动 IC 本身不需要复杂的初始化序列所以我直接用 simple-panel 节点加 display-timings/ { backlight: backlight { compatible pwm-backlight; pwms pwm4 0 25000 0; brightness-levels 0 20 40 80 120 160 200 255; default-brightness-level 4; power-supply vcc3v3_lcd0_n; status okay; }; panel: panel { compatible simple-panel; backlight backlight; enable-gpios gpio0 RK_PC6 GPIO_ACTIVE_HIGH; display-timings { native-mode timing0; timing0: timing0 { clock-frequency 148500000; hactive 1920; hback-porch 148; hfront-porch 88; hsync-len 44; vactive 1080; vback-porch 36; vfront-porch 4; vsync-len 5; hsync-active 0; vsync-active 0; de-active 0; pixelclk-active 0; }; }; status okay; }; }; dsi0 { status okay; panel0 { compatible simple-panel; reg 0; backlight backlight; }; ports { port1 { reg 1; dsi0_out: endpoint { remote-endpoint vp0_out_dsi0; }; }; }; };这里提两个容易出错的细节。第一pwm4的25000是 PWM 周期单位是纳秒对应 40kHz。背光频率太低会听到电流声太高又可能对触摸屏产生干扰我用 20kHz 到 40kHz 之间比较稳具体看你屏厂推荐值。第二enable-gpios这个复位/使能引脚的时序非常重要如果驱动 GPIO 被复用成了别的功能屏幕就会出现“初始化了但一直黑”的情况。VOP 的分配这里也要注意如果 HDMI 已经占了 VP0DSI 那一路建议挂到 VP1否则两路共用一个 VOP带宽和扫描时序容易互相干扰。不同内核版本的 route 写法不一样我用的是vp0_out_dsi0这种 endpoint 连接方式你那边可能是dsi0_in_vp1之类的节点原理是一样的。3.4 eDP屏与BT1120的补充思路eDP 屏的配置和 DSI 很像也需要 panel 节点、背光节点、eDP 控制器节点以及路由节点。区别在于 eDP 有 Link Rate、Lane Count 这些参数以及有时需要用edp-panel的 compatible 让驱动去读 eDP 屏的 DPCD 信息来自动协商链路。如果你手持的是一块 eDP 笔记本屏模组不知道详细参数优先走自动协商不要死填 timing。BT1120 这路比较特殊。它不是接常规 LCD 的而是把 VOP 输出的数字视频信号以 BT.1120 并行格式送出去给外部视频处理芯片或采集设备用。配置思路同样是三件套控制器节点、输入路由节点、路由节点状态。但实际调通后你会发现BT1120 本身不含像素时钟恢复对后端设备的同步要求更高需要和后端联调水平/垂直同步信号。我没有在这台设备的 BT1120 上做复杂的内容合成只是把其中一路 VOP 的画面直接送出去。如果你也想这么干务必确认后端设备要求的色彩空间和时序BT1120 通常是 YUV 信号不是普通 LCD 用的 RGB转换没做对的话画面会整体偏色或者绿屏。4. OpenHarmony侧适配主屏顺序与多屏策略落地4.1 HDF显示设备注册与Composer识别顺序设备树配置好、内核能枚举出多个 connector 之后OpenHarmony 的 HDF 显示驱动会在系统起来的时候扫描 DRM device创建对应的显示设备。多数 RK3568 的 OpenHarmony 移植包已经带好了这块逻辑但你会遇到一个新问题到底哪块屏是主屏主屏顺序直接决定了开机 Logo 显示在哪、RenderService 默认把桌面绘制到哪。它不是一个运行时的“自动行为”而是由 HDF 驱动扫描 connector 的顺序决定的扫描顺序又和 dts 中节点的注册顺序、内核枚举顺序有关。最可靠的做法是在系统侧通过配置文件固定下来。具体做法看你的 vendor 包怎么组织。有些 RK3568 工程里显示相关的 HDF 配置在/vendor/etc/display_config/下里面会有类似display_device_config的文件可以指定屏幕尺寸、刷新率、方向有些则是在 init 脚本里通过属性控制。我建议先跑一条命令看当前系统识别的显示设备hdc shell hidumper -ls在列出的服务里找到显示相关服务再 dump 具体信息。不同版本服务名不一样所以我没法给你一个固定的命令参数。你只要确认“系统确实看到了两个屏幕”这一步就算完成了。4.2 主屏、副屏、异显与同显的落地方式模式的选择要看你的产品定义。我这个项目里HDMI 是“对外展示面”MIPI 是“本地操作面”二者显示内容完全不同属于异显。OpenHarmony 系统级有没有提供“直接配置异显”的命令行开关说实话这个能力在不同版本里成熟度差异很大4.0 之前主要靠应用层代码调多屏接口来实现4.1 之后系统能力完善了很多但也还没有一个像 Androidwm set-user-rotation那样通用统一的命令。所以我会分两条腿走路一是在系统底层的 init 配置里确认两个显示设备都能被正常枚举和打开保证整机不会因为“副屏没准备好”导致主界面卡顿或者渲染异常二是在业务应用层通过 DisplayManager 接口动态创建虚拟屏或者把不同 UIAbility 投到不同屏幕。对系统移植工程师而言你要做的最重要的事情就是保证底层把两块屏都“亮出来、显示正常”上层的业务分流是应用工程师的事。如果你的产品只需要“同显”那简单很多系统通常默认支持镜像模式你只要在底层保证两个屏都能出画面即可。异显则要关注两个屏幕的分辨率和刷新率差异如果一块 4K 一块 800x480合成器把内容从 4K 缩放到小屏上容易出现锯齿和布局错乱。4.3 开机亮度、屏幕方向与触摸校准多屏设备还有一个绕不开的细节副屏的方向和触摸坐标。设备树里 VOP 输出的画面顺序和面板物理安装方向如果不一致就会出现“开机画面横的、触摸坐标竖的”的诡异问题。方向修正一般在 HDF 显示配置里做有些 RK3568 工程支持在display_device_config里配置旋转角度。触摸坐标的映射则复杂一些因为触摸 IC 驱动报出来的是原始坐标指示的是触摸面板的物理方向系统在不做任何处理时默认认为触摸方向和显示方向一致。你把屏幕旋转了 90 度但触摸没跟着转就会出现点 A 出 B 的错乱。这种情况我会在 HDF 或内核 input 层面做坐标变换。注意触摸和显示是两条独立的链路一定分别验证先用系统的触屏测试页面画线看笔画是否跟手、方向是否正确再调整坐标映射参数。我见过太多工程师改了一下午显示方向最后发现问题根本在触摸方向没同步。5. 联调实战与排查黑屏、花屏、顺序错乱一次讲透5.1 多路显示从设备树到开机亮屏的完整联调步骤三路显示都配好后我按下面的顺序做了联调每步都有明确的验证手段强烈建议你也按这个顺序来确认设备树编译通过烧录后dmesg | grep -iE drm|hdmi|dsi|edp没有任何 fatal error查看/sys/class/drm/确认 HDMI、DSI 等 connector 节点都枚举出来status是connected先断开 MIPI 屏只留 HDMI确认 HDMI 单独能出画面且分辨率正确再断开 HDMI只留 MIPI 屏确认 MIPI 能起来背光亮度正常触摸可用双屏同时接上观察主屏是哪一个确认开机 Logo 和桌面在预定的主屏上最后接 BT1120 后端设备确认第三路视频信号有稳定的同步信号和画面帧。第 5 步最容易出问题。两个屏都接上后如果主屏不是你想要的那块先别急着改代码用cat /sys/class/drm/card0-HDMI-A-1/status这类命令确认每个 connector 的连接状态再看内核日志里 VOP 绑定的打印顺序。排查思路是“先确认设备树绑定的 VOP 对不对再调整 HDF 或 init 侧的主屏优先级”。5.2 高频问题速查表下面这张表是我这次移植和以往给 RK 平台做显示适配时总结出来的最高频问题集合每一行都对应一个真实踩过的坑现象可能原因排查命令/手段处理建议开机后所有屏黑屏内核 .config 缺少 DRM/显示驱动ls /dev/dri核对 Kconfig重编内核HDMI 有信号但分辨率很低EDID 读取异常dmesg 搜 edid检查 HDMI 线材/座子焊接或用 video 强制分辨率MIPI 屏黑但背光亮panel 初始化时序不对dmesg 搜 dsi核对 enable/reset GPIO 时序确认 init 序列屏亮但显示花屏时序参数不对或像素时钟误差对比屏规格书 timing核对 hactive/hback-porch 等参数双屏同时开只有一个亮VOP 绑定冲突或带宽不够dmesg 搜 vop/dclk检查 route 是否重复指向同一 VOP副屏显示主屏内容异显失败系统层未做多屏模式设置应用层查 DisplayManager应用侧调用多屏接口或确认系统版本支持异显屏幕方向不对面板安装方向与 VOP 输出不一致旋转配置测试在 HDF 显示配置里做旋转触摸坐标与画面方向不一致触摸驱动未做坐标变换触屏画线测试调整 input 坐标映射屏幕偶尔闪一下PWM 背光频率偏低或干扰观察闪烁频率调整背光 PWM 频率其中“双屏同时开只有一个亮”是我在所有 RK 多屏项目上遇到最多的问题。不只是 RK3568RK3588、RK3399 上同样存在。多数情况是route_xxx节点的connect属性写重复了两个接口都指向了同一个 VOP 的同一个 port导致另一个 VOP 没有可用的数据源。你可以用 dmesg 搜索vop相关的 bind 日志确认每个 VOP 到底绑了哪个显示接口。5.3 容易忽略的硬件与资源冲突设备树改到“看起来全对”但屏幕就是不亮这类问题十有八九出在硬件资源冲突上。RK3568 的不少引脚是复用的一个 GPIO 可能既支持 I2C 又支持 PWM 又支持 GPIO 中断一旦某个外设驱动先 claim 了这个引脚显示链路再去申请同一个引脚就会失败。比如我这次调试时发现 BT1120 的某个数据引脚和板子上一个 LED 的 GPIO 冲突导致 BT1120 一直初始化失败。这类问题查起来特别费时间因为软件日志不会直接告诉你“引脚被占了”只会显示一个模棱两可的 timeout。排查时试着把不相关的外设节点先 disable 一批逐步二分定位。另外多路显示对电源的瞬态功耗要求更高。两块屏同时点亮的时候瞬间电流可能比单屏大很多如果板子的 3.3V/5V 电源余量不足会出现“单屏没问题、双屏总有一颗不亮”的诡异现象。遇到这种问题先量电压不要一上来就怀疑软件。最后再提醒一点多路显示联调时确认每块屏的复位 GPIO 要有足够的延时。我的经验是上电时序硬性要求先供屏电源再拉复位再发初始化序列最后打开背光。顺序反了很伤屏也会导致随机黑屏。写在最后多路显示移植这件事本质上是在硬件能力、内核驱动、系统框架三个层面之间找平衡。RK3568 的硬件能力非常强OpenHarmony 的显示架构也足够现代双方接驳的难点反而不是某一项技术的“深水区”而是那些细碎的节点名、配置项、时序参数、引脚复用问题。你只要按“先单屏、再多屏、再异显”的顺序一步步来大多数问题都能在日志里找到答案。我个人的一个体会是在做系统移植时别急着把全部功能一次性打开先把一条最小路径跑通再逐步叠加。以显示为例就是先让一块屏完美点亮然后增加第二块、第三块。每增加一路只改一个变量验证一个变量这样就算踩坑也能迅速定位。如果你在 RK3568 的 OpenHarmony 多屏移植上也遇到类似问题欢迎按我上面整理的排查思路去试多数情况下问题都能锁定在设备树和资源冲突这两个方向。
返回列表