4. 传感器驱动与接口:MIPI CSI-2 协议详解

好,咱们进入第四章。这一章聊的是摄像头和 SoC 之间的“高速公路”——MIPI CSI-2 接口。说白了,就是 sensor 拍完一张 raw 图,怎么高速、可靠地传给 ISP。

我早年做第一个手机摄像头项目时,就在这上面栽过跟头。sensor 输出明明对的,ISP 这边就是花屏。查了三天,最后发现是 D-PHY 的 skew 没调好。嗯,从那以后,我对 MIPI 的物理层和协议层就格外上心。

4.1 为什么需要 MIPI CSI-2?

传统摄像头接口,比如并行接口,需要十几根甚至二十几根数据线。在手机这种寸土寸金的地方,根本走不通。MIPI 联盟搞出了 CSI-2(Camera Serial Interface 2),用差分串行传输,几对线就能搞定高带宽。

它的核心优势就三点:

  • 高速:单 lane 速率从几百 Mbps 到几 Gbps,多 lane 并行,带宽轻松上 10Gbps+。
  • 抗干扰:差分信号,共模噪声被抑制,走线长一点也没事。
  • 引脚少:一个 4-lane 的 CSI-2,加上时钟也就 10 根线左右。你想想看,要是用并行,得 30 根往上。

4.2 物理层:D-PHY vs C-PHY

MIPI 物理层目前主流就两种:D-PHY 和 C-PHY。我习惯把 D-PHY 比作“经典款”,C-PHY 是“升级款”。

4.2.1 D-PHY

D-PHY 是差分对结构,一对线就是一条 lane。每条 lane 包含两根线:DP 和 DN。时钟 lane 单独一对,数据 lane 可以配 1、2、4 条。

它的工作模式分两种:

  • HS(High Speed)模式:高速数据传输,差分摆幅只有 200mV 左右,功耗低。
  • LP(Low Power)模式:控制指令传输,单端信号,摆幅 1.2V,速率慢但省电。

这里有个关键点:D-PHY 是 DDR(Double Data Rate) 传输。时钟的上升沿和下降沿都采数据。比如 1Gbps 的速率,时钟频率其实只有 500MHz。

避坑指南:我曾经在一个项目中,PCB 走线时没注意 D-PHY 的等长要求。结果四条数据 lane 的 skew 超过了 0.2UI,导致接收端采样出错。后来强制要求每条 lane 对内等长控制在 5mil 以内,lane 间等长控制在 20mil 以内,问题才解决。

4.2.2 C-PHY

C-PHY 是 D-PHY 的进化版。它用三根线组成一个 trio,不再需要单独的时钟 lane。数据通过三线之间的电压差来编码,每个 trio 能传 2.28 bits/UI。

为什么是 2.28?因为三线有 6 种状态,每次跳变只能转到另外 5 种状态中的一种。log2(5) ≈ 2.32,再扣掉一些编码开销,实际有效值就是 2.28。

C-PHY 的优势很明显:

  • 同样 pin 数下,带宽比 D-PHY 高约 1.7 倍。
  • 不需要时钟 lane,节省一对线。
  • EMI 更低,因为三线信号变化更平缓。

但代价是协议更复杂,接收端需要做 3 线到 2 线的解码。我个人觉得,如果带宽需求在 10Gbps 以下,D-PHY 足够成熟稳定。超过 10Gbps,C-PHY 是更好的选择。

特性 D-PHY C-PHY
物理结构 差分对(2线/lane) 三线组(3线/trio)
时钟 独立时钟 lane 内嵌时钟
每 pin 带宽 1 Gbps/pin(约) 1.7 Gbps/pin(约)
协议复杂度 低 高
EMI 中等 低
典型应用 手机、车载、安防 高端手机、AR/VR

4.3 数据打包格式:从 raw 到 byte

物理层搞定后,数据怎么组织?这就是 CSI-2 协议层的事。它定义了一套分层结构:

  1. 应用层:像素数据,比如 raw10、raw12、YUV422。
  2. 协议层:把像素打包成包(Packet),加上包头包尾。
  3. 链路层:处理 CRC、ECC、帧同步。
  4. 物理层:D-PHY 或 C-PHY 的电气传输。

咱们重点看协议层的包结构。一个包分为 长包 和 短包。

4.3.1 短包(Short Packet)

短包只有 32 bits,用于传输帧同步、行同步等控制信息。结构如下:

| 数据标识符 (8 bits) | 虚拟通道 (2 bits) | 数据类型 (6 bits) | 帧号/行号 (16 bits) | ECC (8 bits) |

比如,帧起始(Frame Start)的数据类型是 0x00,帧结束(Frame End)是 0x01。行起始(Line Start)是 0x02,行结束(Line End)是 0x03。

4.3.2 长包(Long Packet)

长包传输实际的像素数据。结构分三部分:

