RK3568 MIPI DSI屏幕适配:uboot显示正常但内核黑屏的排查与解决
2026/9/19 6:11:16 网站建设 项目流程

先说结论:RK3568这种“uboot阶段logo正常显示,进内核后就黑屏”的问题,绝大多数不是硬件坏了,而是MIPI DSI链路在内核阶段没有被正确接管,或者配置没有同步过去。我前后排查过几块不同的板子,也帮同行处理过st7701s、ILI9881、HX8399这类常见屏,踩了不少坑,这里把整个思路和操作过程完整复盘一遍,希望对同样被屏折腾到头疼的人有点帮助。

先说说这个内容能解决什么、适合谁看。如果你手头是RK3568平台,正在做MIPI DSI屏幕适配,碰到了uboot阶段有log或logo,但内核起来后屏幕黑掉的情况,那么这篇文章适合你。哪怕你不是用正点原子的开发板,或者用的内核版本不太一样,排查思路和操作手段也都是通用的,照着捋一遍,大概率能找到问题点。

1. 问题现象与排查思路总览

1.1 先看现象:从logo到黑屏,卡在哪个环节

RK3568的显示链路比较复杂,从CPU到屏幕,中间要经过VOP、DSI控制器、PHY、面板驱动、背光控制,任何一个环节没配合好都会黑屏。但“uboot能显示,内核黑屏”这个现象特别典型,它其实帮我们排除掉了一大堆问题——屏幕本身大概率是好的,排线大概率的接触没问题,MIPI物理链路大概率是通的,背光驱动的硬件部分可能也正常。

那问题就集中在:uboot和内核在初始化DSI屏时的配置差异、内核设备树里panel相关参数的缺失或错误、以及内核drm框架接管屏幕时时序或上电时序不对。所以我刚开始排查的时候,并不会一上来就去量波形,而是先把问题范围缩小到“软件配置两个阶段的不一致”上。

这里要多说一句:很多新手遇到黑屏第一反应是改设备树里的时序参数,改来改去也没效果。时序参数当然重要,但在现象是“uboot亮、内核黑”的情况下,先别着急动timing,先确认内核是否真的把该初始化的都初始化了。

1.2 整体排查路线:逐段缩小问题范围

我的习惯是先把一条链路拆成三个关键节点:uboot出来、内核drm接管、panel最终点亮。对应的排查路线就是三句话:

  • 先确认uboot传给内核的dtb和内核自己用的dtb是不是同一份,设备树配置是不是一致;
  • 再确认内核启动时dsi和panel驱动有没有正确probe,日志里有没有报错;
  • 最后再确认屏幕的上电时序、reset引脚、背光引脚是不是被内核又控制了一遍,导致和uboot的状态冲突。

如果这三步走完还没解决,那就上示波器量信号,确认PHY有没有输出,时钟和数据lane是不是都正常。但90%的情况,走完前三步就能定位到根因。

2. 核心细节解析与实操要点

2.1 MIPI DSI显示链路的基本认知

RK3568的显示链路基本是这样的:应用处理器里有一个或多个VOP(Video Output Processor),负责把内存里的framebuffer扫描出来,通过内部总线送到DSI控制器,DSI控制器再把并行数据转成MIPI DSI的串行差分信号,经过PHY物理层从芯片引脚出去,最后进到屏幕的驱动IC,由驱动IC驱动液晶面板显示。

这个过程中,内核drm框架会有一个完整的链路管理:VOP绑定某个connector,connector上挂着panel,panel提供时序参数和初始化序列。任何一个绑定关系错了,都会出现“内核显示子系统起来了,但屏幕没点亮”的现象。

特别要注意的是,RK3568的VOP有很多个plane和可能的connector配置,设备树里如果同时配置了HDMI和MIPI DSI,一定要确认内核默认选择的connector是哪一个。我遇到过一种情况:uboot里把VOP路由到DSI,所以logo正常;内核起来后drm驱动根据设备树优先级选择了HDMI作为主显示输出,DSI虽然probe了但没有使能,结果就是HDMI没插显示器、MIPI屏幕黑着。

2.2 为什么uboot正常、内核黑屏?

