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 协议层的事。它定义了一套分层结构:
- 应用层:像素数据,比如 raw10、raw12、YUV422。
- 协议层:把像素打包成包(Packet),加上包头包尾。
- 链路层:处理 CRC、ECC、帧同步。
- 物理层: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 物理层传输的完整流程。
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 驱动这块基本就稳了。