CSI-2 协议分层架构:物理层、协议层、应用层
做 CSI-2 调试这些年,我见过不少工程师一上来就扎进眼图测量,或者死磕 D-PHY 电压摆幅。坦白说,要是没搞清楚协议的分层结构,你测出来的很多数据其实是“孤岛”——你看似在调物理层,但问题可能出在协议层或者应用层的逻辑上。所以我个人习惯,在接手一个新项目的第一步,先把 CSI-2 的三层架构在脑子里过一遍。
CSI-2 协议栈从下往上分为三层:物理层、协议层、应用层。每一层只管自己的事,层与层之间通过标准接口传递数据。这种分层设计的好处很明显——换物理层标准(比如 D-PHY 换成 C-PHY)时,协议层和应用层几乎不用改。你想想看,这给硬件和软件解耦带来了多大的灵活度。
核心要点:分层职责
- 物理层:负责原始比特流的传输,定义电气特性、时钟、差分信号。
- 协议层:负责数据打包、拆包、差错控制,保证数据能完整地从发送端交到接收端。
- 应用层:负责解析数据内容,也就是摄像头输出的像素数据怎么组织成一行一帧的图像。
下面这张图是我课前专门画的,把你最需要记住的关系画清楚了——层与层的边界在哪里,各管哪一段。
物理层:信号运输的“高速公路”
物理层说白了就是管线和信号的。CSI-2 的物理层现在主要有两套标准:D-PHY 和 C-PHY。D-PHY 用差分对,每个 lane 一对线(DP/DN),再加一根时钟线;C-PHY 更激进,用三线编码,单 lane 就能传更多数据。不过大部分手机和嵌入式平台目前还是 D-PHY 主流。
物理层最核心的两个状态是 LPS(Low-Power State) 和 HS(High-Speed State)。LPS 下信号电压低、电流小,用来传控制信息或空闲时省电;HS 下信号摆幅大、速度快,用来突突突地传像素数据。两者切换有严格的时序要求——从 LPS 进 HS 要经过一个“准备-同步”序列,出 HS 再切回 LPS 也有个“撤销”序列。嗯,这里要注意:切换时序的 SI/PI 问题,是我在项目中翻车最多的部分。
我的避坑经验: 曾经有一个项目,模组在低温下偶尔丢帧。我花了两周排查,最后发现是 D-PHY 的 HS 退回到 LPS 时的电压下降沿太慢,导致下一包数据误以为还在 HS 模式。解决方案很简单——调整 terminator 的使能时机。所以看物理层不能只看眼图,还得关注模式切换的上升/下降时间。
| 参数 | 典型值/范围 | 说明 |
|---|---|---|
| HS 差分电压 | 200~700 mV | 实测一般调在 350~450 mV |
| HS 共模电压 | 150~325 mV | 受 PCB 噪声影响大 |
| HS 数据速率 | 80 Mbps ~ 4.5 Gbps / lane | 取决于 D-PHY 版本 |
| LPS 电压 | 0~1.2 V(单端) | 一般低于 0.3V 视为 LP-00 |
| UI (Unit Interval) | 与速率相关 | 1 Gbps 时 UI = 1 ns |
协议层:负责打包拆包的“物流中心”
协议层做的事,你可以想象成一个快递分拣中心。应用层(也就是摄像头传感器)源源不断地产生“货物”(像素数据),协议层把它们分成一个个包裹(数据包),贴上标签(包头),加上校验码(ECC/CRC),再按顺序发出去。接收端再根据标签把包裹拆开,还原成原来的数据流。
CSI-2 协议层定义了两种包:短包和长包。短包只有 4 个字节的包头(甚至更少),用来传控制信息,比如帧开始/结束、行开始/结束。长包有完整的包头+数据负载+包尾,负载最多 65535 字节,用来传具体的像素数据。
我个人觉得协议层最重要的字段是 数据标识符(Data Identifier, DI),它由虚拟通道号 VC(2 bit)和数据类型 DT(6 bit)组成。VC 让你能在一条 MIPI 总线上同时传多路摄像头的数据——这个在双摄/多摄手机上太常用了。DT 告诉接收方这包数据到底是 RAW10 还是 YUV422,还是 JPEG 编码的。如果 DT 配错了,图像花屏就没跑。
记得有一次调试时图像总是偏色,我抓了协议层的包一看,发现传感器侧配置为 RAW10,但接收端 SOC 以为是 RAW12。对齐数据类型才搞定。你看,往往不是硬件问题,而是协议层配错了。
// 数据标识符 (DI) 结构示意
// 1 字节: [VC:2bit] [DT:6bit]
// 举例:
// 0x2E → VC=0, DT=0x2E (RAW10)
// 0x1E → VC=0, DT=0x1E (YUV422 8bit)
//
// 长包包头 (Packet Header, PH) 结构:
// 字节0: DI
// 字节1-2: 字计数 (Word Count, WC)
// 字节3: ECC (对前3字节的保护码)
//
// 长包包尾 (Packet Footer, PF):
// 字节0-1: CRC (对负载数据的校验)
注意: CRC 只在长包中可选,但 ECC 是必须的。ECC 能纠正 1 bit 错误并检测 2 bit 错误。协议层还有一个关键机制——在每帧数据结束后,物理层会进入 LPS,然后发送下一个帧开始包。如果一个帧开始包丢了,整帧数据都会被 discard。这就是为什么有时候你看到图像卡住不动了。
应用层:把像素数据拼成图像的“拼图师”
到了应用层,终于跟图像内容打交道了。应用层不关心信号抖动、也不关心包格式,它只看一件事:按什么顺序把收到的像素数据组织成一行一帧的图像。
CSI-2 应用层定义了多种像素格式,比如 RAW8、RAW10、RAW12、RGB888、YUV422 等。每种格式规定了每个像素占用多少 bit、在数据负载里怎么排列。比如 RAW10 每个像素用 10 bit 表示,但物理层是按 8 bit 对齐的,所以四个 RAW10 的像素会被打包成 5 个字节——这种打包规则在 MIPI 标准里写得很细,我建议第一次接触的人一定要看标准里的“Pixel Order”表格。
另外应用层还定义了帧结构:每帧图像由若干行组成,每行由若干像素组成。行之间用“行开始/行结束”短包隔开,帧之间用“帧开始/帧结束”隔开。如果接收端解析时发现帧开始包之后没有收到预期的像素总数,就会报错或丢帧。
三层协作:一张调试时的“分层检查清单”
当你遇到 CSI-2 通信问题时,我建议按这个顺序排查:
- 物理层:看眼图、测 HS 电压摆幅、量 LPS-HS 切换时间、检查时钟抖动。如果眼图闭合或者抖动过大,协议层和应用层再怎么调也没用。
- 协议层:用逻辑分析仪抓包,检查包头 ECC 是否报错、CRC 是否失败、VC 和 DT 是否匹配、帧开始/结束包是否丢失。
- 应用层:检查像素格式对齐、帧尺寸(行有效像素数、总行数)是否与 sensor 配置一致。
我曾经遇到一个怪毛病——图像每隔几帧有一条亮线。排查物理层眼图正常,协议层包也没丢。最后发现是接收端 SOC 把行的有效像素数配少了 2 个像素,导致下一行数据错位了 2 个像素,累积到一帧末尾就出现了一条亮线。这就是应用层的问题,跟物理层完全无关。
所以你看,理解分层不仅仅是应试。它让你在调试时知道“问题出在哪一层”,而不是盲目地焊电阻、动 Terminator。后面我会一步步展开每一层更细的调试方法,今天先把三层架构的边界和职责记牢了。