第三章 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、帧同步、行同步的关系串起来了。建议你保存下来,调试时对照着看。
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%的排查时间。