这里要理解一个关键差异:uboot的显示框架和内核的drm框架是完全两套独立的代码。uboot里一般用简单的dcache、clock、IOMUX初始化加你自己的panel初始化序列,凑合能用就画个logo刷出来;而内核里需要板级描述(设备树)、驱动模型(panel/DSI/bridge)、帧缓冲分配、时钟框架、pinctrl框架全部协同工作。

所以经常会出问题的地方就三个:

  1. u-boot里用的时序参数和内核设备树里的时序参数不一致。常见的是时钟频率差一点,导致内核推导出来的HFP、HBP、VFP、VBP不一样,屏幕能接受但没有信号锁定。
  2. 内核里panel的初始化序列(就是通过DCS命令配置屏幕IC的寄存器)和uboot里用的初始化序列不一致。有些屏幕必须严格按照厂商给的初始化代码顺序送指令,差一条命令都出不来画面。
  3. 上电时序不一样。uboot里先拉reset、再开电源、再送初始化序列;内核里可能有独立的backlight驱动、panel驱动、电源供给,它们之间的顺序没控制好,导致panel启动失败。

这三条如果都没问题,但屏幕还是黑,下一步就要怀疑内核的DSI控制器驱动本身是不是有兼容性问题,或者PHY配置的lane数、频率是否和屏幕实际支持的对应不上。

2.3 还要注意uboot与内核设备树必须一致

这其实是一个新手很容易忽略的点。RK平台通常会分为两个设备树:一个给uboot用,一个给内核用,在标准的RK SDK里是同一个设备树,但实际项目中经常分开了。改uboot的dts容易,改内核的dts也容易,但如果两者之间不一致,就会出现“uboot正常、内核黑”的诡异现象。

我之前碰到过一个案子,uboot里配的是MIPI摄像头,面板配置用的DSI屏,但内核的dts里那张屏的panel-compatible写错了,结果内核虽然识别到了DSI控制器,但找不到panel节点,屏幕自然不亮。所以第一步永远先检查设备树的一致性,而不是闷头点波形。

3. 实操过程与核心环节实现

3.1 第一步:确认内核日志和drm state

排查时我习惯先打开串口终端,启动内核,盯着dmesg输出。启动完成后第一件事是看几样东西:

  • dsi控制器有没有注册成功,有没有报超时或同步错误;
  • panel驱动有没有probe,compatible是否匹配;
  • VOP和connector的绑定状态;
  • 有没有显式提到“no display monitor”这类字样。

推荐命令是:

dmesg | grep -i dsi dmesg | grep -i panel dmesg | grep -i vop dmesg | grep -i drm

如果dmesg里完全找不到dsi相关输出,大概率是设备树里节点状态不对。如果出现了“link training failed”之类的错误,那问题就在PHY和时序配置上。如果没有任何错误,但屏幕黑,那么就得看一下drm的state,确认当前enable的connector是哪个。

cat /sys/kernel/debug/dri/1/state

注意dri/后面的序号,不同板子可能不同,多试几个,比如/sys/kernel/debug/dri/0/state/sys/kernel/debug/dri/2/state。看输出里DSI-1这个connector的状态是“connected”还是“disconnected”,mode是不是你设的那个分辨率。

3.2 第二步:对照设备树配置,逐项核对屏幕参数

这是最耗时间但最值得做的一步。我通常准备一张纸(或者直接在电子表格里),左边写屏幕规格书里的关键参数,右边写设备树里的配置,逐项对。

常见的需要核对的位置包括:

panel@0 { compatible = "st7703,panel"; reg = <0>; backlight = <&backlight>; reset-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_LOW>; enable-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; panel_in_dsi: endpoint { remote-endpoint = <&dsi_out_panel>; }; }; }; };

时序写在panel的时序子节点里,常见的字段是:

  • clock-frequency(像素时钟,或者说DSI的位时钟来源)
  • hactive/vactive
  • hback-porch/hfront-porch
  • hsync-len
  • vback-porch/vfront-porch
  • vsync-len

比如某款720x1280的屏,hsync-len是10,hback-porch是20,hfront-porch是50,vsync-len是8,vback-porch是20,vfront-porch是30,那么这些数值必须原样填进设备树。这些参数如果某一项差了很大,屏幕虽然黑但用示波器看DSI是有波形输出的,很多新手这时会误以为输出正常,实际是时序不匹配导致panel无法锁定。

