RK3568 MIPI屏uboot正常内核黑屏?设备树到DRM的完整排查指南

发布时间:2026/9/19 15:27:12
RK3568 MIPI屏uboot正常内核黑屏?设备树到DRM的完整排查指南 RK3568 的板卡调试MIPI 屏是最常见的“劝退”项目之一。很多人遇到的场景就是这样uboot 阶段 logo 正常显示看着一切就要成了结果 Linux 内核跑起来之后屏幕直接黑掉串口里系统其实已经正常启动了。背光有时候亮着有时候不亮敲键盘也没反应整个人瞬间回到原点。下面我就把这类“uboot 显示正常、进内核黑屏”的问题完整拆解一遍从现象分类、设备树链路核对、屏参断层、背光时序到 modetest 和 DRM 调试节点的实际用法最后用一个 ST7701S 屏幕的完整修复过程收尾。正在调 RK3568/RK3588 平台 MIPI 屏的 BSP 工程师或者刚接触 Rockchip DRM 显示链路的嵌入式开发者都可以照着这个思路走一遍。1. 先界定故障边界是真黑屏还是假黑屏问题到底在哪一段1.1 先把“黑屏”拆成三种经验里最忌讳的就是拿到“黑屏”两个字就直接翻设备树。黑屏不是一个单一原因至少可以拆成三种完全不同的现象完全黑屏背光也不亮屏幕像没通电一样。背光亮着但没有画面屏幕只是发光。开机瞬间有画面然后黑掉偶尔还带着闪屏或者条纹。三种现象对应的排查方向差异极大。完全黑屏优先查 LCD 电源、背光使能、reset 时序背光亮无画面优先查 DSI 数据链路和 panel 初始化序列画面出现后再消失优先查 logo 继承、fbcon 抢占或者 route 节点配置。花五分钟确定现象属于哪一类比盲目看日志效率高得多。1.2 uboot 能点亮只代表“硬件链路没有死”这一点值得反复强调uboot 和内核用的是完全独立的两套显示框架。uboot 阶段是 U-Boot 自带的 video driver读的是 uboot.dts 里的 display-timings 或 panel 节点完成一次最简单的 mode set然后往 framebuffer 里画 logo。内核阶段则是 DRM、panel driver、VOP2 这套完整的 display pipeline读的是 kernel dts走的是组件绑定流程。这两套东西不是同一份代码也不是同一份设备树。所以 uboot 的 logo 正常只能说明几件事MIPI 的物理链路没有断PCB 走线和连接器大概率没问题屏幕的供电和 reset 大体上是对的uboot 里配的屏参和激励信号能被屏幕接受。但内核能不能点亮完全取决于内核设备树里的 route 配置、panel compatible 匹配、DRM 组件绑定、背光设备这几个环节是否齐全。uboot 亮了而内核黑屏恰恰说明“断层”出现在这两套框架交替的位置。1.3 进入正题前先回答三个问题不管日志多复杂我建议先确认三件最基础的事内核是否真的起来了能不能通过串口登录。DRM 相关设备有没有绑定成功。/sys/class/drm/ 下面有没有 DSI connector。先保证串口能登录系统然后执行dmesg | grep -iE drm|vop|dsi|panel|backlight | tail -n 100 cat /sys/class/drm/card0-DSI-1/status如果根本不存在 card0-DSI-1 这个目录说明 DSI encoder 或者 panel 驱动没有 probe 成功大概率是设备树 compatible 或端口连接问题。如果节点存在状态是 connected说明链路已经注册了问题很可能出在 mode set、背光或初始化序列上。这三个答案直接决定后面往哪个方向钻。2. 设备树接线图排查从 display-subsystem 到 panel 的完整链路核对2.1 一条完整显示链路在设备树里长什么样RK3568 的显示链路在设备树里是一条很明确的“接线图”display-subsystem → vop2 → VP 端口 → route_dsi0 → dsi0 controller → MIPI D-PHY → panel 节点每个环节都有对应的节点和 status 控制。我见过很多次黑屏就是因为 route_dsi0 的 status 还是 disabled或者 connect 属性指到了别的 VP 上。典型的 RK3568 设备树结构大概是这样省略无关内容vop2 { vop2_out: port { #address-cells 1; #size-cells 0; route_dsi0: route-dsi0 { status okay; logo,uboot logo.bmp; connect vp2_out_dsi0; }; }; }; dsi0 { status okay; panel0 { compatible st7701s,720x1280; reg 0; backlight backlight; reset-gpios gpio3 RK_PA5 GPIO_ACTIVE_LOW; ports { #address-cells 1; #size-cells 0; port0 { reg 0; dsi0_out_panel: endpoint { remote-endpoint dsi0_in_vp2; }; }; }; }; };这里的 endpoint 名称只是示意不同 SDK 版本写法会有差异。核心是如果 route_dsi0 没有配成 okay或者 connect 没有连到 dsi0 对应的 VP 输出内核 DRM 根本不会把 VOP 输出路由到 DSI。这个节点太容易被遗漏了尤其是从某个参考板 dts 裁剪过来的时候经常保留着原来的 disabled 状态。2.2 route 节点里三个属性少一个都不行Rockchip 的 route 节点不是普通设备树节点那么直观但理解起来其实不难。status控制这个视频输出路由是否参与组件绑定。如果 disabledVOP2 对应 VP 不会绑定到 DSI现象就是完全没有显示。connect指定 VP 输出 endpoint。在支持多路显示的平台上如果 connect 指错比如想用 dsi0 却 connect 到 vp1_out_dsi1同样会黑屏或者画面跑到错误接口上。logo,uboot决定 uboot 的 logo 内存区域要不要被内核继承。这一个属性在配置了开机动画后特别关键因为 uboot 切到内核时会经历一次 pipeline teardown如果 logo 继承失败屏会先黑一下严重时直接停在黑屏。判断 route 是否生效最直接的方法是看内核日志里有没有对应的组件绑定信息比如drm/rockchip: bound ...。如果日志里完全没有优先确认 route 节点有没有被 include 到最终 DTB 里。有时候你改了 dtsi 文件但实际编译用的是另一个 dts这种低级错误我在项目里遇到过不止一次。2.3 panel 节点核对清单接下来快速过一遍 panel 节点本身我习惯按下面几项逐条核对compatible是否匹配内核已有的 panel 驱动或 panel-simple 匹配表不匹配的话设备树不会 probe。reset-gpiosGPIO 编号和 active 状态高有效还是低有效是否正确。backlight是否正确引用 backlight 节点且默认亮度是否够大。power-supply / vddio-supplypanel 的电源域是否在开机阶段被正确拉起来。portspanel 的 endpoint 是否与 dsi0 的 endpoint 对应上。下面的表格可以当排查清单用检查项正常情况异常影响route_dsi0.statusokaydisabled 时完全无输出route_dsi0.connect指向 dsi0 对应 VP 输出输出到错误接口或黑屏panel compatible能匹配到驱动probe 失败无 connectorreset-gpios 极性与屏规格书一致屏幕一直处于 reset 状态backlight 引用存在且默认亮度0画面正常但亮度为 03. 屏参与初始化序列断层uboot 能亮不等于内核能亮3.1 两种 panel 的本质区别在设备树里MIPI 屏大致分两类。一类是简单的 panel-simple 或 panel-timing屏幕只需要 hback-porch、vfront-porch 这些时序参数上电后就能直接接收像素流。这类屏通常是 RGB 接口转 MIPI 的转换模块或者内部没有复杂标定逻辑的屏幕设备树里给几组 timing 就行。另一类是带控制器的屏幕像 ST7701S 就是一颗很常见的 LCD 驱动控制器。它不仅要 timing还必须在开机时通过 MIPI DSI 短包和长包写入初始化序列。初始化序列包括退出睡眠模式、设置显示分辨率、调整内部寄存器、打开显示等。如果内核启动时没有完整执行这段序列屏幕就停留在默认的异常状态表现出来就是黑屏、白屏或者花屏。这种差异正是“uboot 亮、内核黑”最常见的原因之一uboot 里的驱动执行了一遍屏幕初始化序列效果是好的内核的 panel 驱动如果有同样的序列或者能匹配到兼容驱动问题不大但一旦内核的序列缺失或时序不对屏幕就废了。3.2 ST7701S 这类屏的初始化序列怎么搬运Rockchip 的内核里很多 SDK 通过rockchip,panel-init-sequence这个属性直接在设备树里描述初始化序列由 panel-simple 的 Rockchip 变体解析执行。格式很有规律第一个字节命令类型0x05 表示短包不带参数0x15 表示短包带参数0x39 表示长包。第二个字节写完命令后的延时时长单位是 ms。第三个字节后面携带的数据长度。之后是真正的命令和数据。给一段简化的示例panel-init-sequence [ 05 78 01 11 05 14 01 36 39 0a 03 FF 77 01 05 96 01 29 ];第一行表示发送命令 0x11退出睡眠模式然后延时 120ms第二行命令 0x36设置扫描方向延时 20ms第三行是长包命令写入三个参数最后发送 0x29打开显示延时 150ms。很多人直接把 uboot 里能正常显示的初始化序列复制到内核设备树却发现不行。原因通常是延时字段被改了或者长包里的数据长度写错。ST7701S 这类屏对时序非常敏感sleep out 之后如果没有足够的延时后续命令会全部丢失屏幕就会停在“初始化一半”的状态表现出来就是黑屏或者异常条纹。3.3 怎么确认初始化序列到底执行了没有不要靠猜直接看日志。正常的初始化过程里dmesg 会打印类似下面的信息st7701s dsi-panel: MIPI DSI init sequence applied具体字符串每个驱动都不一样。更通用的方法是确认有没有 error 级别的 DCS 写失败dmesg | grep -iE mipi_dsi_dcs_write|failed to write如果在日志里看到mipi_dsi_dcs_write returned -22或者-EIO说明链路根本没建立起来或者序列本身有问题。如果没有任何报错但屏幕还是黑的我建议用 modetest 强制触发一次 mode set看看是“一直黑”还是“能亮一下”。这一步能把问题分为“初始化序列问题”和“内核根本没有触发 mode set”两类排查方向完全不同。4. 背光与供电时序黑屏的首席背锅侠4.1 PWM 背光配置最常见的大坑默认亮度为 0这一条值得单独拎出来说。RK3568 平台上用 pwm-backlight 很常见节点大概长这样backlight: backlight { compatible pwm-backlight; pwms pwm12 0 1000000 0; brightness-levels 0 10 20 30 40 50 60 70 80 90 100; default-brightness-level 9; enable-gpios gpio3 RK_PB1 GPIO_ACTIVE_HIGH; };如果 default-brightness-level 设成 0或者根本没有这个属性背光就会以最低亮度点亮在白天环境下看起来和黑屏几乎没有区别。我之前排查过一个“内核起来黑屏”的问题折腾了两天最后发现只是 brightness-levels 里最小档是 0默认档也是 0PWM 确实有输出但占空比接近零。所以无论调试什么问题第一步先把 default-brightness-level 调到最大那一档排除“亮度太低”这种乌龙。这个操作成本最低收益却很大。4.2 reset 脚和电源时序让屏幕在正确的状态进入工作好多 MIPI 屏对时序非常挑剔VCI 上电之后要等 10msRESX 拉低保持至少 10ms再拉高等待 120ms然后才允许通过 MIPI 发送任何命令。如果 reset 极性反了reset-gpios 设为 ACTIVE_HIGH 但实际屏是低有效屏幕会一直被按在 reset 状态无论发什么命令都不理你。如果你在 uboot 和内核两边都看到屏幕能起来但每次进内核后就黑可以重点查一下内核的 GPIO 请求是不是成功了。有些 GPIO 被其他驱动占用也会导致 reset 从来没被正确释放。日志里一般会有gpio ... already requested之类的警告别忽略。供电时序也一样很多屏幕有两个电源域模拟电源 AVDD 和数字电源 VDDIO。设备树里分别用 power-supply 和 vddio-supply 描述。如果 VDDIO 晚于 AVDD甚至一直没有起来屏幕的 IO 状态就是不确定的。在调试阶段我习惯直接在板子上用万用表量这几个电压确认时序无误后再回过头怀疑软件。4.3 手电筒法物理排除背光亮不亮和屏幕有没有画面是两件事。遇到“背光不亮”的黑屏先用强光手电筒贴着屏幕照如果能看到隐约的内容或者操作界面的变化说明 LCD 其实已经点亮了只是背光通路有问题。这个方法虽然原始但极其有效。手电筒照不到内容的再看 MIPI 链路。有条件的话用示波器探 MIPI 的 clock lane看有没有连续时钟输出。有波形但黑屏通常是初始化序列或 panel 状态问题完全没有波形问题就往 VOP 路由、DSI 控制器时钟配置方向查。这也是为什么调试圈里经常搜索“mipi时钟信号示波器波形”的原因——看到波形心里就有底。5. modetest 与 DRM 调试节点把面板踢一脚验证真伪5.1 modetest 强制触发一次 mode set当怀疑是“内核没主动输出”而不是“panel 坏了”时modetest 是最好用的探针。libdrm 自带的这个工具几乎能覆盖所有 DRM 调试场景。用法很简单modetest -M rockchip -p先列出所有 connector、encoder、crtc 和 modes。比如看到 DSI-1 连接的是 720x1280 的屏再手动指定 connector id 触发一次 mode setmodetest -M rockchip -s 78:720x1280这里的 78 是 DSI-1 的 connector id在实际板子上会不同以上一条命令的显示为准。如果在 modetest 强制输出后屏幕亮了说明 panel 驱动、初始化序列、VOP 配置都没有问题黑屏只是系统启动时没有触发 mode set——这时候去查开机 logo 继承、fbcon 或者应用层的 framebuffer 使能逻辑。如果 modetest 也点不亮那就别怀疑系统层了专心查设备树、硬件链路和初始化序列。注意rootfs 里不一定预装了 modetest。如果是在开发板阶段我一般直接交叉编译 libdrm 里的 modetest 放进去或者用 Buildroot 打开BR2_PACKAGE_LIBDRM的测试工具选项。这个工具早装晚装都要装省得排障时干瞪眼。5.2 debugfs summaryDRM 驱动自己汇报状态Rockchip 的 DRM 驱动在 debugfs 下提供了很多节点最常用的是cat /sys/kernel/debug/dri/0/summary输出内容大概会有 VOP2 各个 VP 的状态VOP2 VP0: enable1, mode720x128060, connectorsDSI-1 plane [0]: win0, enabled1, fmtXR24 plane [1]: cursor, enabled0如果 enable1说明 VP 已经工作enable0说明 route 没有成功或者 mode set 没触发。另外像/sys/kernel/debug/dri/0/state也能看到整个 DRM 状态机。在嵌入式板子上这些 debugfs 节点比什么工具都直接。需要提醒的是部分内核配置需要打开CONFIG_DRM_ROCKCHIP_DEBUG或CONFIG_DEBUG_FS才有这些节点。如果 cat 不到优先检查内核配置而不是怀疑路径错了。5.3 dmesg 关键字速查表在调试中我经常反复搜索下面几个关键字整理成表关键字含义故障方向bound 0x...vopVOP2 组件绑定成功正常继续查下一环failed to bind组件绑定失败route/端口配置问题No panel found没有匹配的 panelcompatible 不匹配mipi_dsi_dcs_write failedDSI 写命令失败链路或初始化序列问题get-clk failed时钟获取失败dts 时钟配置问题unable to request gpioGPIO 被占用硬件资源冲突日志不可能替你解决全部问题但它能帮你在最短时间内把排查范围缩小到某一层。真正动手改设备树之前把日志里这几类关键字过一遍能避免很多重复劳动。6. 修复实例复盘从 LOGO 正常到黑屏再到稳定显示6.1 项目背景与现象这块板子是 RK3568 配了一块 6.5 寸的 ST7701S 方案 MIPI 屏分辨率 720x1280RGB 接口转 MIPI 的模组。烧完固件后uboot 阶段 logo 显示正常进入内核之后屏幕直接黑掉。串口里系统已经启动完成也能登录DTS 里的 route_dsi0 也已经确认是 okay。于是我开始了完整的排查流程。6.2 第一次修改先把背光最大亮度拉起来刚开始我并没有急着看 debugfs而是先验证现象。cat /sys/class/drm/card0-DSI-1/status能看到 connectedmodetest 手动触发 mode set 也能看到一条 mode但是屏幕始终没有光。拿手电筒照屏幕隐约能看到功能界面的轮廓——这几乎可以确定 LCD 本身已经在接收画面只是背光没动作。查 backlight 节点发现 default-brightness-level 被设成了 0。我把默认值调到 90% 位置重新烧录后再看屏幕直接亮起来了。亮度问题虽然简单但它藏得很深因为日志里 PWM 驱动没有任何报错看起来“背光正常”。6.3 第二次反复初始化序列里的延时被拍扁了背光亮了之后画面仍然不稳定。每次重启有时候能正常显示有时候起一半就黑掉而且黑掉的时候 dmesg 里会出现st7701s dsi-panel: mipi_dsi_dcs_write returned -22这个报错直接指向初始化序列写入失败。我对比了屏幕模组厂提供的初始化代码和内核里rockchip,panel-init-sequence的配置发现一个关键差异模组厂给的序列在 sleep out 之后要求延时 120ms设备树里却写的是 5ms。也就是说屏幕还没从睡眠状态缓过来后续命令就已经发过去了要么被丢弃要么解析错误。我把所有关键命令后的延时按模组规格书重新对齐尤其是 0x11sleep out之后的 120ms 和 0x29display on之前的 150ms然后再次烧录测试。这次重启多次都稳定显示黑屏问题彻底消失。6.4 复盘为什么一开始没有发现这个案例里最大的教训是不要因为 uboot 阶段显示正常就觉得初始化序列一定是好的。uboot 和内核使用了两套驱动、两份设备树、两段初始化流程哪怕同一块屏两边的配置也可能不同。我在初始阶段被“uboot logo 正常”误导浪费了不少时间在检查 VOP 路由和硬件链路上而真正问题反而在初始化序列的延时参数里。另一个教训是看到 dmesg 报错再动手要看完整上下文不要只盯第一条错误。mipi_dsi_dcs_write returned -22这个报错出现之后后面跟着的往往是几十条连续失败但其实源头是第一二条命令的时序不对。把第一处修好后面的问题自然消失。最后再补一个实际调试经验遇到“uboot 亮、内核黑”的问题不要急着改内核配置先把三类证据抓到手——屏幕当前是完全没有画面还是只有背光问题、dmesg 里有没有 DRM/DSI/panel 相关报错、modetest 能不能强制点亮。这三类证据基本就决定了问题在设备树路由、初始化序列还是背光配置。我后来在 RK3588 的另一个项目上遇到类似情况也是按这个顺序定位到 panel reset 极性错误。流程本身不复杂关键是别被“uboot 能亮”这个假象带偏。