4、CSI-2 协议层:长包与短包格式、数据类型定义、虚拟通道机制

好,咱们今天聊聊 CSI-2 的协议层。说实话,很多工程师做 MIPI 调试,硬件上拉个波形没问题,但一遇到图像花屏、数据错位,就抓瞎了。为什么?因为没搞懂协议层在干什么。

协议层,说白了就是摄像头和处理器之间约定好的“说话方式”。你发一串 0 和 1,对方得知道哪是头、哪是尾、中间是什么数据。CSI-2 协议层就干这个事。

4.1 长包与短包:两种基本“信封”

CSI-2 的数据传输,分两种包:长包(Long Packet)和短包(Short Packet)。我习惯把它们比作寄快递:

  • 短包:就像一张明信片。内容少,就写个“帧开始”、“帧结束”之类的控制信息。32 位数据,一次搞定。
  • 长包:就像一个大箱子。里面装的是真正的图像数据(像素)。箱子外面贴着快递单(包头),里面是货物(有效数据),最后还有个签名(校验)。

咱们先看短包格式。它很简单:

短包格式(32位):
[Data ID (8位)] [Word Count (16位)] [ECC (8位)]

等等,你可能要问:短包只有 32 位,那 Word Count 字段干嘛用的?嗯,这里有个细节——短包的 Word Count 字段其实被用来存放“短包数据内容”了,比如帧号、行号这些。ECC 是纠错码,保证这 32 位别传错。

长包就复杂一些:

长包格式:
[包头: Data ID (8位) + Word Count (16位) + ECC (8位)]
[有效数据: Word Count 字节]
[包尾: 16位 CRC 校验]

我在项目中遇到过一个问题:某款 sensor 输出的长包,Word Count 和实际数据长度对不上。结果图像下半部分全是乱的。后来发现是 sensor 的寄存器配置错了,把行长度设成了奇数。记住,长包的有效数据必须是 32 位对齐的,不够的要补 0。

注意:长包的 CRC 校验只保护有效数据,不保护包头。包头的错误靠 ECC 纠错。所以如果你看到 CRC 报错,问题出在数据内容上;如果 ECC 报错,那多半是控制信号(比如 HSync)的时序有问题。

4.2 数据类型(Data Type):给数据贴个标签

数据类型,就是告诉接收方:“我这包数据是什么格式”。它放在每个包的 Data ID 字段里,占高 6 位(低 2 位是虚拟通道号)。

常见的 Data Type 我列个表,你调试时肯定用得上:

Data Type (十六进制) 含义 说明
0x00-0x07 保留 别用,用了可能出奇怪问题
0x08-0x0F 短包(帧/行同步) 0x00: 帧开始, 0x01: 帧结束, 0x02: 行开始, 0x03: 行结束
0x10-0x17 通用短包 留给厂商自定义,我一般不用
0x18-0x1F 通用长包 同上,非标数据用
0x2A RAW8 8位原始Bayer数据,最常用
0x2B RAW10 10位原始数据,4个像素占5字节
0x2C RAW12 12位原始数据,2个像素占3字节
0x2D RAW14 14位,工业相机用得多
0x1E RGB888 24位RGB,调试时方便看
0x1C YUV420 8位 视频压缩常用

我个人习惯,调试初期先把 sensor 配成 RAW8 或 RGB565。为什么?因为数据量小,逻辑分析仪抓包容易看。等通路调通了,再换成 RAW10 或 RAW12 提高画质。

小技巧:如果你发现图像颜色不对,先检查 Data Type 是否匹配。我曾经花了两天查一个颜色偏绿的问题,最后发现 sensor 输出的是 RAW10,但 ISP 端配成了 RAW8——每个像素少读了 2 位,颜色能对才怪。

4.3 虚拟通道(Virtual Channel):一根线上跑多路数据

虚拟通道,是 CSI-2 里一个非常巧妙的设计。你想想看,现在的手机摄像头模组,经常是主摄、广角、景深好几个 sensor 同时工作。难道每个 sensor 都拉一组 MIPI 线到处理器?那板子得乱成什么样。

虚拟通道就是解决这个问题的。它允许最多 4 个不同的数据流,共用同一组 MIPI 物理通道(D-PHY 的 1 对时钟 + 1~4 对数据线)。每个数据流通过 Data ID 的低 2 位来区分,也就是 VC0 ~ VC3。

看个实际例子。假设你有个双摄模组:

  • 主摄(RAW10, 1920x1080)→ VC0
  • 景深(RAW8, 640x480)→ VC1

这两个 sensor 的数据会交替出现在同一条 MIPI 数据线上。接收端(处理器)根据 Data ID 里的 VC 号,把数据分别送到不同的处理模块。就像一条高速公路上,不同颜色的车走不同的车道。

我画个图帮你理解:

虚拟通道(Virtual Channel)工作原理 主摄 Sensor VC0, RAW10 景深 Sensor VC1, RAW8 MUX 打包 + 插入VC ID MIPI 数据线上的包序列 VC0 VC1 VC0 VC1 ← 时间 → 接收端(处理器) 根据 VC ID 分发到不同模块

看到没?VC0 和 VC1 的包是交错传输的。接收端拿到每个包,先看低 2 位是 00 还是 01,然后分别处理。这样一根 MIPI 线就相当于变成了 4 根虚拟的线。

关键点:虚拟通道的切换是在包级别完成的。也就是说,一个长包必须完整传输完,才能切换到另一个 VC 的包。你不能在一个长包中间切换 VC。这个在调试时要注意,如果发现数据交叉错乱,先检查是不是有 sensor 在包中间切了 VC。

4.4 避坑指南:协议层常见问题

最后,我分享几个实际项目中踩过的坑:

  • 短包丢失导致帧同步失败:我曾经遇到一个案子,图像偶尔会卡住不动。抓波形发现,sensor 输出的帧开始短包(0x00)偶尔会丢失。原因是 sensor 的电源纹波太大,导致内部逻辑偶尔复位。加了个电容就好了。
  • Data Type 不匹配:这个前面提过。调试时一定先用逻辑分析仪抓一下包,确认 Data Type 字段的值。别信 sensor 的 datasheet,有时候它写的是错的。
  • 虚拟通道冲突:如果你用多路 sensor,记得每个 sensor 的 VC 号要唯一。我见过两个 sensor 都配成 VC0 的,结果数据混在一起,图像像万花筒。
  • Word Count 越界:长包的 Word Count 字段是 16 位的,最大 65535 字节。如果你的行数据超过这个值,必须拆成多个长包。有些 sensor 不会自动拆分,需要你手动配寄存器。

嗯,协议层的东西就这些。说白了,就是搞清楚“谁在什么时候发了什么数据”。你只要把包格式、数据类型、虚拟通道这三个概念吃透了,CSI-2 的协议层就没什么能难住你的了。

我的调试习惯:每次拿到新 sensor,第一件事不是看图像,而是用逻辑分析仪抓一段 MIPI 数据,手动解析几个包。确认短包顺序正确、Data Type 对、VC 号无误。这一步花 10 分钟,能省后面 10 小时的 debug 时间。