4、MIPI CSI-2 协议层:长包与短包格式、数据类型与虚拟通道、帧同步与行同步机制

好,我们进入 MIPI CSI-2 协议层。说实话,这部分是驱动开发中最绕、也最容易出 bug 的地方。很多工程师调不通 sensor,最后发现不是硬件问题,而是协议层的包格式没搞对。

MIPI CSI-2 的协议层,说白了就是定义数据怎么打包、怎么传输、怎么解析。它把数据分成两种包:长包和短包。这两种包配合起来,才能完成一帧图像的完整传输。

4.1 长包与短包:协议层的两种基本单元

先看短包。短包只有 32 位数据,结构非常简单:

短包格式(32位):
+--------+--------+--------+--------+
|  Data ID  |  Word Count / ECC  |  ECC  |
+--------+--------+--------+--------+
- Data ID(8位):虚拟通道 + 数据类型
- Word Count / 数据(16位):短包的数据字段
- ECC(8位):纠错码

短包不传图像数据,它只传控制信息。比如帧开始、帧结束、行开始、行结束。我刚开始做 sensor 驱动时,以为短包不重要,结果图像一直花屏。查了两天,发现是帧同步的短包时序不对。

长包才是真正传图像数据的。它的结构稍微复杂一点:

长包格式:
+--------+--------+--------+--------+------------------+--------+
|  Data ID  |  Word Count  |  ECC  |  图像数据(可变长)  |  CRC  |
+--------+--------+--------+--------+------------------+--------+
- Data ID(8位):虚拟通道 + 数据类型
- Word Count(16位):数据负载的字节数
- ECC(8位):包头纠错码
- 数据负载:实际图像数据
- CRC(16位):数据校验码

长包的核心是 Word Count 字段。它告诉接收端这包数据有多长。接收端根据这个值来切分数据流。嗯,这里要注意:Word Count 的单位是字节,不是像素。

关键点:长包和短包的区别不在于数据量,而在于用途。短包是控制信令,长包是数据传输。两者通过 Data ID 中的数据类型字段区分。

4.2 数据类型与虚拟通道:如何区分不同的数据流

Data ID 是 8 位字段,它包含两部分:

  • 高 2 位:虚拟通道标识(Virtual Channel, VC)
  • 低 6 位:数据类型标识(Data Type, DT)

虚拟通道有什么用?你想想看,一个 MIPI 接口可以同时传多路数据。比如双摄像头模组,或者摄像头同时输出 RAW 和 YUV 两路数据。虚拟通道就是用来区分这些数据流的。

数据类型定义了负载的格式。我整理了一份常用的数据类型表:

数据类型 值(十六进制) 说明
RGB888 0x1E 24位 RGB 格式
RAW8 0x2A 8位 RAW 数据
RAW10 0x2B 10位 RAW 数据
RAW12 0x2C 12位 RAW 数据
YUV420 8bit 0x1E YUV 420 格式
帧开始(FS) 0x00 短包,帧同步开始
帧结束(FE) 0x01 短包,帧同步结束
行开始(LS) 0x02 短包,行同步开始
行结束(LE) 0x03 短包,行同步结束

个人经验:配置 sensor 时,一定要确认 sensor 输出的数据类型和驱动中配置的一致。我曾经遇到一个 case,sensor 输出 RAW10,但驱动配成了 RAW8,结果图像全是条纹。查了半天才发现是数据类型不匹配。

4.3 帧同步与行同步机制:图像传输的骨架

帧同步和行同步,是 MIPI CSI-2 协议中最核心的时序机制。没有它们,接收端根本不知道哪里是图像的开始和结束。

帧同步的流程是这样的:

  1. 发送端先发一个 帧开始(FS) 短包
  2. 然后逐行发送图像数据(每行是一个长包)
  3. 所有行发送完毕后,发一个 帧结束(FE) 短包

行同步的流程类似:

  1. 每行开始前,发一个 行开始(LS) 短包
  2. 然后发送该行的图像数据(长包)
  3. 行数据发完后,发一个 行结束(LE) 短包

我画了一张图,帮你理解这个时序关系:

MIPI CSI-2 帧同步与行同步时序 FS 帧开始 LS 行1 数据(长包) LE LS 行2 数据 ... LS 最后一行 数据(长包) LE FE 帧结束 时序说明: 1. 每帧以 FS(帧开始)短包开始,以 FE(帧结束)短包结束 2. 每行以 LS(行开始)短包开始,以 LE(行结束)短包结束 3. 行数据使用长包传输,包含 Word Count、ECC、数据和 CRC 4. 短包和长包通过 Data ID 中的数据类型字段区分

为什么需要行同步?因为接收端需要知道每行数据的边界。如果没有行同步,接收端无法判断数据流中哪里是一行的结束、下一行的开始。特别是在传输 RAW 数据时,每行的像素数可能不是固定的。

4.4 协议层的实际配置要点

在实际驱动开发中,协议层的配置主要集中在 sensor 的寄存器设置上。我总结几个关键点:

  • 数据类型配置:sensor 的输出格式必须和 CSI-2 接收端匹配。比如 sensor 输出 RAW10,接收端也要配成 RAW10。
  • 虚拟通道配置:如果使用多路数据,每路数据要分配不同的虚拟通道 ID。
  • 帧同步使能:确认 sensor 是否开启了帧同步和行同步的短包输出。有些 sensor 默认不开启。
  • Word Count 验证:接收端收到长包后,会检查 Word Count 是否和实际数据长度一致。不一致会报错。

避坑指南:我曾经遇到一个 case,sensor 输出的帧率一直不对。查了很久,发现是 sensor 的帧同步配置中,帧开始和帧结束的短包之间插入了额外的空白包。接收端把这些空白包当成了有效数据,导致帧计数错误。解决方案是在 sensor 的寄存器中关闭空白包输出。

4.5 协议层与物理层的配合

协议层和物理层是紧密配合的。物理层负责把协议层的包转换成差分信号,通过 D-PHY 或 C-PHY 传输。协议层不关心物理层用什么接口,它只定义包的格式和时序。

但有一点要注意:协议层的包长度不能超过物理层的传输能力。比如 D-PHY 的每个 lane 有最大速率限制,如果长包的数据量太大,会导致传输时间过长,影响帧率。