还有一个很重要的参数是lane-count,在dsi控制器节点里定义。如果屏幕是4 lane,你配成2 lane,那数据带宽直接减半,分辨率高的时候大概率黑屏,分辨率低的时候可能白屏或者花屏。

3.3 第三步:检查背光与使能顺序

uboot阶段亮、内核阶段黑,有一种常见情况是:uboot里把背光拉亮了,进内核后drm驱动又会重新执行panel操作,但中间背光驱动的probe把背光灭了,之后又没有正确恢复。这个现象在连接开发板、用外部供电的时候尤其明显。

我建议你在内核起来后,用驱动或者命令直接测试背光:

echo 255 > /sys/class/backlight/backlight/brightness

如果屏幕亮了,说明panel的显示没问题,是背光默认策略问题。如果背光好像没反应,就需要查背光的供电和PWM配置。

另外还要注意reset-gpios和enable-gpios的极性。有些panel是低电平有效,有些是高电平有效,uboot和安卓内核往往用同一套GPIO控制,但如果你的厂商SDK里某处正好设置反了,就会出现“时好时坏”的情况。拧螺丝之前先测这哥俩,能省不少事。

3.4 第四步:用示波器量MIPI DSI信号

软件排查走完依然黑屏,那就得上示波器量信号。量的时候注意,MIPI DSI是差分信号,要用差分探头,或者两个通道分别接DP和DN,再用数学通道做差分。重点是量时钟lane和数据lane。

正常工作时,你能看到明显的差分时钟波形,时钟频率和面板要求的bit clock吻合。数据lane上在初始化阶段会有DCS指令波形,在显示阶段会有视频数据流波形。如果数据lane完全静默,或者波形幅度很小,那说明PHY没有正常驱动。如果时钟有、数据也有,但屏就是黑,那就要停在这条链路上了,重新回头检查时序和初始化序列参数。

顺便说一句,有些人用逻辑分析仪去量MIPI DSI,这个是不现实的。DSI跑的是高速差分信号,普通逻辑分析仪根本采不到。示波器是必须的,带宽最好在500MHz以上,200MHz的示波器虽然能看出来有没有波形,但看高速信号细节会比较吃力。

3.5 第五步:用软件临时验证屏体与驱动链路

如果你手头暂时没有示波器,也可以先用软件手段临时验证一下链路通不通。我知道RK平台有一个很好用的调试入口:drm的debugfs接口。除了上面提到过看state,还可以尝试把某个平面的内容强制输出。

在Linux下,可以用modetest工具(来自libdrm)来查看或者设置模式,也可以写个小程序调用KMS的接口。如果手头正点原子或其他板卡的SDK里带了自己编译的modetest,那就很方便。

modetest -M rockchip -p modetest -M rockchip -s 56:720x1280

第一个命令打印所有plane和connector的信息,第二个命令尝试对某个connector设置一个720x1280的mode(connector ID是多少以-p输出为准)。如果modetest设置完屏幕就出画面了,那说明整个链路没坏,是上层显示服务或者内核启动时的默认显示path有冲突。

这些小验证看起来土,但非常好使:它能帮你把问题从“硬件坏了”、“内核驱动坏了”、“显示协议栈坏了”这三者之间切分开。

4. 内核drm驱动适配中那些容易踩的坑

4.1 panel驱动兼容性配置

RK3568内核里自带了很多常见panel的驱动,比如st7703、ili9881c、hx8394等。如果你的屏用的是其中一个驱动IC,最省力的办法是直接复用现成驱动,然后重点检查设备树里的compatible是否匹配。

一个常见的坑是:屏幕的驱动IC是超便宜的超万能驱动IC,它支持兼容模式,但也不会在厂商驱动列表里。这时候你可能得自己写一个简单的panel驱动。其实也不难,基本就是copy一份现有的panel驱动模板,把初始化序列换成厂商给的那一串DCS命令,再填好时序参数和enable/disable回调。

