3. MIPI协议层(CSI-2):分层结构、长包与短包、数据类型与虚拟通道

各位同学,今天我们来聊聊MIPI CSI-2的协议层。说实话,很多工程师做摄像头驱动调了半年,对物理层(D-PHY)的时序倒背如流,但一提到协议层就含糊其辞。我个人觉得,协议层才是真正决定你能否把图像数据“看懂”的关键。你想想看,物理层只是把0和1传过来,但怎么解析成像素、怎么区分不同摄像头的数据,全靠协议层说了算。

3.1 CSI-2的分层结构

CSI-2协议层,说白了就是一套“数据打包规范”。它从上到下分为三层:

  • 应用层:处理像素数据,比如RGB、YUV、RAW等格式的转换。
  • 协议层:负责数据打包、解包,包括长包和短包的生成与解析。
  • 物理层:D-PHY或C-PHY,负责电气信号的传输。

嗯,这里要注意,我们平时说的“MIPI调试”,90%的时间都在和协议层打交道。我在项目中遇到过好几次,明明物理层眼图测试都过了,但图像就是花屏。最后发现是协议层的包长度计算错了,导致数据错位。所以,别小看这层。

核心要点:协议层是连接物理层和应用层的桥梁。它不关心电压高低,只关心数据怎么组织。

应用层(Application Layer) 像素格式转换、图像处理 协议层(Protocol Layer) 长包/短包、数据类型、虚拟通道 物理层(Physical Layer) D-PHY / C-PHY 电气信号 数据流向:应用层 → 协议层 → 物理层

3.2 长包与短包

MIPI CSI-2的数据传输,分为两种包:长包和短包。我刚开始学的时候,总觉得这名字起得太随意了。但用久了你会发现,这名字其实很贴切。

3.2.1 短包(Short Packet)

短包只有4个字节,固定长度。它用来传输控制信息,比如帧同步、行同步、数据类型标识等。短包的结构很简单:

  • 数据标识符(DI):1字节,包含虚拟通道号和数据类型。
  • 数据字段:2字节,具体含义由数据类型决定(比如帧号、行数等)。
  • ECC:1字节,纠错码,保护前3个字节。

短包最常见的用途就是帧起始(FS)和帧结束(FE)。我记得有一次调试一个800万像素的摄像头,图像总是少了几行。抓包一看,发现帧结束短包里的行数计数不对。嗯,这种问题用示波器抓D-PHY信号根本看不出来,必须用协议分析仪。

小技巧:调试时优先检查短包。如果短包里的ECC报错,那后面的长包数据大概率也是错的。我曾经因为这个习惯,省下了整整两天的排查时间。

3.2.2 长包(Long Packet)

长包用来传输真正的图像数据。它的长度是可变的,结构如下:

长包结构:
+--------+--------+--------+--------+--------+--------+--------+--------+
|  DI    |  WC (低字节) |  WC (高字节) |  ECC   |  数据负载 (WC字节)  |  CRC  |
+--------+--------+--------+--------+--------+--------+--------+--------+
|  1字节 |     2字节     |  1字节  |   WC字节(可变)  |  2字节  |
+--------+--------+--------+--------+--------+--------+--------+--------+
  • DI:数据标识符,同短包。
  • WC:字计数(Word Count),表示数据负载的字节数。
  • ECC:纠错码,保护DI和WC。
  • 数据负载:实际的像素数据。
  • CRC:循环冗余校验,保护数据负载。

你想想看,为什么要有WC?因为图像分辨率不同,每行的数据量也不同。WC告诉接收端“这一包有多少数据”,这样接收端才知道什么时候该收下一个包。我在项目中遇到过一种情况:摄像头输出的分辨率是1920x1080,但WC算出来是1922。结果每行多出2个字节,图像就斜了。排查了半天,发现是驱动里对齐设置错了。

避坑指南:我曾经因为WC计算错误,导致图像出现“锯齿状”偏移。检查WC时,一定要确认它是否包含了填充字节(padding)。有些传感器会在行尾自动补0对齐,WC里是包含这些填充字节的。

3.3 数据类型(Data Type)

数据类型(DT)是DI字段中的高6位,用来告诉接收端“这包数据是什么格式”。常见的DT值如下:

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

我建议你把这张表存下来。调试时最常遇到的情况就是:摄像头输出的是RAW10,但接收端配置成了RAW8。结果图像颜色完全不对,像鬼片一样。说白了,就是数据类型没对上。

经验之谈:配置摄像头时,先确认传感器手册里支持哪些DT值。有些传感器虽然标称支持RAW10,但实际输出时DT值可能写的是0x2B还是0x2C,一定要看寄存器配置。

3.4 虚拟通道(Virtual Channel)

虚拟通道(VC)是DI字段中的低2位。它有什么用呢?简单说,就是让一条MIPI物理链路上可以同时传输多路摄像头的数据。

举个例子:你做一个双摄手机,主摄和广角共用一条MIPI总线。主摄的数据包VC=0,广角的数据包VC=1。接收端根据VC值,把数据分别送到不同的处理模块。这样就不用为每个摄像头单独拉一条MIPI线了,省引脚、省PCB面积。

虚拟通道的取值范围是0~3,共4个通道。DI字段的结构如下:

DI(1字节):
+----+----+----+----+----+----+----+----+
| DT6 | DT5 | DT4 | DT3 | DT2 | DT1 | VC1 | VC0 |
+----+----+----+----+----+----+----+----+
|       数据类型(6位)       | 虚拟通道(2位) |

我在项目中遇到过一个问题:两个摄像头都配置了VC=0,结果数据混在一起,图像像“叠影”一样。排查了半天,发现是驱动初始化时忘了给第二个摄像头设置VC值。嗯,这种低级错误,犯过一次就再也不会忘了。

实用建议:多摄像头项目中,建议把主摄固定为VC=0,副摄固定为VC=1。这样调试时,看到VC=0的数据就知道是主摄的,逻辑清晰。我曾经见过一个项目,VC分配得乱七八糟,最后查问题查得想摔示波器。

3.5 总结

好了,这一章的内容就这些。总结一下:

  • CSI-2协议层分为应用层、协议层、物理层,各司其职。
  • 短包传控制信息,长包传图像数据。短包固定4字节,长包可变长度。
  • 数据类型(DT)告诉接收端数据格式,配置错了图像就花。
  • 虚拟通道(VC)让一条MIPI总线可以传多路数据,多摄像头项目必备。

说实话,协议层的东西看起来琐碎,但每一个细节都可能成为你调试路上的“坑”。我建议你找个开发板,实际抓一包数据,对照着协议手册看一遍。纸上得来终觉浅,绝知此事要躬行。

核心一句话:MIPI协议层就是一套“数据打包规则”。你理解了长包短包、DT和VC,就等于拿到了读懂MIPI数据的钥匙。

可可精品资料库