1. MIPI LP RX 是什么:先搞清楚你在调哪条链路
做嵌入式显示或者图像采集的工程师,这几年几乎人手一块带 MIPI 接口的板子。MIPI D-PHY 的物理层,平时大家嘴上都是 HS、LP 一起说,可真到了自己用 FPGA 写接收端,或者调一块 ST7701S 的 DSI 屏点不亮的时候,才会发现问题的根源往往不在高速差分线上,而是那个经常被忽略的 LP(Low Power)模式。这篇文章围绕 MIPI LP RX 展开——也就是 D-PHY 低功耗模式下接收侧的设计与调试,把电平、状态机、FPGA 实现、屏幕适配和排查经验串起来讲一遍,适合正在做 MIPI 图像采集或显示驱动、尤其是被物理层折腾过的工程师参考。
1.1 一句话看懂 D-PHY 的两种工作模式
MIPI D-PHY 的每条 lane 物理上就是两根线,通常叫 Dp 和 Dn。这两种工作模式的区别,从电气上看得最清楚:
- High-Speed(HS)模式:两根线走差分信号,摆幅很小,典型只有 200mV 左右,速率可以做到每 lane 几百 Mbps 到 2.5Gbps。它负责搬运像素数据、大块图像内容。
- Low-Power(LP)模式:两根线各自作为单端信号使用,摆幅接近 1.2V,速率很低,一般 10Mbps 都算高了。它负责传输控制命令、状态反馈、同步序列,以及总线空闲时的状态维持。
LP-RX 就是接收侧去识别 LP 模式下这些单端电平的部分。你可以把 HS 理解成“满载货车”,把 LP 理解成“指挥旗语”——货车跑得再快,出发前也得先靠旗语确认路线,到了卸货点还得靠旗语停下来。在 MIPI 链路上,HS 数据包的前后必须有 LP 状态参与建立和退出,任何一次握手动作错了,数据显示根本没戏。
1.2 LP-RX 在 CSI-2 / DSI 链路中的真实位置
拿 CSI-2(摄像头接口)来说,一次正常传输的物理层序列是:
- 总线处于 LP-11 空闲态;
- 主机发送 HS 建立序列 LP-11 → LP-01 → LP-00,随后进入 HS-0;
- HS 模式下连续发送差分数据,包括 SoT、数据包、EoT;
- 最后通过 LP-00 → LP-10 → LP-11 退出,回到空闲。
这套序列里,接收端必须实时监视每一条 lane 上的 LP 状态,判断当前总线属于空闲、建立中、HS 传输还是退出中。你的 FPGA 也好、SoC 的 MIPI 控制器也好,都需要一个 LP-RX 通道持续工作,才能在正确的时间点打开 HS 接收通路。
DSI(显示接口)这边更直接。屏幕进入命令模式后,主机发往面板的初始化命令,比如 ST7701S 这类驱动 IC 的寄存器配置,几乎全走 LP 单端信号,数据速率低,但时序关系非常讲究。很多同学把配置数据配得像模像样,屏幕就是不亮,最后用示波器一看,LP 波形上的建立时间、保持时间完全不达标。所以 LP-RX 不只是 FPGA 底层实现的问题,它直接关系到驱动代码写出来有没有用。
2. 电气层与协议层:LP-RX 的核心约束
2.1 电平阈值、迟滞与端接电阻
MIPI D-PHY 规范对 LP-RX 的输入做了明确定义。以 1.2V 的 VDDIO 为例,接收端判定高电平的阈值大约在 0.55×VDD 附近,判定低电平的阈值大约在 0.30×VDD 附近,中间这段就是设计上刻意留出的迟滞区。实际 PHY 厂商的实现会略有差异,但思路一致:输入信号必须有一个清晰的“高”和“低”,而且状态翻转时不能因为噪声来回抖动。
这里有个普遍误解:很多人以为 MIPI 所有输入都要接 100 欧差分端接。事实上 100 欧差分端接只在 HS 模式需要,LP 模式走的是单端高阻输入,不端接。如果你的板子上 LP 通路被错误地加了端接电阻,你会发现 LP 电平被拉低,状态根本判不对。反之,HS 接收端如果省了端接,高速信号反射严重,眼图一团糟,这是两类问题,别混在一起查。
具体到 FPGA 实现,LP-RX 通常不能用差分缓冲器直接收。Xilinx 的 IBUFDS、Intel 的 LVDS 缓冲器是为 HS 差分信号设计的,而 LP 信号是两根线各自对地的单端电平。正确做法是给 Dp 和 Dn 分别分配普通单端输入引脚,设置成 LVCMOS18 或 LVCMOS33(按板子实际电平来),然后让内部逻辑去同时采样这两个电平。
2.2 四种 LP 总线状态与状态迁移
LP 模式的核心概念是四种总线状态,由 Dp、Dn 两根线的电平组合表达:
| 状态 | Dp 电平 | Dn 电平 | 含义 |
|---|---|---|---|
| LP-11 | 高 | 高 | 空闲 / 控制模式待机 |
| LP-01 | 低 | 高 | 常用于 HS 建立序列、反向传输 |
| LP-00 | 低 | 低 | HS 建立序列末段、ULPS |
| LP-10 | 高 | 低 | HS 退出序列、反向传输 |
把这四个状态映射到两位二进制数 {Dp, Dn},就是 2'b11、2'b01、2'b00、2'b10。你看,这不就是一根简单的两位并行总线嘛。收到端只要把两路单端信号同时采进来,就能实时解码总线处于什么相位。
关键在状态迁移的时序约束。比如 HS 建立序列要求 LP-11 保持一段时间(T_LPX,典型 50ns 以上),LP-01 要保持 T_HS-PREPARE(典型 40ns 以上),LP-00 之后要在规定窗口内完成进入 HS。规范里给的是最小值,实际调试时必须留足余量,尤其 FPGA 实现里采样时钟、逻辑延时都会吃掉一部分时间预算。
2.3 采样时钟怎么选
LP 数据速率虽然只有几 Mbps,但采样时钟不能只按奈奎斯特来。我习惯的做法是用一个 100MHz 到 200MHz 的时钟去过采样,原因有两个:
- 毛刺滤波需要时间分辨率。规范要求 LP-RX 能滤掉特定脉宽以下的噪声尖峰,过采样率越高,滤波窗口切得越准。
- 状态迁移的时间测量需要精度。判断 LP-01 持续了多久、够不够 T_HS-PREPARE,直接靠计时器累加,时钟越快,边界判断误差越小。
有的工程为了省资源,用 25MHz 去采 10Mbps 的 LP 信号,理论能采到,实际上稍微来点噪声整条链路就崩。做物理层实现,宁可多花几倍逻辑资源,也要把余量做足。
3. FPGA 实现 LP-RX 的完整方案(可直接抄作业)
3.1 顶层架构与引脚规划
我自己在项目里常用的顶层结构是这样划分的:
- 引脚层:Dp/Dn 各接一个单端输入缓冲,直接进 IO 逻辑;
- 同步层:用采样时钟打两到三拍,消除亚稳态;
- 解码层:把同步后的两路电平组合成 2-bit 状态;
- 滤波层:对状态做毛刺滤波,识别稳定状态;
- 状态机层:根据状态迁移产生 HS 使能、命令接收使能等控制信号;
- 数据层:把 LP 模式下收到的串行控制数据转成字节流。
引脚规划有个容易踩的坑:尽量让 Dp 和 Dn 落在同一个 IO Bank,并且电平标准一致。曾有块板子把 Dp 安排在 1.8V Bank、Dn 安排在 3.3V Bank,结果 LP 信号电平标准不统一,接收端判定阈值完全错位,折腾了两天才发现。
3.2 毛刺滤波与状态解码
同步之后先做滤波。MIPI 规范里 LP-RX 对噪声有明确容忍要求,具体数值会因 PHY 版本不同有差异,但设计思路上都是“太短的状态变化不认”。我习惯用可配置的滤波窗口,比如 5 到 10 个采样周期,只有连续 N 拍都是同一个状态,才认为状态真的变了。
滤波和状态迁移识别可以合并成一个简化的状态机,核心逻辑类似下面这样:
// 简化版 LP 状态识别,实际工程需要增加滤波计数器 reg [1:0] lp_state_raw; // {Dp, Dn} 同步后的原始组合 reg [1:0] lp_state_filt; // 滤波后的稳定状态 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin lp_state_filt <= 2'b11; filt_cnt <= 0; end else begin if (lp_state_raw == lp_state_filt) begin filt_cnt <= 0; end else if (filt_cnt >= FILTER_THRESHOLD) begin lp_state_filt <= lp_state_raw; filt_cnt <= 0; end else begin filt_cnt <= filt_cnt + 1; end end end这段逻辑的意思很直白:新状态必须连续稳定 FILTER_THRESHOLD 拍才被采纳,否则视为毛刺。实测下来这个结构对线缆耦合噪声、地弹导致的短暂跳变都有很好的抑制作用。注意滤波阈值不能设太大,否则真正的短脉冲状态(比如 LP-01 只持续 40ns 的建立序列)会被误滤掉。
3.3 LP 模式命令数据的字节恢复
DSI 命令模式或者某些反向通道里,LP 信号是真正的串行数据,不是单纯的状态序列。这时候接收端要做的就是把 Dp/Dn 上的沿变化还原成字节。常见做法是用过采样时钟检测起始位,然后按位中心采样。
具体流程:
- 检测到 LP-10 → LP-00 的下降沿,认为是起始条件;
- 以位周期的中间点为采样点,逐个采样后续位;
- 累计到 8 bit 后拼装成字节,同时检查结束位。
这里最大的坑是位周期的“零”漂移。尽管 LP 速率低,发送端的时钟也未必和你的采样时钟同源,位周期会有累计误差。如果有效数据有几十个字节,靠开头校准一次采样点可能不够,稳健的做法是每个字节都重新对齐起始沿,或者用数字锁相环跟踪沿位置。我在一个 CSI-2 反向命令通道的项目里实测过,不做逐字节重对齐,超过 16 字节的命令流就会出错,做了之后 256 字节都没问题。
3.4 与 HS-RX 的切换逻辑
LP-RX 和 HS-RX 不是两个独立工作的模块,它们必须协同。以 CSI-2 接收为例,正确的工作流是:
- LP-RX 先检测到 LP-11 → LP-01 → LP-00 的建立序列;
- 确认 LP-00 后启动 HS-RX,切换到差分接收通路;
- HS 数据接收过程中 LP-RX 仍然监视总线,一旦检测到退出序列迹象就准备复位 HS 通路;
- 检测到 LP-00 → LP-10 → LP-11 后,HS-RX 完全关断,回到 LP 空闲监视。
切换逻辑的时序配合要特别注意。HS-RX 内部的 CDR(时钟数据恢复)需要预热时间,建立序列长度是有限的,所以从 LP-00 识别到 HS 使能之间的延迟必须尽量短。我的做法是把 HS 使能信号直接由 LP-00 组合逻辑产生,不经过状态机额外一拍,把多余的启动延迟省掉。代价是可能引入一点点亚稳态风险,但配合 D 触发器同步和足够的建立时间预算,实际是可控的。
4. 屏幕适配与平台实战
4.1 ST7701S 这类 DSI 屏的 LP 时序要求
ST7701S 是现在低端 MIPI 屏里非常常见的一颗驱动 IC,很多 720p 甚至 1080p 的 DSI 屏都在用它。这颗 IC 对初始化命令的要求极其典型:上电后需要通过 LP 模式接收一串初始化序列,配置显示模式、时序参数、伽马等。
根据我调屏的经验,ST7701S 这类屏最容易出问题的不是命令内容错,而是 LP 时序不满足。以下几点几乎每次都会踩到:
- 命令开头需要足够的 LP-11 空闲时间,很多屏规定上电后要先保持一段时间总线空闲再发第一条命令;
- 每个命令之间的间隔要留够,太快了驱动 IC 来不及解析;
- LP 信号的高电平不要低于 VIH 阈值,尤其是在供电电压波动大的板子上。
常见的 RK3588 平台在内核里适配 MIPI 屏,用的就是这类初始化序列配置。你会在 dts 里看到类似init-sequence = <0x00 0x00 ...>的写法,每一组 hex 都对应一条 DSI 命令,最终会以 LP 信号的形式发给 ST7701S。序列写错一个字节屏幕可能只是显示异常,但时序配置错了,屏幕会直接点不亮。
4.2 RK3588 等 SoC 适配 MIPI 屏的检查点
RK3588 的 MIPI DSI 控制器功能很全,但恰恰因为功能全,适配时反而要多留个心眼。我在调 RK3588 驱动 MIPI OLED 屏的过程中,整理过一份检查清单,分享出来:
- dts 里的电源时序:MIPI 屏的 AVDD、VCCIO、RESET 脚顺序不对,屏幕要么不亮要么花屏,这属于 LP 之外的“隐性时序”,很多人忽略了;
- lane 映射:RK3588 的 DSI 控制器 lane 顺序可以配置,板子上的物理连接如果和 dts 不一致,现象是时钟有波形但图像全黑;
- 命令模式还是视频模式:OLED 屏多数用命令模式,需要每帧刷一次带数据命令;LCD 屏常用视频模式,配置方式完全不一样;
- LP 时钟极性:某些屏对数据线极性敏感,错了的话初始化命令发过去石沉大海。
如果调试时发现初始化命令已经发出去(示波器能看到 LP 波形),但屏没有反应,优先查 lane 映射和电源时序,这两个问题在 RK3588 上出现频率最高。
4.3 Deskew Calibration 是什么,要不要做
Deskew calibration(去偏斜校准)在 MIPI 界是个热门词,简单说就是校准多条 lane 之间的传播延迟差。高速模式下,数据 lane 和时钟 lane 的延时如果差太多,接收端采样窗口就会变小,严重时直接采错。
这个校准在两种情况下特别重要:
- 高速 PCB 上走线长度差异较大的时候;
- 使用连接器、FPC 软排线的时候。MIPI 屏用的 FPC 一旦走线不等长、弯折半径不一致,各 lane 偏斜会明显变大。
但这里要泼一盆冷水:deskew calibration 主要针对 HS 高速通路,和 LP-RX 没有直接关系。很多调屏新手听到“mipi dphy deskew calibration”就觉得是解决一切问题的万能钥匙,结果折腾半天发现自己的问题根本不在偏斜上。收到命令乱码先查 LP 采样和电压阈值,不要一步跳到 deskew。当然,如果你的高速数据眼图闭合、时序裕量不足,那确实需要做 lane-to-lane 的偏斜校准,FPGA 里可以通过可调延迟链(比如 Xilinx IDELAY)实现。
5. 常见问题与排查技巧实录
5.1 LP-RX 一直停在 LP-11,看不到任何命令
这个现象在调屏时出现频率极高:总线一直都是空闲电平,主机那边明明发了命令,接收端却像瞎了一样。我排查这类问题的顺序是:
- 先用示波器抓到 Dp/Dn 的实际波形,确认信号到底有没有过来。很多“看不到命令”其实是线没接好、连接器虚焊或者 FPC 插反了;
- 确认电平是否在判定阈值内。如果波形是 1.2V 摆幅但采样端配置成了 3.3V 输入,高电平没问题,但低电平可能达不到 VIL 阈值;
- 检查引脚约束。FPGA 里引脚分配错位或约束漏加,信号根本没进到你要的逻辑;
- 检查滤波阈值。毛刺滤波窗口设太大,真正的短命令脉冲会被当毛刺滤掉。
第四点最隐蔽。我有一次调一块紫光同创 FPGA 驱动 MIPI 屏的板子,命令怎么发都不响应,最后发现是滤波窗口把 LP-01 状态整个滤没了,建立序列永远走不完。把滤波阈值从 16 拍改成 4 拍就好了。
5.2 收到乱码与字节错位
命令能收到但内容是乱的,问题大概率出在采样相位。LP 数据是单端串行信号,没有专门的随路时钟,接收端全靠自己过采样对齐。应对方案是前面说的逐字节重对齐,也就是每个字节的起始沿都重新做一次采样点校正。
乱码还有一个常见来源:地电位差。当发送端(SoC)和接收端(FPGA)不在同一块板上,或者通过长排线连接时,两边参考地不一致,LP 信号的判定就会出现窗口偏移。这种情况除了保证共地之外,最好还是在接收端加一点迟滞余量,不要卡着规格边界算。
5.3 HS/LP 切换时丢尾
有时 HS 数据接收正常,但每次传输的结尾都会丢几个字节,或者下一条命令直接失步。这通常是 HS 退出序列和 LP 空闲重建的衔接出了问题。
排查思路是盯紧退出序列:HS 数据结束后,总线先回 LP-00,然后 LP-10,最后稳定在 LP-11。如果你的 LP-RX 状态机在 LP-00 阶段就过早复位了 HS 通路,尾部数据就会被截断;反过来如果 HS 通路关断太晚,LP-10 状态可能被误当成 HS 数据采进去。正确的做法是:在检测到 LP-00 之后,用一个可配置的延迟窗口关断 HS,窗口大小按 HS 尾部的 EoT 长度来定。
5.4 物理排查工具清单
最后列一份我在现场调试时会备齐的工具,每一件都派上过用场:
| 工具 | 用途 |
|---|---|
| 四通道示波器(500MHz 以上) | 同时看 Dp、Dn、时钟、复位,抓 LP 状态迁移 |
| 有源差分探头 | 测 HS 差分信号,眼图、摆幅,避免接地回路 |
| FPC 转接板 | 延长线调试屏幕时保证阻抗和信号完整性 |
| I2C/逻辑分析仪 | 对照屏的初始化命令,确认配置是否被正确发出 |
示波器探头带宽不够的话,看 LP 信号还行,看 HS 信号就是一坨模糊的波形,无法判断真实质量。这部分投资别省。
6. 一点个人体会
我做了这么多年 MIPI 相关的调试,最深的感觉是:LP-RX 在整条链路里不起眼,但它就像门锁,开不了门,屋里再好的东西也搬不出去。很多工程师把精力放在 HS 眼图和 CDR 配置上,结果折腾到最后,问题不过是 LP 状态机里一个滤波参数设错了。
我自己现在的习惯是,新板子回来先把 LP 通路单独验证一遍,写一个简单的 loopback 或监视逻辑,确认四种 LP 状态都能正确识别,再做高速链路的调试。这一步虽然花时间,但能省掉后面至少一周的联调痛苦。希望这篇文章里提到的思路、代码和排查顺序,也能让你少走一些我走过的弯路。