这里有一个很重要的注意事项:初始化序列不要随便精简。很多厂商SDK里的初始化序列,前面几条是进入命令模式、设置page selector,后面才是真正配置画面参数。精简过程中少一条命令,屏幕可能就不亮或者颜色不对。我之前遇到过一次,为了省事删掉了两条“延时”,结果屏幕颜色整体偏绿,排查了半天,最后加上延时就好了。

4.2 涉及驱动IC型号识别的问题

有些屏会在初始化的时候主动读回屏幕IC的ID,用来确认型号和驱动IC匹配。但很多屏的这个读取流程是要软件主动去发命令的,如果你的panel驱动里没有实现“读取IC ID并校验”的逻辑,内核就直接按设备树里的compatible当作是那个IC了。

这时候,uboot阶段可能已经调好了,一切正常;内核阶段呢?内核里的驱动可能又会重新执行初始化序列。如果初始化序列完全一样,就没问题;如果驱动库里的初始化序列和厂家提供的内核版本初始化序列有细微差异,那就可能一进内核就黑屏。

所以遇到“uboot好、内核黑”,我总会顺手对比一下同一款屏在uboot里的初始化代码和内核panel驱动里的初始化序列。别嫌繁琐,这个动作能解决一大半问题。

4.3 时钟频率:一个最容易让人迷惑的参数

DSI的时序参数里,clock-frequency往往最让人迷惑。它到底是指pixel clock还是DSI byte clock还是DSI bit clock?不同DRM驱动里计算方式不一样,但有个粗略的口诀:DSI bit clock一般比pixel clock高,因为要按lane数分摊负担。

举个例子:一块720x1280@60Hz的屏,pixel clock大约在60MHz左右。如果用了4 lane,bit clock可能只需要跑到200~300MHz就够了;如果用2 lane,bit clock就得接近400MHz,对PCB要求也更高。设备树里填的clock-frequency,一般直接按panel规格书里的数值来,如果规格书里没写,就得根据具体的DSI控制器驱动来算。

RK3568的DSI也支持通过clk-tree动态计算频率,但如果你设备树里配的时序和屏幕实际初始化序列里设置的频率差异太大,就会造成信号质量差甚至完全黑屏。这时示波器量到的时钟波形频率会偏离预期,一眼就能看出来。

4.4 多屏同时显示时,connector优先级问题

前面提过,RK3568可以输出到多个显示接口。当uboot阶段只初始化了MIPI DSI作为logo输出时,进内核后如果有HDMI/TYPEC/LVDS等其他输出接口也处于活跃状态,内核可能默认选择了其中某个作为主显示,但没有同步去关掉其他输出,结果就是哪个都不亮,或者只有背光亮。

排查方法还是上面的modetest -p,看哪个connector是connected。如果发现DSI不是主板选择的主显示接口,可以通过设备树或者bootargs参数调整显示输出的优先级。RK平台常见的方案是在drm平台驱动里设置对应的路由表,优先使能需要的输出,同时关闭或保持-disable状态的其他输出。

5. 典型问题排查实录:一个完整的case

5.1 问题描述

有一个项目在RK3568上接了一块MIPI DSI接口的720x1280屏幕。插上电,uboot阶段logo正常,然后进入内核,屏幕就始终黑着,只有背光亮着,看起来非常有迷惑性——你会觉得屏坏了,其实屏加电了但没画面。

5.2 逐步排查记录

第一步,串口登录后,先看dmesg里的DRM信息。发现drm初始化正常,DSI控制器probe成功,panel也probe成功,没有明显报错。这就是最麻烦的情况,因为内核很“满意”,可屏幕没给画面。

第二步,看drm state。cat /sys/kernel/debug/dri/1/state后发现DSI connector是connected,而且mode也是720x1280。这说明内核确实想让DSI输出了。

第三步,怀疑初始化序列问题。把内核panel driver里的初始化序列和uboot里的初始化序列一对比,发现内核少了两条关键命令,一条是设置RGB order,另一条是设置LVDS mapping。补上初始化序列后,屏幕依然黑。

第四步,量波形。用示波器看DSI时钟lane有波形,而且频率是对的;数据lane也有波,只是初始化阶段波一下之后就没有后续了。这个现象说明panel没有送出有意义的画面回传,但也不像完全没收到初始化命令。