| 包头 (32 bits) | 数据载荷 (可变长度) | 包尾 (16 bits CRC) |

包头格式:

| 数据标识符 (8 bits) | 虚拟通道 (2 bits) | 数据类型 (6 bits) | 字计数 (16 bits) | ECC (8 bits) |

这里 字计数 表示数据载荷的字节数。ECC 是 8 位的纠错码,能纠正 1 bit 错误,检测 2 bit 错误。

包尾就是 16 位的 CRC,校验整个数据载荷的完整性。

经验之谈:我建议你在调试时,先抓一个完整的帧,检查短包的帧起始和帧结束是否成对出现。如果帧结束丢了,ISP 会一直等数据,导致卡死。我曾经遇到过 sensor 在低光照下帧结束偶尔丢失,后来在 sensor 驱动里加了超时重传机制才搞定。

4.4 数据类型与虚拟通道

数据类型(Data Type, DT)告诉接收端,这包数据是什么格式。常见的 DT 值:

数据类型 DT 值 (Hex) 说明
RAW6 0x28 6-bit raw 数据
RAW8 0x2A 8-bit raw 数据
RAW10 0x2B 10-bit raw 数据
RAW12 0x2C 12-bit raw 数据
RAW14 0x2D 14-bit raw 数据
YUV420 8-bit 0x1E YUV 4:2:0 格式
YUV422 8-bit 0x1E YUV 4:2:2 格式
RGB888 0x24 24-bit RGB
Embedded Data 0x12 嵌入式元数据(增益、曝光等)

虚拟通道(Virtual Channel, VC) 允许在同一个物理链路上传输多路视频流。比如,主摄像头用 VC0,副摄像头用 VC1。ISP 根据 VC 号区分数据来源。

4.5 数据打包示例:RAW10 格式

咱们以 RAW10 为例,看看像素怎么打包成字节流。RAW10 每个像素 10 bits,4 个像素凑成 5 个字节。

假设四个像素值:P0=0x3FF, P1=0x2AA, P2=0x155, P3=0x000。

打包方式:

Byte 0: P0[9:2]  → 0xFF
Byte 1: P1[9:2]  → 0xAA
Byte 2: P2[9:2]  → 0x55
Byte 3: P3[9:2]  → 0x00
Byte 4: P0[1:0] | (P1[1:0] << 2) | (P2[1:0] << 4) | (P3[1:0] << 6) → 0x3F | 0x28 | 0x54 | 0x00 = 0xE4

注意,Byte 4 是四个像素的低 2 bits 拼起来的。这种打包方式叫 packed format,节省带宽。

注意:有些 sensor 支持 unpacked format,每个像素占 2 字节,高 6 bits 补零。这样带宽浪费了,但处理简单。我建议你在带宽够用的情况下,优先用 unpacked,调试起来方便很多。

4.6 整体数据流与协议栈

下面这张图展示了从 sensor 像素输出到 MIPI 物理层传输的完整流程。

MIPI CSI-2 协议栈与数据流 MIPI CSI-2 协议栈与数据流 应用层 像素数据:RAW10 / RAW12 / YUV422 / RGB888 协议层 打包成短包/长包,添加包头(ECC) + 包尾(CRC) 链路层 帧同步、行同步、虚拟通道复用、错误检测 物理层 D-PHY(差分对)或 C-PHY(三线组)电气传输 接收端(ISP / SoC) 关键点 • 短包:帧同步 • 长包:像素数据 • ECC 纠 1 检 2 • CRC 校验载荷

4.7 调试与常见问题

最后,分享几个我在项目中遇到的 MIPI 调试经验:

  • 信号完整性:用示波器看 D-PHY 的眼图。如果眼图张开度小于 70%,大概率会有误码。我曾经在 2.5Gbps 速率下,眼图只有 50%,后来调整了驱动强度才改善。
  • LP 模式切换:从 LP 切到 HS 时,需要一段 LP->HS 切换序列。如果序列时序不对,接收端会丢失第一个包。我建议在 sensor 初始化时,先发一个空帧,让链路稳定下来。
  • CRC 错误:如果 ISP 报 CRC 错误,先别急着怀疑硬件。检查一下 sensor 的时钟频率是否准确,PLL 配置是否正确。我遇到过 sensor 的 PLL 分频比配错,导致输出速率比预期高了 10%,CRC 错误率飙升。
  • 虚拟通道冲突:多路摄像头共用 CSI-2 时,确保每个 sensor 的 VC 号不重复。否则 ISP 会把两路数据混在一起,画面直接花掉。

总结一下:MIPI CSI-2 是摄像头和 ISP 之间的桥梁。物理层选 D-PHY 还是 C-PHY,看带宽和成本。协议层要理解包结构、数据类型和虚拟通道。调试时,眼图、CRC、切换序列是三大关注点。把这些搞透了,sensor 驱动这块基本就稳了。