MIPI HS RX实战:差分采样、Deskew校准与RK3588/FPGA调试指南

发布时间:2026/10/31 6:23:04
MIPI HS RX实战:差分采样、Deskew校准与RK3588/FPGA调试指南

做嵌入式显示驱动这几年,我至少有三次半夜被叫去处理“屏幕为什么花了”。三块屏、三种现象,复盘下来,问题全集中在 MIPI HS RX 这一环:要么是屏侧的接收端没有正确进入高速模式,要么是多 lane 之间偏斜导致取出来的数据和发送端对不上,要么是 FPC 软排线接触不良导致差分信号变成了乱码。MIPI HS RX 说白了就是 MIPI 链路里专门负责接收高速串行差分信号的那半边,不管你是拿 FPGA 做摄像头或屏幕的数据采集,还是调 RK3588 上 MIPI 屏幕的 Linux 驱动,只要你碰 MIPI 接口,就绕不开它。这篇文章我尽量用做项目时踩坑的口吻,把 HS RX 的物理层要点、FPGA 接收实现、RK3588 配屏调试,以及常用排查手段一次性说清楚,给刚入门或正在被 MIPI 折腾的工程师一个能直接落地的参考。

1. MIPI HS RX到底是什么,为什么一上来就得搞懂它

1.1 一对差分线上的两个世界:HS和LP

MIPI D-PHY 物理层的一对差分线(Dp/Dn)要干两件差别很大的事。LP 模式是低功耗信令,用来传握手、转换方向、进入省电状态,平时电压在 1.2V 左右,是一根线对地看的单端信号;HS 模式才是真正的高速搬运工,差分摆幅只有 200mV 上下,数据速率可以到 1Gbps 甚至 2.5Gbps per lane。HS RX 就是指接收端把这个 200mV 的差分信号准确采出来、恢复成字节流的那部分电路。

很多工程师第一次接触 MIPI,习惯照着 LVDS 的思路去理解,但 MIPI 和 LVDS 有本质区别。LVDS 是纯高速差分传输,不需要在协议层做那么多状态切换;MIPI 则是把低速控制和高速度数据硬塞在同一对线上,通过特定的 LP 到 HS 转换时序来切换模式。接收端必须能识别“LP-11 → LP-01 → LP-00 → HS-0”这个 Entry 序列,才能正确打开高速接收通路。如果这个转换时序乱了,HS RX 会误认为没有数据进来,屏幕自然收不到内容。

从工程角度看,TX 端的时序相对好做,因为发送方只要照着规范输出电平就行;RX 端难在要在有限的噪声容限里做判决,还要处理多条 lane 之间的同步。这就像同一个播音员读稿,TX 是嘴,RX 是录音笔,嘴说话可以端着,录音笔在嘈杂现场想把声音录清楚就要费更多功夫。MIPI HS RX 就是这支录音笔。

1.2 RX在DSI/CSI链路里的位置

MIPI 协议分好几层:物理层(D-PHY)、协议层(DSI/CSI)、应用层。HS RX 属于物理层,但它上游直接决定你能不能在协议层看到干净的数据。以 DSI 为例,主机侧的 MIPI DSI TX 把像素和 DCS 命令打包成包,经过 D-PHY 高速 lane 发出去;屏侧(比如 ST7701S 这类驱动 IC)内部的 HS RX 把这些比特流接收下来,再做字节对齐、包解析,最终驱动 LCD/OLED 面板。CSI 的方向反过来,摄像头 sensor 做 TX,SoC 或 FPGA 的 CSI RX 做接收,但 HS RX 的底层机制差不多。

这也是为什么很多热词都指向 HS RX:st7701s mipi 屏驱动、mipi dsi、mipi oled 屏驱动,本质上都是要让对端 HS RX 正常工作;fpga 实现 mipi、紫光同创 fpga 驱动 mipi,则是我们自己要做一个 HS RX 的接收通道。可以说 MIPI 链路好不好,一半看 TX 发得规不规范,另一半更看 RX 收得稳不稳。

1.3 从热词看大家真正卡住的点

最近搜 MIPI 相关的内容,翻来覆去总绕不开几类问题。一类是“st7701s mipi”“mipi oled 屏驱动”,典型场景是 RK3588 这类主控接 MIPI DSI 屏,Linux 下屏点不亮;一类是“fpga 实现 mipi”“紫光同创 fpga 驱动 mipi”,典型场景是做视频采集或屏信号转接,需要自己写接收逻辑;还有一类是“mipi dphy deskew calibration”,这是高速多 lane 接收时避不开的话题。

这些词看起来分散,其实都指向同一个核心:HS RX 没有适配好。点不亮屏,可能是屏端 HS RX 没进入工作状态;FPGA 收不到数,可能是接收端 lane 对齐失败;屏幕闪烁,往往是 FPC 或者 skew 问题。所以与其东一榔头西一棒子去搜零散解决方案,不如把 HS RX 这一环系统吃透,后面所有问题都能按图索骥。