第五步,怀疑是上电时序冲突。查了内核里的power-supply配置,发现panel驱动里没有配置power-supply节点,而uboot里是直接把某个regulator拉高,保证panel供电。进内核后,统管regulator的框架发现该regulator没有被引用,可能在某些情况下自动拉低或进入休眠。修法是在panel设备树节点里显式加上power-supply = <&vcc_lcd>,并在驱动里做enable和disable操作。补上这一步,屏幕终于正常点亮。

这是一个非常典型的案例,问题出在“uboot里裸跑的初始化顺序”和“内核里电源管理机制接管了供电”之间的差异。眼高手低,动不动就想改时序,实际是电源给闹的。

5.3 最后定位的根因

最终根因总结下来就是:内核panel驱动power-supply缺失导致某路LDO没被正确持续供电,初始化序列里又有一些小差异。两者叠加,展现了“uboot正常、内核黑屏”的现象。单独只改其中某一处,都不一定能好。

这给我们的启示是:遇到这种问题时,不要只盯着一类原因,建议把设备树里的电源、reset、backlight、panel时序、初始化序列这几样打包在一起做一次全面核对。很多板卡,uboot为了最小化,会默认把很多GPIO和regulator拉到一个安全状态,而内核是一个完整的管理系统,你配置少了某项,驱动就真的不会去操作,最后自然就是黑屏。

6. 调试工具链与个人经验总结

6.1 必备工具与查看命令

这里整理一下我每次排查MIPI屏幕问题都会用到的东西,顺手分享给各位,省得临时百度。

工具用途备注
串口终端看内核日志、交互调试必须,建议接出串口,方便实时看dmesg
adb(如果跑Android)进系统后看dmesg/logcat、操作debugfsRK3568可同时跑Linux和Android
dmesg查看驱动probe、报错、调用栈第一道防线
/sys/kernel/debug/dri/*/state看显示链路状态需要mount debugfs
modetest测试输出模式、触发显示来自libdrm
示波器量DSI信号质量、时序、频率最好有差分探头
万用表量供电是否正常、GPIO电平、背光电压简单但有用

在RK3568上,我一般会先把debugfs挂载好:

mount -t debugfs none /sys/kernel/debug

然后用下面几条命令快速过一遍状态:

cat /sys/kernel/debug/dri/1/state cat /sys/kernel/debug/dri/1/overview cat /sys/kernel/debug/dri/1/clocks

overview能看到当前系统注册了多少plane、encoder、connector,clocks能看到各模块的时钟状态,方便快速确认是不是时钟没有起来。

6.2 一些经验之谈和避坑建议

最后说几个实际项目中更容易踩的坑,希望你们少走弯路。

第一,不要迷信所谓“通用驱动”。很多屏的驱动IC型号类似,但厂商解锁后使用不同的初始化命令,甚至是相同命令不同参数。复用驱动时一定要拿厂商提供的初始化序列做diff,不能直接套。

第二,uboot和内核尽量不要各维护一份屏参。如果你有条件,尽量让内核直接复用uboot解析出来的参数,或者至少在文档里标清楚两份dts的维护关系。我见过很多项目,改动只改内核dts,结果uboot里的fb还按旧参数显示,等改完重新编译又乱套了。

第三,不要怕看源码,尤其RK平台的内核源码本身已经很完善,panel驱动也很多可以参考。遇到问题先找到对应DSI控制器驱动的源码,看看它的probe流程、enable流程是怎么写的,配合设备树README,能省很多时间。

第四,改了初始化序列后,一定要重新编译并确认镜像烧录进去了。听起来是废话,但有时候你改了代码却忘了烧录,或者烧的是另一个分区,或者加载的是dtb overlay,然后对着屏幕发几个小时的呆——真的遇到过。

把排查的顺序捋顺很关键:先分阶段,再查设备树,再查时序和电源,再看信号,最后再怀疑逻辑。整个过程不难,难的是每一步都不愿意细查。只要耐心下来,90%的“uboot亮、内核黑”都能找到明确的原因。祝各位早日点亮自己的屏幕。

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

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

立即咨询