帧结构与数据包格式:长包与短包、帧头帧尾、Escape模式
说到MIPI CSI-2的帧结构,我个人的经验是——如果你不理解长包和短包的区别,那调试起来基本就是靠猜。网上很多教程把它讲得玄乎,其实说白了就一句话:短包管控制,长包扛数据。
咱们今天把这块彻底捋清楚。我会结合我遇到过的几个坑,帮你把帧头帧尾、Escape模式这些东西都消化掉。
什么是短包?什么是长包?
CSI-2链路上跑的有两种包:短包(Short Packet, SP) 和 长包(Long Packet, LP)。它们有完全不同的用途。
| 特性 | 短包 | 长包 |
|---|---|---|
| 长度 | 固定 4 字节(32 bit) | 可变长度(4~65535+CRC字节) |
| 内容 | 只含数据标识符(DI)+ 字数据或虚拟通道/数据类型 | DI + 字计数 + 实际像素数据 + ECC + CRC |
| 净荷 | 无净荷,仅控制信息 | 有净荷,存放图像数据或元数据 |
| 常用场景 | 帧开始(FS)、帧结束(FE)、行开始(LS)、行结束(LE) | 传输实际像素行数据,或嵌入式数据块 |
举个实际例子:我调试一个1080p sensor时,发现画面总是上下颠倒。查了半天,发现是短包里的帧开始/帧结束顺序发反了。嗯,这里要注意——短包虽然小,但它决定了整个帧的边界。
帧头与帧尾:FS 和 FE
每帧数据的边界由两个短包划定:
- Frame Start (FS):数据类型(DT)= 0x00(传统模式)或 0x01(带虚拟通道)。
- Frame End (FE):DT = 0x01(传统模式)或 0x11(带虚拟通道)。
你想想看,如果没有FE,接收端就一直等数据,直到缓冲溢出或者超时。我曾经遇到一个项目,sensor输出FE丢失,结果FPGA那边一直卡在行缓冲区不释放,整个系统死锁了。所以FS和FE必须成对出现,这是CSI-2协议的基本契约。
行起始与行结束:LS 和 LE
对于逐行传输的sensor,每一行也由短包划定边界:
- Line Start (LS):DT = 0x02
- Line End (LE):DT = 0x03
不过有些sensor为了省带宽,会忽略LS/LE,只用FS/FE配合长包里的字计数来识别行边界。这取决于你的数据传输模式配置。
长包格式详解
长包是真正搬运图像数据的主力。它的结构分为三段:
- 包首(Packet Header, PH):固定4字节,包含数据标识符(DI,含虚拟通道和数据类型)+ 16位字计数 + ECC。
- 包数据(Packet Data):长度由字计数决定,单位是字节(或word,取决于配置)。
- 包尾(Packet Footer, PF):固定2字节CRC-16校验。
下面是典型的长包字节序(以CSI-2传统模式为例):
Byte 0: Data Identifier (VC[1:0] + DT[5:0])
Byte 1: Word Count Low Byte
Byte 2: Word Count High Byte
Byte 3: ECC (6-bit EC + 2-bit header correction)
Byte 4 .. (Word Count)*: Raw pixel data (e.g., raw10 packed as 5 bytes per 4 pixels)
Byte (4+WordCount) .. (4+WordCount+1): CRC-16 (optional, depends on mode)
注意:字计数的单位在不同PHY配置下有差异,一般是字节数。
核心要点:ECC保护的是包首本身,CRC保护的是包尾。我曾经试过故意破坏包首的一个bit,接收端ECC能自动纠正1-bit错误,但2-bit错误直接丢包。这个丢包行为由接收端实现决定,有些芯片会丢弃整包,有些会报错中断。调试时务必确认你的SoC的CSI-2控制器是怎么处理ECC错误的。
Escape模式:不是每根线都跑CSI
Escape模式是MIPI D-PHY物理层提供的一种超低功耗数据传输模式,用于传输控制信息(如触发信号、状态查询、或低速数据传输)。它在数据传输通道(不是时钟通道)上通过特定的LP(低功耗)状态序列来进入。
其工作原理简单说:
- 物理层从HS(高速)或LP(低功耗)空闲状态出发,发送Escape Entry序列(LP-11 → LP-10 → LP-00 → LP-01 → LP-00)。
- 随后可以传输8位数据(或更长的Escape命令)。
- 退出时发送Escape Exit序列(LP-00 → LP-01 → LP-00 → LP-11)。
Escape模式主要用在命令集传输(如CCP2/E)或带外控制(如触发闪光灯、更改sensor增益而不中断视频流)。我以前在安防摄像机方案里,用Escape模式传送一帧的全局曝光时间配置,省掉了一根额外的I2C线。嗯,这个用法挺妙的。
帧结构与数据包关系总图
下面这张图是我整理的典型帧传输序列,里面标出了短包、长包和Escape模式的交互位置。你先看看整体流程,再细究每个节点。
实际调试中你需要注意的细节
我再说几个实战中碰到的高频问题:
- 长包字计数错误:如果字计数比实际像素数据少,接收端会认为包提前结束,CRC校验算不对。如果多,接收端会卡在等待数据,直到超时。我之前用FPGA做接收端,每次遇到超时就报错复位整个链路,后来改成按CRC结果决定是否丢弃该行,稳定性好很多。
- 短包的ECC:短包只有4字节,ECC占6位,可纠正1位错误、检测2位错误。我在一个项目中抓到过ECC不断报错的情况,原因是PCB走线过长导致信号反射,在LP状态下产生了毛刺。嗯,不要忽视短包的ECC状态寄存器,它往往是PHY层问题的先兆。
- Escape模式的退出条件:要确保Escape Exit序列完成后DLP状态回到LP-11,否则下一个HS请求可能无法开始。我记得有个项目因为GPIO驱动配置错误,导致LP-11保持时间不够,每次Escape退出后链路就进入假死状态。
最后分享一个我个人的习惯:在调试初期,我会强制把sensor配置成「每个长包都带CRC」的模式,即使有些数据手册说可选。因为CRC能告诉我数据完整性是否OK。等链路稳定了,再根据功耗要求决定是否关闭CRC。千万别一上来就图省电把CRC关掉,那时候你连问题是sensor还是PHY都分不清。