4. D-PHY 简介:MIPI D-PHY 标准、工作模式、数据通道与时钟通道

咱们做嵌入式驱动开发,早晚要跟 MIPI D-PHY 打交道。我最早接触它是在一个摄像头模组调试项目里,板子都画好了,结果 MIPI 信号怎么都锁不住。后来一查,原来是我对 D-PHY 的电气特性理解不够深。说白了,D-PHY 就是 MIPI 联盟定义的物理层标准,专门用来在摄像头和显示屏这类外设与 SoC 之间高速传数据。

4.1 D-PHY 标准到底是什么?

MIPI D-PHY 是一套 串行、差分、低功耗 的物理层规范。它不像 USB 或者 HDMI 那样用固定的封装,而是给了你很灵活的组合方式。一根通道(lane)里包含两条线:一条正极(DP/DnP),一条负极(DN/DnN)。信号就靠这对差分线上的电压差来传递。

核心要点:D-PHY 定义了两种工作模式——高速 (HS) 模式 和 低功耗 (LP) 模式。HS 模式用来怼大带宽数据,LP 模式用来做控制信号或者省电。两种模式可以快速切换,这也是 D-PHY 最牛的地方。

我建议你记住这个数:D-PHY 的 HS 模式单通道速率可达 80 Mbps ~ 4.5 Gbps(规范 v2.0 以后更高)。LP 模式只有约 10 Mbps,但功耗极低。

4.2 工作模式:HS 与 LP 的切换逻辑

很多人刚学 D-PHY 时被它的状态机搞晕。其实没那么复杂。你想想看,两条线上各有两个电压状态:HS 时差分对摆动幅度很小(约 200 mV 峰峰值),共模电压在 200 mV 左右;LP 时单端电压跳到 1.2V 或 0V。

我总结了一个快速判断的方法:

  • HS 模式:差分对上的信号像正弦波一样反转,摆幅小、频率高。用来传像素数据、解串后的字节流。
  • LP 模式:单端线上只有 0 或 1 逻辑(1.2V / 0V)。用来传 CS(控制)、Turnaround、Escape 等握手信号。

两种模式之间靠 高速退出序列 和 高速进入序列 来切换。我曾经在一个项目中遇到过切换时序不满足的情况,导致 LP 转 HS 时 bus 上出现毛刺,接收端 CRC 报错。后来加上一个 100 ns 的等待才解决。

注意:HS 模式必须在 LP 模式先进入一个特定的“高速准备”状态(HS-Prepare),时间窗口约 40 ns。如果 MDIO 配置的 D-PHY 寄存器给的空闲时序不对,那就等着丢包吧。

4.3 数据通道与时钟通道

D-PHY 链路至少包含 一条时钟通道 和 一到多条数据通道。我习惯把时钟通道想象成“节拍器”,数据通道跟着它跳。架构图如下:

D-PHY 链路结构 (1 CLK Lane + 2 Data Lanes) SoC 发送端 设备接收端 时钟通道 (CLK) 数据通道 0 (DL0) 数据通道 1 (DL1) 说明: 时钟通道提供双向随路时钟(DDR,即在上升沿和下降沿都采样数据)。 数据通道在 LP 模式下可单独用于控制或 Escape 序列。

上面的图我故意只画了 1 条时钟 + 2 条数据。实际应用中,一个 D-PHY 链路可以支持最多 4 条数据通道,每条数据通道都是独立差分队。时钟通道固定为 DDR 双边沿采样,也就是说每周期采样两次,数据速率是时钟频率的两倍。

通道类型 方向 典型速率 主要用途
时钟通道 (CLK) 单向 (发送→接收) 最高 2 GHz DDR 随路时钟,数据采样基准
数据通道 (DATA) 单向或双向 最高 4.5 Gbps 传输像素/指令/状态

4.4 通道操作状态机

每条通道的状态由 电平组合 来标志。LP 模式下两条线上有 11、10、01、00 四种状态,每个状态有特定含义。比如 BS (Bridge Stop) 状态就是 LP-11,代表总线空闲。

我当年调 D-PHY 时,最头疼的就是 Escape 模式进入。要发送一串特定的 LP 序列(LP-11 → LP-10 → LP-00 → LP-01 → LP-00 …),然后才能进入 Escape 命令。你想想看,如果时序偏差一点点,接收端就会解析成不同的状态。

一个小技巧:在调试时用逻辑分析仪同时抓 CLK+ 和 CLK- 两根线,然后观察差分波形。HS 模式下的“共模电压”必须稳定,否则说明你的 PLL 或者终端阻抗有问题。

4.5 字节与通道分配:映射逻辑

数据从 SoC 送入 D-PHY 发送器时,是按照 字节 (Byte) 为单位分配到各个数据通道上的。假设你有 2 条数据通道,每个时钟周期会同时发送 2 个字节(每个通道一个字节)。

// 伪代码示例:字节到通道的映射
// 假设 4 条数据通道 (DL0~DL3)
// 在时钟周期 N,发送字节 B0~B3
// DL0 发送 B0, DL1 发送 B1, DL2 发送 B2, DL3 发送 B3
// 下一个时钟周期再发送 B4~B7

void byte_to_lane_mapping(uint8_t *data, uint32_t len) {
    for (uint32_t i = 0; i < len; i += num_lanes) {
        for (uint32_t lane = 0; lane < num_lanes; lane++) {
            lane_buffer[lane].next_byte = data[i + lane];
        }
    }
}

这个映射对驱动工程师来说,主要影响 MDIO 寄存器配置。D-PHY 内部有一组 时钟分频 和 通道启用 寄存器。比如你要启用第 3 条通道,就需要把对应 bit 置 1。我曾经遇到过一个 bug:忘记配置 lane mapping 顺序,结果接收端看到的像素数据全是乱的——红通道跑到绿通道去了。

4.6 调试避坑:我的亲身体会

如果你用 MDIO 去改写 D-PHY 的 LP 模式电压阈值寄存器,注意写完后要等待至少 10 us 再切模式,否则新阈值还没生效,导致误判状态。我曾在某款 SoC 上吃过这个亏,花了整整两天才发现。

再提一个关于 Termination 的点:D-PHY 的 HS 模式需要终端电阻(50 Ω 对地),而 LP 模式不需要。如果终端没接好,HS 信号反射会很大。我自己做开发板时特意加了一对拨码开关,可以随时断开终端,方便对比测试。

嗯,这一章我们就先聊到这。D-PHY 核心概念其实不多:标准、HS/LP 模式、通道结构、状态机。你只要记住这几条,后面看 MDIO 访问寄存器时就不会发懵。