2. 接收端的核心细节:差分采样、时钟恢复与deskew

2.1 200mV的差分摆幅,远比想象中脆弱

MIPI D-PHY HS 模式的差分电压典型值是 200mV,共模电压在 150~250mV 附近。和 LVDS(350mV 典型值)相比,MIPI 的 HS 信号更“软”,对接收端的灵敏度和噪声抑制要求更高。做 HS RX 电路时,输入端通常需要 100Ω 差分终端电阻,而且要在芯片内部或外部处理好共模偏置。

在 PCB 上,差分对要控制 100Ω 差分阻抗,对内等长要尽量严格。很多工程师在 Layout 时只关心总长度,没有认真做 lane 内等长,结果眼图一边闭合,HS RX 怎么调都白搭。我曾经遇到过一版板子,问题就是 Dp/Dn 两根线在连接器附近差了好几毫米,导致高速采样时码间干扰特别大,后来把走线重新绕等长,误码率直接降了几个数量级。

如果你用 FPGA 的普通 LVDS IO 去做 HS RX,还要注意 LVDS 输入的共模范围是否覆盖 MIPI 的共模电压。有些 FPGA 的 LVDS buffer 共模范围偏高端,MIPI HS 共模 200mV 左右,直接采会压在输入范围边缘,这时候可以考虑用片内的 Vref 辅助或者换支持低共模的输入结构。实测下来,这类“电平兼容”问题比协议问题更隐蔽,因为波形看起来有,就是采不出来。

2.2 deskew calibration:多lane同步的救命稻草

MIPI D-PHY 的 clock lane 和 data lane 之间、多条 data lane 之间都会存在 skew。来源很多:PCB 走线长度差、连接器 Pin 延时、FPC 弯折导致的有效长度变化、温度漂移。Skew 一旦超过接收端的容忍范围,HS RX 就会在错误的沿上采样,后果就是错位、花屏、误码。

Deskew calibration 就是接收端对所有 lane 做时间偏移校准的过程。在专用 D-PHY PHY 里,校准通常由硬件自动完成,比如 RK3588 自带的 MIPI DSI/CSI PHY;但在 FPGA 实现里,这一块经常要自己做。Xilinx 7 系列里的 IDELAY 就是干这个用的,通过 tap 调整每根数据 lane 的延时,让所有 lane 对齐到同一采样时刻。

这里要特别提醒:deskew 不是只能靠硬件自动跑,也不要以为“低频低速时没问题,高速就没事”。速率越高,一个 UI(Unit Interval)的时间越短,微小 skew 的影响会被放大。比如 1.5Gbps 时一个 bit 只有约 666ps,PCB 上信号传播速度大约 150ps/inch,那不到 5 英寸的长度差就吃掉整整一个 bit。所以真正高速的场景,必须把 deskew calibration 当成一个正式步骤来对待,而不是“可选优化”。

2.3 没有CDR,但有clock lane:采样时钟从哪来

很多人误以为 MIPI 和 SerDes 一样要靠 CDR 从数据中恢复时钟。其实标准 D-PHY 有一条专门的 clock lane,用于给 data lane 提供 DDR 采样时钟。接收端用 clock lane 的上升沿和下降沿分别采样数据,这样每个时钟周期能采两拍。

FPGA 实现时,通常把 clock lane 差分信号转成单端后送入 BUFIO,再通过 BUFR 分频出字节时钟;data lane 则通过 ISERDES 做串并转换。没有专门的 D-PHY 硬核时,这套方案在 1Gbps 以下是可行的。但要注意,clock lane 路径上的任何延迟不匹配都会被 data lane 采样过程放大,所以 BUFIO 和 BUFR 的位置、时钟约束都必须严格对待。

如果场景里没有 clock lane(比如某些特殊接口),才需要考虑真正的 CDR 架构。MIPI 的 D-PHY 规范以 clock lane 为主,这是 HS RX 比普通 SerDes 好做一点的原因,但也因此很多人忽略了“采样时钟干净”这个前提,最后姻果都跑到 clock lane 信号质量上。

3. 用FPGA实现一个MIPI HS RX:骨架与踩坑

3.1 先分清你要做CSI RX还是DSI RX

FPGA 里做 MIPI RX,方向不同,协议层差别很大。CSI RX 是接收摄像头 sensor 的图像数据,包类型是长包和短包,解析完以后输出并行 RGB/YUV/RAW 数据;DSI RX 则是接收主控发给屏幕的视频和命令流,需要解析 DCS 命令、video mode 包,才能知道一帧图像从哪里开始、在哪里结束。

但两者在物理层差不多:都要检测 LP→HS 转换、用 clock lane 采样、做 lane 对齐和 bitslip。所以如果你第一次做 FPGA MIPI RX,建议先搭一个物理层全通、协议层只做基本包长包尾检测的骨架,把“能不能收到连续字节”确认了,再往协议上加功能。我见过很多新人一上来就想着把一帧图像完整解析出来,结果连 bit 对齐都没搞定,查了两周都不知道是在物理层丢数据。

