4. MIPI 协议层调试:长包/短包解析、ECC 校验、CRC 错误、虚拟通道配置
MIPI CSI-2 协议层,说白了就是摄像头和 SoC 之间约定的「语言规则」。物理层把 0 和 1 传过来了,但怎么知道这些比特流代表什么?是帧开始、一行数据、还是配置命令?这就得靠协议层来解析。
我刚开始调 MIPI 的时候,总觉得只要物理层 Lock 住、 Lane 对齐了,数据就应该没问题。结果有一次,图像出来全是花屏,折腾了两天才发现是虚拟通道配错了。嗯,从那以后我再也不敢轻视协议层的调试了。
4.1 长包与短包:MIPI 的两种「信封」
MIPI CSI-2 协议定义了两种基本的数据单元:短包和长包。你可以把短包想象成一个「信封的封面」,长包就是「信封里的内容」。
| 类型 | 长度 | 内容 | 典型用途 |
|---|---|---|---|
| 短包 | 固定 4 字节 | 数据标识符 (DI) + 16 位数据 + ECC | 帧开始 (FS)、帧结束 (FE)、行开始 (LS)、行结束 (LE) |
| 长包 | 可变长度 | 包头 (4B) + 有效载荷 + 包尾 (2B CRC) | 像素数据、嵌入式数据 |
短包解析要点:
- 短包只有 32 个比特,在调试时最容易抓取分析。
- 数据标识符 (DI) 的高 2 位是虚拟通道号,低 6 位是数据类型。
- 16 位数据字段:对于帧开始/结束包,这里存放的是帧号或行号。
长包解析要点:
- 包头包含:DI (1B) + 字计数 WC (2B) + ECC (1B)。
- 字计数 WC 告诉接收端这个长包的有效载荷有多少字节。
- 包尾是 2 字节的 CRC 校验值,覆盖从包头之后到 CRC 之前的所有数据。
4.2 ECC 校验:单比特纠错的「守护神」
ECC(Error Correction Code)是 MIPI 协议层的第一道防线。它只保护短包和长包包头的 4 个字节,能纠正 1 个比特错误,检测 2 个比特错误。
为什么会需要 ECC?因为 MIPI 是高速串行链路,偶尔会有比特翻转。如果包头的字计数被翻转了一位,接收端可能把 1000 字节的数据包当成 2000 字节来读,后果就是整帧图像错位。
ECC 调试步骤:
- 读取接收端 ECC 状态寄存器,查看是否有 ECC 错误计数。
- 如果 ECC 错误计数持续增长,说明链路质量有问题。
- 检查 ECC 是否被正确使能。有些 SoC 默认关闭 ECC 校验。
- 用示波器看差分信号的眼图,确认信号质量。
4.3 CRC 错误:图像花屏的「元凶」
CRC(Cyclic Redundancy Check)是长包有效载荷的完整性校验。接收端收到长包后,会重新计算 CRC 并与包尾的 CRC 值比对。如果不一致,就说明传输过程中数据发生了错误。
CRC 错误的常见原因:
- 物理层信号质量差(抖动、幅度不足)。
- 时钟频率偏差过大(超过 ±1000 ppm)。
- Lane 之间的 skew 超出接收端容忍范围。
- SoC 的接收端 FIFO 溢出(带宽不足)。
调试流程:
- 先确认 CRC 错误是偶发还是持续。偶发错误通常来自物理层干扰。
- 持续错误:检查时钟频率和 Lane 速率配置是否匹配。
- 查看接收端 FIFO 状态,确认是否有溢出。
- 用示波器测量所有 Lane 的 skew,确保在 0.5 UI 以内。
我的经验: 有一次调试 4K@60fps 的摄像头,图像每隔几秒就闪一下。查了三天,最后发现是 SoC 的 DMA 带宽不够,导致接收端 FIFO 溢出,CRC 错误率高达 5%。把 DMA 优先级调高后,问题解决。
4.4 虚拟通道配置:多路复用的「门牌号」
虚拟通道(Virtual Channel, VC)是 MIPI CSI-2 实现多路复用的关键机制。一条 MIPI 链路上最多可以传输 4 个虚拟通道的数据,每个通道用 VC ID(0-3)来区分。
虚拟通道的典型应用场景:
- 双摄像头共用一条 MIPI 总线(主摄 + 广角)。
- 摄像头同时输出 RAW 图像和 YUV 图像。
- 摄像头输出图像数据 + 传感器元数据(如陀螺仪数据)。
配置要点:
| 配置项 | 发送端(摄像头) | 接收端(SoC) |
|---|---|---|
| VC ID | 在传感器寄存器中设置 | 在 CSI-2 接收控制器中设置 |
| 数据类型 | RAW10 / RAW12 / YUV422 等 | 与发送端一致 |
| 数据格式 | 像素顺序、打包方式 | 解包方式匹配 |
4.5 协议层调试的「三板斧」
总结一下,协议层调试我一般按这个顺序来:
- 看短包: 确认帧开始/结束信号是否正常,帧号是否连续。
- 看 ECC: 检查包头是否有错误,确认链路基本可靠。
- 看 CRC: 检查有效载荷是否有错误,确认数据完整性。
- 看 VC: 确认虚拟通道配置是否正确,数据是否路由到正确的处理模块。
下面这张图展示了 MIPI 协议层调试的核心逻辑:
说白了,协议层调试就是一层一层往上查。先确认短包结构正确,再查 ECC 有没有纠错,然后看 CRC 有没有报错,最后确认虚拟通道把数据送到了正确的地方。每一步都有对应的寄存器可以读,关键是知道读什么、怎么读。