4. CSI/DSI接口驱动
MIPI CSI-2,说白了就是摄像头和处理器之间的“普通话”。没有它,Sensor 再牛,数据也传不到 ISP 那边。我早年做第一款手机摄像头驱动时,就被这个接口折腾得不轻——协议栈看着简单,真调起来全是坑。
这一章,咱们把 CSI-2 从协议到驱动,一层层剥开。重点放在 D-PHY 物理层怎么配、CSI 接收控制器怎么初始化、多 Lane 怎么对齐。嗯,都是实战里绕不开的硬骨头。
4.1 MIPI CSI-2 协议栈分层
CSI-2 协议分三层,我习惯这么记:物理层(D-PHY)管传输、协议层(UniPro/Long Packet)管组包、应用层(Pixel/Byte packing)管数据格式。你想想看,Sensor 采集的 RAW10 数据,得先打包成长包,再通过 D-PHY 的差分线发出去。SoC 端的 CSI 接收控制器,再一层层解包,最后喂给 ISP。
| 层级 | 职责 | 我踩过的坑 |
|---|---|---|
| 应用层 | 定义像素格式、数据类型(RAW8/10/12、YUV422、JPEG) | RAW10 的 packing 顺序搞反,图像直接花屏 |
| 协议层 | 长包/短包结构、ECC 校验、CRC 校验 | ECC 算错一个 bit,整帧丢包 |
| 物理层 | D-PHY 电气特性、Lane 状态机、高速/低功耗模式切换 | Termination 电阻没配好,信号眼图惨不忍睹 |
核心要点:CSI-2 的包结构里,短包(8字节)用于帧同步、行同步;长包(Header + Data + Footer)才是真正的图像数据。Header 里的 WC(Word Count)字段,决定了这一行有多少像素数据。我见过有人把 WC 配成 0,结果 ISP 一直等数据,系统直接卡死。
4.2 D-PHY 物理层配置
D-PHY 是 CSI-2 的“高速公路”。它用差分信号(Dp/Dn)传输,支持 HS(高速)和 LP(低功耗)两种模式。HS 模式跑数据,LP 模式传控制信号。配置 D-PHY,说白了就是调好这几样东西:
- 电压摆幅:HS 模式下,差分电压典型值 200mV(±25mV)。我调过一款 Sensor,电压摆幅偏小,导致 SoC 端误码率飙升。后来用示波器一看,眼图都闭合了。
- Termination 电阻:接收端必须使能 100Ω 差分终端电阻。这个电阻没开,信号反射能把数据全打乱。
- HS 时钟频率:决定了每 Lane 的数据速率。比如 1.5Gbps/Lane,4 Lane 就是 6Gbps。注意,时钟频率不能超过 SoC 的 CSI 控制器上限。
- LP 模式时序:LP-11、LP-01、LP-00 这些状态切换,必须满足 D-PHY 规范的最小时间。我遇到过 LP 退出时间太短,导致 HS 时钟锁不住。
我的习惯:初始化 D-PHY 时,先配好 Termination 和电压摆幅,再使能 HS 时钟。顺序反了,容易烧 PHY。另外,建议在驱动里加一个 D-PHY 状态读取接口,调试时能实时看 Lane 状态。
4.3 CSI 接收控制器驱动开发
CSI 接收控制器,是 SoC 端负责“收包”的硬件模块。它的驱动开发,核心就是配好 时序参数和 DMA 通道。我以某款主流 SoC 为例,说说初始化流程:
- 复位与时钟使能:先复位 CSI 控制器,再使能时钟。注意,有些 SoC 的 CSI 时钟和 ISP 时钟是绑定的,不能单独关。
- 配置 Lane 数:告诉控制器,Sensor 用了 1 Lane、2 Lane 还是 4 Lane。这个必须和 Sensor 端一致。
- 配置数据类型:比如 RAW10、YUV422。控制器会根据这个来解析包里的像素数据。
- 配置虚拟通道(VC):如果 Sensor 支持多路数据流(比如主路 RAW、辅路 YUV),就用 VC 区分。我做过一个项目,Sensor 同时输出 RAW 和 JPEG,VC 配错了,ISP 一直收到乱码。
- 配置 DMA:设置 DMA 的目的地址、行宽、帧大小。建议用双缓冲(ping-pong buffer),避免丢帧。
- 使能中断:帧开始、帧结束、错误中断。调试阶段,错误中断一定要开,能帮你快速定位问题。
// CSI 接收控制器初始化伪代码
void csi_rx_init(struct csi_device *csi) {
// 1. 复位
writel(CSI_SRST, csi->base + CSI_CTRL);
udelay(10);
writel(0, csi->base + CSI_CTRL);
// 2. 配置 Lane 数和数据类型
writel(CSI_LANE_NUM_4 | CSI_DT_RAW10, csi->base + CSI_CFG0);
// 3. 配置虚拟通道
writel(CSI_VC_ENABLE | CSI_VC_ID(0), csi->base + CSI_VC_CTRL);
// 4. 配置 DMA
writel(csi->dma_addr, csi->base + CSI_DMA_ADDR);
writel(csi->line_size, csi->base + CSI_DMA_STRIDE);
writel(csi->frame_height, csi->base + CSI_DMA_FRAME_SIZE);
// 5. 使能中断
writel(CSI_INT_FRAME_START | CSI_INT_FRAME_END | CSI_INT_ERR,
csi->base + CSI_INT_EN);
}
注意:CSI 控制器的寄存器配置,不同 SoC 差异很大。有的 SoC 需要先配 Lane 数再使能时钟,有的则相反。一定要看 datasheet 的初始化序列。我曾经因为没按顺序配,导致 CSI 控制器一直报 Lane 同步失败。
4.4 多通道 Lane 配置与同步
多 Lane 传输,说白了就是把数据分散到多条 Lane 上同时发,提高带宽。但 Lane 之间会有 skew(偏移),接收端必须做 Lane 对齐。我见过最头疼的问题,就是 4 Lane 模式下,有一条 Lane 的 skew 太大,导致整帧数据错位。
Lane 同步的流程,一般是这样的:
- HS 时钟同步:所有 Lane 共享同一个 HS 时钟。时钟 Lane 必须先稳定,数据 Lane 才能开始传输。
- Lane 对齐序列:Sensor 在每帧开始前,会发送一个特定的对齐序列(比如 0xB8 0xB8 0xB8 0xB8)。CSI 控制器检测到这个序列后,就知道 Lane 对齐了。
- Skew 补偿:控制器内部有 FIFO,用来补偿 Lane 之间的延迟差。FIFO 深度要足够,否则 skew 大了会溢出。
调试技巧:如果图像出现条纹或错位,先检查 Lane 对齐状态寄存器。很多 SoC 都有 Lane 对齐状态位,比如 Lane0_align_done、Lane1_align_done。如果某条 Lane 一直没对齐,大概率是硬件连接问题或 D-PHY 配置不对。
4.5 知识结构总览
下面这张图,把 CSI-2 从 Sensor 到 ISP 的完整数据流画了出来。你可以看到,D-PHY 负责物理传输,CSI 控制器负责协议解析和 DMA,ISP 负责图像处理。每一层都有各自的配置要点。
4.6 避坑指南
做 CSI 驱动这些年,我总结了几条血泪教训:
- Lane 顺序别搞反:有些 SoC 的 Lane 映射不是顺序的。比如 Lane0 对应物理 Lane2。配错了,数据全乱。建议先读 SoC 的 CSI 引脚复用表。
- 时钟 Lane 必须优先稳定:数据 Lane 的同步依赖时钟 Lane。如果时钟 Lane 没锁住,数据 Lane 怎么配都没用。
- DMA 地址要对齐:很多 SoC 要求 DMA 地址 32 字节对齐。不对齐的话,DMA 传输会报错。我遇到过一例,图像偶尔花屏,查了两天才发现是 DMA 地址没对齐。
- 中断处理要快:CSI 中断是高频中断(每帧至少一次)。中断处理函数里不要做耗时操作,比如打印日志。否则容易丢帧。
重要提醒:CSI 驱动调试时,先用 1 Lane 模式验证基本通路。1 Lane 通了,再切到多 Lane。这样能快速定位问题是出在 Lane 同步还是协议解析。我每次都是这么干的,屡试不爽。