1. 从一个“调不通”的屏说起:MIPI LP RX 到底在解决什么问题
如果你做过嵌入式显示或者摄像头相关的项目,大概率遇到过这种场景:硬件上电,主控和屏幕之间的高速数据通道(HS)看起来已经跑起来了,示波器上也能抓到差分信号在翻转,但屏幕就是不亮,或者初始化命令发不下去,读回来的寄存器值永远是0xFF或者0x00。这时候很多人第一反应是“时序不对”“时钟没配好”,但真正卡住你的,往往是那条看起来不起眼的低速通道——MIPI LP(Low Power)模式下的接收通路。
MIPI LP RX,说白了就是 MIPI D-PHY 里负责低速、低功耗状态下的信号接收部分。它不跑图像数据,跑的是控制命令、寄存器读写、以及链路建立前的握手信息。你可以把它理解成一条“管理通道”:高速通道是运货的大卡车,LP 通道就是调度室的对讲机。对讲机不通,卡车再多也进不了站。这个内容适合所有在做 MIPI 屏幕点亮、摄像头模组调试、FPGA 对接 MIPI 接口的工程师,尤其是那些 HS 已经通了、却卡在初始化阶段的同学。
我这些年接触过 ST7701S、ILI9881、以及各种 MIPI 液晶屏的调试,也用过紫光同创、Xilinx 的 FPGA 去实现 MIPI 收发。踩过的坑里,至少有一半跟 LP RX 有关。下面我把这套东西从设计思路到实操细节完整拆一遍,尽量让你少走弯路。
2. 内容整体设计与思路拆解
2.1 为什么 LP 通道比 HS 更容易出问题
很多人有个误区:HS 速率高,肯定更难做。实际上在工程里,HS 差分信号只要阻抗控制好、走线等长、参考时钟稳定,反而容易一次通。LP 通道是单端信号,电平标准跟 HS 完全不同,而且它依赖上拉电阻、驱动能力、以及收发两端的时序配合。任何一个环节偏了,LP 就收不到正确的电平。
MIPI D-PHY 的 LP 模式定义了四种线路状态:LP-00、LP-01、LP-10、LP-11。这四种状态通过两条线(Dp 和 Dn)的不同电平组合来表示。LP-11 是空闲态(Stop State),LP-00 到 LP-10 的跳变序列用来表示进入 HS 或者发送 Escape 命令。接收端要能准确识别这些状态,才能正确解析出控制信息。
注意:LP 状态的电平阈值不是固定的 1.2V 或 1.8V,而是相对于 VDD 的比例。很多新手直接拿 1.8V 的 GPIO 去接,结果电平不匹配,LP RX 永远识别不到 LP-11。
2.2 方案选型的核心考量:用硬核还是软核
在实际项目里,实现 MIPI LP RX 有三条路:
- 专用 PHY 芯片:比如一些 MIPI 桥接芯片,内部集成了完整的 D-PHY,你只需要配置寄存器。优点是省心,缺点是灵活性差,成本高,而且有些芯片的 LP 时序是固定的,改不了。
- FPGA 软核实现:用 FPGA 的普通 IO 加上拉电阻,自己写状态机去采样 LP 信号。优点是灵活,可以针对特定屏幕调时序;缺点是对 IO 的输入延迟、采样时钟要求高,尤其是 LP 的脉宽可能只有几十纳秒。
- SoC 内置 PHY:像 RK3588 这类芯片,MIPI 控制器和 PHY 都是集成的,你只需要配置设备树和驱动。这是最省事的,但一旦出问题,排查手段有限,因为你看不到 PHY 内部的状态。
我个人的经验是:如果是产品量产,优先用 SoC 内置 PHY;如果是调试阶段或者需要对接非标屏幕,FPGA 软核更可控。紫光同创的 FPGA 我用来驱动过 MIPI 屏,LP RX 部分就是用普通 IO 加状态机实现的,后面会详细讲。
2.3 LP RX 在整个链路中的位置
一条完整的 MIPI 链路,从发送端到接收端,LP 信号要经过:发送端 LP 驱动器 -> PCB 走线 -> 接收端 LP 接收器 -> 状态机解析。LP RX 的任务就是把线路上的四种状态准确还原成数字逻辑,然后交给协议层去判断是 Short Packet、Long Packet 还是 Escape 模式命令。
这里有个关键点:LP RX 不是简单的 GPIO 读取。因为 LP 信号的跳变可能很快,而且要在 HS 和 LP 之间切换,接收端需要有一个稳定的采样机制。通常做法是用一个比 LP 信号频率高得多的时钟去过采样,然后做边沿检测和状态解码。
3. 核心细节解析与实操要点
3.1 LP 四种状态的物理层定义
先把这个基础打牢。MIPI D-PHY 规定,每条 Lane 有两根线:Dp 和 Dn。LP 模式下,这两根线是独立驱动的单端信号。四种状态如下:
| 状态 | Dp 电平 | Dn 电平 | 含义 |
|---|---|---|---|
| LP-00 | 低 | 低 | Bridge 状态,用于 Escape 模式 |
| LP-01 | 低 | 高 | 表示数据 0 |
| LP-10 | 高 | 低 | 表示数据 1 |
| LP-11 | 高 | 高 | Stop 状态,空闲 |
这里的“高”和“低”是相对于接收端的供电电压。通常 LP 信号的摆幅是 0 到 1.2V,但阈值一般在 0.4V 到 0.8V 之间。具体要看 PHY 的规格书。
提示:如果你用 FPGA 的普通 IO 去接收 LP 信号,一定要确认 IO 的输入阈值。有些 FPGA 的 LVCMOS 输入阈值是 0.5*VCC,如果 VCC 是 3.3V,阈值就是 1.65V,而 LP 信号最高才 1.2V,那就永远识别不到高电平。这时候需要加电平转换或者用支持更低阈值的 IO Bank。
3.2 LP RX 状态机的设计思路
在 FPGA 里实现 LP RX,核心是一个状态机。我一般会这样设计:
- 用一个 200MHz 的时钟去采样 Dp 和 Dn(假设 LP 信号最窄脉宽是 50ns,200MHz 采样周期 5ns,足够过采样)。
- 对 Dp 和 Dn 分别做同步和去抖,通常连续采样 3 次相同才认为电平稳定。
- 根据 Dp 和 Dn 的当前电平,解码出 LP 状态。
- 检测状态跳变序列,判断是进入 HS 还是 Escape 命令。
这里有个细节:LP 信号在进入 HS 之前,会有一个 LP-11 -> LP-01 -> LP-00 的序列,然后才是 HS-0。接收端要能准确捕捉这个序列,否则会误判。我试过用简单的边沿检测,结果因为信号振铃导致误触发,后来加了数字滤波才稳定。
3.3 上拉电阻和驱动能力的匹配
LP 模式是单端信号,发送端和接收端都需要有上拉电阻。通常发送端有可配置的上拉,接收端也有。如果两边都上拉,可能会导致电平拉不低;如果都不上拉,又可能浮空。
我的经验是:接收端保持一个弱上拉(比如 10kΩ 到 100kΩ),发送端根据协议要求配置。在 FPGA 实现时,如果 FPGA 的 IO 支持内部上拉,可以用内部上拉,但要注意内部上拉的阻值可能不准,最好还是外部加一个。
注意:LP 信号的上升沿和下降沿时间也有要求,太快会导致 EMI 问题,太慢会导致接收端识别错误。一般建议上升/下降时间在 1ns 到 10ns 之间。如果走线很长,可能需要加串联电阻来匹配。
3.4 与 HS 模式的切换时序
LP RX 不仅要能接收 LP 信号,还要能正确判断什么时候切换到 HS 模式。这个切换过程是:LP-11 -> LP-01 -> LP-00 -> HS-0。接收端在检测到 LP-00 之后,要在一个很短的时间内切换到 HS 接收模式,否则会丢失 HS 同步头。
在 FPGA 里,这个切换通常是通过一个多路选择器来实现的:LP 状态机检测到进入 HS 的序列后,输出一个切换信号,把接收通路从 LP 采样切换到 HS 差分接收。这个切换的延迟要尽可能小,否则 HS 的第一个 bit 可能采不到。
我实测下来,如果用普通 IO 做 LP 接收,切换延迟大概在 10ns 到 20ns 左右,对于大多数 MIPI 屏幕来说够用了。但如果 HS 速率很高(比如 1Gbps 以上),这个延迟就可能造成问题,需要考虑用专用的 SelectIO 或者 ISERDES 来做。
4. 实操过程与核心环节实现
4.1 硬件准备与信号测量
在开始写代码之前,先确认硬件。你需要:
- 一块带 MIPI 接口的屏幕或者摄像头模组。
- 主控板(SoC 或者 FPGA 开发板)。
- 示波器或者逻辑分析仪,带宽至少 500MHz,最好 1GHz 以上。
- 如果可能,准备一个 MIPI 协议分析仪,但那个东西很贵,一般用示波器抓 LP 信号就够了。
先上电,用示波器抓 Dp 和 Dn 的波形。正常情况下,你应该能看到 LP-11 的空闲态,然后是一串 LP 跳变。如果什么都看不到,先检查供电和上拉电阻。如果看到的是乱七八糟的波形,可能是发送端没有正确配置。
提示:抓 LP 信号的时候,示波器探头要用高阻探头,不要用 50Ω 匹配,否则会把信号拉死。触发方式可以设成 Dp 的下降沿,这样容易抓到进入 HS 的序列。
4.2 FPGA 端 LP RX 的 Verilog 实现
下面是我在紫光同创 FPGA 上实际用过的 LP RX 核心代码。为了便于理解,我做了简化,去掉了跟具体项目相关的部分。
module mipi_lp_rx ( input wire clk, // 200MHz 采样时钟 input wire rst_n, input wire dp_in, // Dp 输入 input wire dn_in, // Dn 输入 output reg lp_state, // 解码后的 LP 状态 output reg lp11_flag, // LP-11 检测 output reg hs_req // 请求切换到 HS ); // 同步和去抖 reg dp_sync0, dp_sync1, dp_sync2; reg dn_sync0, dn_sync1, dn_sync2; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin dp_sync0 <= 1'b0; dp_sync1 <= 1'b0; dp_sync2 <= 1'b0; dn_sync0 <= 1'b0; dn_sync1 <= 1'b0; dn_sync2 <= 1'b0; end else begin dp_sync0 <= dp_in; dp_sync1 <= dp_sync0; dp_sync2 <= dp_sync1; dn_sync0 <= dn_in; dn_sync1 <= dn_sync0; dn_sync2 <= dn_sync1; end end wire dp_stable = (dp_sync0 & dp_sync1 & dp_sync2) | (~dp_sync0 & ~dp_sync1 & ~dp_sync2); wire dn_stable = (dn_sync0 & dn_sync1 & dn_sync2) | (~dn_sync0 & ~dn_sync1 & ~dn_sync2); // 状态解码 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin lp_state <= 2'b00; lp11_flag <= 1'b0; hs_req <= 1'b0; end else if (dp_stable && dn_stable) begin case ({dp_sync2, dn_sync2}) 2'b00: lp_state <= 2'b00; // LP-00 2'b01: lp_state <= 2'b01; // LP-01 2'b10: lp_state <= 2'b10; // LP-10 2'b11: lp_state <= 2'b11; // LP-11 endcase lp11_flag <= (dp_sync2 & dn_sync2); // 检测 LP-11 -> LP-01 -> LP-00 序列 if (lp_state == 2'b11 && {dp_sync2, dn_sync2} == 2'b01) hs_req <= 1'b1; else if (lp_state == 2'b00) hs_req <= 1'b0; end end endmodule这段代码的核心就是同步、去抖、解码、序列检测。实际项目中,你可能还需要加上超时检测、错误计数等功能。
4.3 参数计算与时钟选择
采样时钟的选择很关键。假设 LP 信号的最窄脉宽是 50ns,那么采样周期至少要小于 25ns,也就是采样频率要大于 40MHz。但为了可靠去抖,我一般会用 200MHz,这样每个 LP 状态至少能采到 10 个点。
如果你用的 FPGA 时钟资源有限,可以用 100MHz,但去抖的连续采样次数要相应减少,比如改成 2 次。不过 2 次去抖的抗干扰能力会差一些,信号质量不好的时候容易误判。
提示:LP 信号的脉宽跟具体协议有关。比如 Escape 模式下的命令,有些脉宽只有 20ns 左右。如果你的采样时钟只有 100MHz,可能采不到。所以建议先用示波器量一下最窄脉宽,再决定采样时钟。
4.4 与协议层的对接
LP RX 解码出来的状态,最终要交给协议层去解析。协议层需要知道:
- 当前是 LP 模式还是 HS 模式。
- 如果是 LP 模式,是 Short Packet 还是 Escape 命令。
- 如果是 Escape 命令,具体是什么命令(比如 Reset、ULPS、Trigger 等)。
在 FPGA 里,我通常会用一个简单的状态机来解析 Escape 命令。Escape 模式的进入序列是 LP-11 -> LP-01 -> LP-00 -> LP-01 -> LP-00,然后才是具体的命令。这个序列比较长,需要仔细检测。
5. 常见问题与排查技巧实录
5.1 LP RX 收不到任何信号
这是最常见的问题。排查顺序如下:
- 检查供电和上拉:用万用表量 Dp 和 Dn 的静态电平。如果是 LP-11,应该都是高电平。如果都是低电平,可能是上拉没接或者发送端在驱动低。
- 检查 IO 阈值:确认 FPGA 或 SoC 的 IO 输入阈值是否低于 LP 信号的高电平。如果阈值太高,需要换 IO Bank 或者加电平转换。
- 检查采样时钟:用示波器看采样时钟是否正常。如果时钟没起来,状态机就不会工作。
- 检查约束文件:FPGA 的引脚约束是否正确,输入延迟是否设置合理。
我遇到过一种情况:FPGA 的 IO 约束里把 Dp 和 Dn 配成了差分对,结果 LP 模式下单端信号被差分接收器吃掉了,什么都收不到。后来改成普通单端 IO 就正常了。
5.2 LP 状态跳变误判
有时候 LP RX 能收到信号,但状态跳变总是误判,导致协议层解析错误。原因通常是信号振铃或者去抖不够。
解决办法:
- 增加去抖的连续采样次数,比如从 3 次增加到 5 次。
- 在 PCB 上靠近接收端加一个小电容(比如 10pF)来滤高频振铃,但注意电容不能太大,否则会拖慢边沿。
- 调整采样时钟的相位,让采样点落在信号稳定的中间位置。
注意:加电容滤波是一把双刃剑。LP 信号本身速率不高,加 10pF 一般没问题,但如果加到 100pF,边沿就会变得很慢,可能导致 HS 切换时丢失同步头。
5.3 进入 HS 后 LP RX 干扰 HS 接收
有些设计里,LP RX 和 HS RX 共用同一组引脚。如果 LP RX 的状态机在 HS 模式下还在运行,可能会产生错误的切换信号,干扰 HS 接收。
解决办法是在进入 HS 模式后,把 LP RX 的状态机暂停或者复位,等 HS 传输结束、回到 LP-11 后再重新使能。这个控制逻辑要跟协议层配合好。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 完全无信号 | 供电/上拉异常 | 万用表量静态电平 | 检查上拉电阻和供电 |
| 电平识别错误 | IO 阈值不匹配 | 查 FPGA IO 手册 | 换 IO Bank 或加电平转换 |
| 状态跳变误判 | 振铃/去抖不足 | 示波器看波形 | 增加去抖次数或加小电容 |
| HS 切换失败 | 切换延迟太大 | 逻辑分析仪抓时序 | 优化状态机或改用专用 IO |
| Escape 命令解析错误 | 序列检测不全 | 对照协议查序列 | 完善状态机 |
5.5 独家避坑技巧
- 先抓波形再写代码:不要一上来就写 Verilog,先用示波器把 LP 信号的波形抓清楚,知道脉宽、电平、跳变序列,再动手写。
- 用 LED 做状态指示:在调试阶段,把 LP 状态机的关键状态输出到 LED 上,比如 LP-11 亮一个灯,HS 请求亮另一个灯。这样不用逻辑分析仪也能大致判断状态。
- 保留测试点:PCB 上一定要留 Dp 和 Dn 的测试点,最好还有采样时钟的测试点。调试的时候你会感谢自己。
- 不要忽略地线:LP 信号是单端的,对地线质量很敏感。如果地线不好,信号上会有很多噪声。确保接收端和发送端有良好的共地。
6. 从屏幕点亮到系统集成:LP RX 的延伸思考
6.1 不同屏幕的 LP 时序差异
ST7701S 和 ILI9881 这类屏幕,LP 初始化序列的时序要求不完全一样。有些屏幕对 LP 的脉宽要求很严格,比如要求 LP-00 的持续时间在 40ns 到 80ns 之间。如果你的 FPGA 状态机响应太慢,可能就错过了。
我在调试 ST7701S 的时候,发现它的 Escape 模式进入序列比标准协议要求的要快一些。后来把采样时钟提高到 250MHz,并且减少了去抖次数,才稳定下来。所以不要迷信“标准”,要以实际屏幕的规格书为准。
6.2 FPGA 实现 MIPI 的优劣势
用 FPGA 实现 MIPI LP RX,最大的优势是灵活。你可以根据屏幕的实际情况调整采样时钟、去抖次数、状态机响应速度。而且 FPGA 可以同时做多路 LP RX,适合多 Lane 的应用。
劣势也很明显:占用逻辑资源,而且 LP 信号的时序约束比较麻烦。如果 FPGA 的 IO 延迟太大,可能需要在 PCB 上做补偿。另外,FPGA 的普通 IO 做 LP 接收,抗干扰能力不如专用 PHY。
6.3 与 SoC 方案的对比
RK3588 这类 SoC,MIPI 控制器是集成的,LP RX 由硬件自动处理。你只需要在设备树里配置好参数,比如时钟频率、Lane 数量、LP 时序等。优点是省事,缺点是出了问题不好排查。
我遇到过 RK3588 的 MIPI 输入 1080i 信号时,LP RX 偶尔会丢帧。后来发现是设备树里的 LP 时序参数跟屏幕不匹配,调整之后就好了。所以即使是 SoC 方案,也要仔细看屏幕的规格书,把 LP 相关的参数配对。
6.4 实际项目中的经验总结
做了这么多项目,我最大的体会是:LP RX 虽然只是 MIPI 链路里的一小部分,但它决定了整个链路能不能建立起来。很多“屏幕不亮”“没信号”的问题,根源都在 LP 通道。
如果你正在调试 MIPI 屏幕,建议先把 LP RX 调通,确认能正确收到 LP-11 和 Escape 命令,再去调 HS。这样问题会少很多。另外,不要怕麻烦,多用示波器和逻辑分析仪,把波形抓清楚,比盲目改代码有效得多。
最后分享一个小技巧:如果你用的是 Xilinx 或紫光同创的 FPGA,可以用 IDELAY 或者 IDELAYE2 来调整输入延迟,这样可以在不改变 PCB 的情况下,微调 LP 信号的采样点。我试过用 IDELAY 把 LP RX 的误码率从 10% 降到几乎为零,效果很明显。