3.2 硬核IP还是软核逻辑:1.5Gbps是分水岭

FPGA 实现 HS RX 有几种路线。一是用 FPGA 自带的专用 MIPI D-PHY IP 或硬核,比如紫光同创部分 PGL 系列就有 MIPI 硬核方案,直接用厂家 IP 最省事;二是用高速 transceiver(如 Xilinx GTH/GTY)配合协议 IP;三是用普通 IO + ISERDES + 逻辑自己写软核接收。

我的经验是:1Gbps 以下可以放心用第三种方案,只要时钟约束做好,稳定性够用;1.5Gbps 以上尽量别自己硬拼,因为普通 IO 的采样窗口和时序裕量开始不够,眼图稍微恶化就采错。国产 FPGA 尤其要看原厂给出的 MIPI 参考设计,紫光同创的做法一般都有现成 Demo,优先拿 Demo 跑通,再改自己的协议逻辑,比自己从零调省力太多。

有朋友可能会问,用 transceiver 做 MIPI 是不是更“高级”?不一定。Transceiver 适合无参考时钟的 CDR 场景,而 MIPI 有 clock lane,直接用普通 IO 反而协议更透明;只是高速率下必须考虑发送端 TX 的信号质量和接收端 buffering。方案选择不是越贵越好,是越能帮你收敛时序越好。

3.3 一个最小RX逻辑的实操骨架

我用 Xilinx 7 系列举例,一个最小 HS RX 物理层一般分几步:

  1. 用 IBUFDS 接收 clock lane 和 data lane 的差分信号。
  2. clock lane 接 BUFIO + BUFR,产生 bit clock 和 byte clock;data lane 进 ISERDESE2,DDR 模式,串并宽度建议设 8 bit。
  3. 通过 BITSLIP 对每个 data lane 做 bit 滑移,搜索同步码或训练码。具体同步码要看协议层定义,DSI 和 CSI 的包起始同步码不一样。
  4. data lane 之间做 deskew,保证同一时刻所有 lane 的字节对齐。
  5. 把多 lane 的并行数据合并成字节流,送到上层协议解析。

这个骨架里,最容易翻车的是第三、四步。BITSLIP 只在合适时机滑动,否则会把已经对齐的 lane 又搞乱;多 lane deskew 又和 BITSLIP 互相影响。我的建议是先让所有 lane 分别独立搜索同步码,锁定之后再检查 lane 间相对延时,而不是一开始就一起调。

3.4 带宽计算别拍脑袋

接屏或者接 sensor 之前,先算链路带宽够不够。MIPI DSI 的链路总速率约等于 lane 数 × 单 lane 数据率。假设 4 lane、每 lane 1.2Gbps,总带宽就是 4.8Gbps。但协议开销要扣掉:包头的 4 字节、ECC/CRC、行消隐里的 blank 包等等,实际有效载荷通常按 85%~90% 估算。

以 1080p60 RGB888 为例,像素时钟约 148.5MHz,24bit 像素,纯数据率是 148.5×24 ≈ 3.56Gbps。如果链路上限是 4 lanes × 1Gbps = 4Gbps,再扣除协议开销,余量大约 10%~15%,勉强可行但已经偏紧。这时候建议提高 lane rate 而不是减少 lane 数,或者降低帧率。许多屏“偶尔闪一下”,并不是屏的问题,而是 lane rate 紧贴极限,物理层稍微劣化就出错。留 20% 余量是挺好的习惯。

4. RK3588 Linux适配MIPI屏:从DTS到屏幕上电

4.1 先看硬件,别急着改设备树

遇到 RK3588 + ST7701S 这种搭配时,很多人第一反应是去改 DTS。但我要先泼一盆冷水:设备树改得再漂亮,FPC 线序错了也白搭。MIPI 口插 FPC 后出现视频异常,先检查软排线是否插到位、方向是否正确、Pin 定义是否与显示模组一致。MIPI 信号频率高,FPC 本身就是一个易损点,金属手指磨损、弯折过度,都会导致 HS RX 收到断续信号。

另外,5V/3.3V 电源和复位时序应该用示波器确认一遍。先量屏供电、再量复位脚电平,最后在屏端 FPC 上量 MIPI 差分信号。很多点不亮的屏幕,不是驱动没写对,是屏供电压根没起来。RK3588 的 DSI 输出默认在启动阶段可能不发信号,所以你想直接看波形,得让内核先把 DSI 控制器拉起来。

4.2 设备树里的lane配置和link-frequencies

RK3588 的 DTS 中,DSI 节点会挂一个 panel 子节点。ST7701S 这类驱动 IC 通常使用兼容 Serial 接口的 DSI,需要配置 data lane 数量、lane 映射、reset GPIO、backlight 等。

以简化版为例:

&dsi0 { status = "okay"; panel@0 { compatible = "sitronix,st7701s"; reg = <0>; reset-gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; backlight = <&backlight>; port { panel_in_dsi: endpoint { remote-endpoint = <&dsi0_out>; >