第三章 CSI-2协议层:长包与短包、DT、VC与帧同步

各位做图像调试的同行,今天我们来聊聊MIPI CSI-2协议层里最核心的几个概念。说实话,我刚入行那会儿,对着示波器看MIPI波形,满眼都是0和1,根本分不清哪是哪。后来踩了不少坑,才慢慢摸清楚这些包结构到底在说什么。

CSI-2协议层,说白了就是定义摄像头怎么把图像数据打包发给主控。它分两种包:短包和长包。短包管控制,长包管数据。你想想看,没有短包,主控都不知道一帧图像从哪开始、到哪结束,那画面不就乱套了?

3.1 短包格式:控制信令的骨架

短包只有4个字节,非常精简。它的结构是这样的:

字节位置 内容 说明
Byte 0 数据标识符(DI) 高4位=VC,低4位=DT
Byte 1 数据字节1 短包数据(低8位)
Byte 2 数据字节2 短包数据(高8位)
Byte 3 ECC 纠错码,可纠正1bit错误

短包不传图像数据,它只传控制信息。比如帧起始(FS)、帧结束(FE)、行起始(LS)、行结束(LE)。这些包就像交通信号灯,告诉接收端什么时候开始收数据、什么时候该停了。

关键点:短包的数据字段只有16位(2个字节)。对于帧号这种需要更大数值的场景,16位可能不够用。我遇到过一款sensor,帧号超过65535后直接回绕,导致上位机解析出错。后来我们在驱动层做了帧号连续性检测,才把这个坑填上。

3.2 长包格式:图像数据的载体

长包才是真正装图像数据的。它的结构比短包复杂得多:

+----------------+----------------+----------------+----------------+
|  包首(PH)     |   数据负载      |   包尾(PF)    |
| 4字节           | 可变长度        | 2字节           |
+----------------+----------------+----------------+----------------+
| DI | WC | ECC   | 像素数据...     | 校验和(CRC)   |
+----------------+----------------+----------------+----------------+

包首(Packet Header)包含:

  • DI(Data Identifier):1字节,包含VC和DT
  • WC(Word Count):2字节,表示数据负载的字节数
  • ECC:1字节,对包首做纠错

数据负载就是实际的像素数据。RAW8、RAW10、RAW12,都塞在这里。包尾是2字节的CRC校验,用来保证数据完整性。

我的经验:调试时如果发现图像有随机花屏,先别急着怀疑sensor。用示波器抓一下MIPI波形,看看CRC是不是经常报错。我曾经花了两天查一个花屏问题,最后发现是FPC排线太长,信号质量下降导致CRC频繁出错。换短排线就好了。

3.3 数据类型(DT)与虚拟通道(VC)

这两个字段都在DI字节里。高4位是VC,低4位是DT。

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

DT值(Hex) 数据类型 说明
0x2A RAW8 8位RAW数据
0x2B RAW10 10位RAW数据
0x2C RAW12 12位RAW数据
0x1E YUV420 8bit YUV格式
0x00 帧起始包(FS) 短包
0x01 帧结束包(FE) 短包

虚拟通道(VC)允许在同一条MIPI链路上传输多路数据。比如一个双目摄像头模组,左眼用VC0,右眼用VC1,共用同一组差分线。接收端根据VC值把数据分到不同的处理通道。

注意:VC不是随便设的。我曾经遇到一个项目,左右眼VC设反了,结果图像左右颠倒,排查了半天才发现是VC配置问题。建议在sensor初始化时就把VC和物理通道的对应关系写死在驱动里,别让上层应用乱改。

3.4 帧起始(FS)与帧结束(FE)包

这两个是短包,用来标记一帧图像的边界。FS包在帧数据的最前面,FE包在最后面。接收端收到FS就知道要开始收数据了,收到FE就知道这一帧结束了。

FS和FE包的数据字段里,通常会携带帧号(Frame Number)。帧号从0开始,每帧加1。接收端可以用帧号检测是否有丢帧。

避坑指南:有些sensor的FS包和FE包里的帧号不一致,或者帧号不连续。我遇到过一款sensor,在切换分辨率时帧号会跳变。如果你在驱动里做了帧号连续性检查,记得在分辨率切换时重置检查逻辑,否则会误报丢帧。

3.5 行起始(LS)与行结束(LE)包

LS和LE也是短包,用来标记每一行的边界。不过,不是所有sensor都会发LS/LE包。有些sensor只在帧级别做同步,行级别靠数据负载的连续传输来区分。

LS包的数据字段里,通常会携带行号。接收端可以用行号来检测是否有丢行。LE包则标记该行数据结束。

我个人习惯,在调试初期先看FS/FE包是否正常,再看LS/LE包。如果FS/FE都对了,但图像还是错位,那大概率是LS/LE的问题。

3.6 知识结构图:CSI-2协议层核心逻辑

下面这张图,把短包、长包、VC、DT、帧同步、行同步的关系串起来了。建议你保存下来,调试时对照着看。

CSI-2协议层核心逻辑 短包(4字节) 长包(可变长度) FS(帧起始) FE(帧结束) LS(行起始) LE(行结束) 包首(PH) 数据负载 包尾(PF) DI WC ECC VC(4bit) DT(4bit) 关键流程: 1. 接收端先检测FS短包,获取帧号,准备接收新帧 2. 然后接收一行行的长包(数据负载),每行可能有LS/LE短包标记 3. 收到FE短包,表示当前帧结束,校验帧号是否连续 4. 如果DT不匹配或CRC错误,接收端会丢弃该包或整帧

3.7 调试中的常见问题

最后,我总结几个实际调试中容易踩的坑:

  • DT配置错误:sensor输出RAW10,但主控配置成RAW8,图像颜色会完全错乱。用示波器抓包,看DI字段的DT值对不对得上。
  • VC冲突:多路摄像头共用MIPI总线时,VC必须唯一。我见过两个sensor都配成VC0,结果数据混在一起,图像像鬼影一样。
  • 帧号不连续:如果sensor在特定场景下丢帧,接收端会检测到帧号跳变。这时候要查sensor的帧同步信号是否稳定,或者MIPI时钟是否有抖动。
  • LS/LE丢失:有些sensor在低分辨率模式下不发LS/LE包,但主控驱动默认等待这些包,导致超时。建议驱动兼容两种模式。

我的调试习惯:拿到一块新sensor,我会先写一个简单的MIPI抓包工具,把FS/FE、LS/LE、DT、VC、帧号全部打印出来。确认这些基础信息都对,再去看图像内容。这一步能省掉后面80%的排查时间。