第一章:Sensor驱动基础——MIPI CSI-2协议、上电时序与I2C调试

各位同学,欢迎来到《瑞芯微Sensor驱动与ISP Pipeline对接实战》的第一章。

做嵌入式视觉,说白了就是让摄像头把光信号变成芯片能处理的数字信号。这中间要过好几道关:Sensor本身怎么工作、数据怎么传过来、ISP怎么接住。咱们第一章,先把最基础的三件事讲透——MIPI CSI-2协议、Sensor上电时序、I2C通信调试。

这三件事,我当年刚入行时踩过不少坑。有一次调一颗索尼的Sensor,上电时序差了0.5ms,结果图像全是花屏,查了三天才发现是reset信号给早了。嗯,这种教训,我希望你们别重复。

本章核心目标:理解MIPI CSI-2物理层与协议层的基本概念,掌握Sensor上电时序的硬件要求,学会用I2C工具调试Sensor寄存器。

1.1 MIPI CSI-2协议概述

MIPI CSI-2,全称是Camera Serial Interface 2,是移动设备和嵌入式平台最主流的摄像头接口协议。瑞芯微的RK3588、RK3568、RV1126这些芯片,CSI-2接口都是标配。

CSI-2的物理层基于MIPI D-PHY。D-PHY使用差分信号传输,一对差分线就是一个Lane。典型的配置是1个Clock Lane + 1~4个Data Lane。数据在DDR模式下传输——时钟的上升沿和下降沿都采样数据,所以带宽利用率很高。

CSI-2协议的分层结构:

  • 物理层(PHY Layer):D-PHY规范,定义电气特性、线序、时序。
  • 协议层(Protocol Layer):定义数据包格式、帧结构、数据类型。
  • 应用层(Application Layer):定义像素格式、数据映射,比如RAW10、RAW12、YUV422。

我个人习惯把CSI-2的数据流想象成「快递包裹」:

  • 每一帧图像是一个大包裹
  • 每行数据是一个小包裹
  • 每个包裹有包头(Header)和包尾(Footer)
  • 包头里包含了数据类型、像素格式、行长度等信息

CSI-2的数据包类型,常用的有这些:

数据类型(Data Type) 描述 常见场景
0x2B RAW10 10-bit原始Bayer数据
0x2C RAW12 12-bit原始Bayer数据
0x1E YUV422 8-bit 处理后的YUV数据
0x12 JPEG 压缩图像数据

避坑提示:我曾经在调试RK3588时,Sensor输出的是RAW10,但CSI-2配置成了RAW12。结果图像亮度异常,每个像素都偏暗。检查了半天才发现是数据类型不匹配。记住:Sensor输出什么格式,CSI-2就要配什么格式,一个字都不能错。

下面这张图,是我画的一个CSI-2数据流的结构图,帮你理解数据是怎么从Sensor走到SoC的:

MIPI CSI-2 数据流结构图 图像Sensor RAW / YUV 输出 MIPI D-PHY 差分信号 / DDR传输 CSI-2 Receiver 协议解析 / 解包 ISP Pipeline 图像处理 4-lane MIPI 差分数据 帧数据 CSI-2 协议层 • 帧起始包 (FS) • 帧结束包 (FE) • 行数据包 (Line) • 数据类型 (DT) 应用层 • RAW8/10/12/14 • YUV422/420

1.2 Sensor上电时序与硬件原理图解读

Sensor是个精密的模拟器件。它需要严格的电源上电顺序,否则轻则图像异常,重则烧毁芯片。你想想看,Sensor内部有模拟电路、数字电路、IO电路,它们对电源的依赖完全不同。

典型的Sensor电源域:

  • AVDD(模拟电源):通常2.8V,给像素阵列和模拟前端供电。
  • DVDD(数字核心电源):通常1.2V或1.8V,给数字逻辑供电。
  • IOVDD(IO电源):通常1.8V,给I2C、MIPI接口供电。

上电时序,说白了就是这三个电源谁先来、谁后来,以及复位信号什么时候释放。不同厂家的Sensor要求不一样,但有个通用原则:先模拟、后数字、再IO,最后释放复位。

我拿一颗常见的Sensor举例,它的上电时序要求是这样的:

步骤 动作 时间要求 说明
1 AVDD上电 (2.8V) t0 模拟电源先稳定
2 DVDD上电 (1.2V) t0 + 1ms 数字核心后上电
3 IOVDD上电 (1.8V) t0 + 2ms IO接口最后上电
4 MCLK提供时钟 t0 + 3ms 主时钟稳定输入
5 复位释放 (XSHUTN拉高) t0 + 5ms 所有电源稳定后释放复位
6 I2C初始化配置 t0 + 10ms 复位后等待至少5ms再写寄存器

警告:千万不要忽略上电时序!我曾经在一个项目里,硬件工程师把DVDD和IOVDD用同一个LDO供电,导致上电时两个电源同时起来。Sensor虽然能工作,但图像偶尔会出现横纹干扰。查了两个月,最后发现是电源纹波耦合到了像素阵列。换成分立LDO供电后,问题彻底解决。

看硬件原理图时,我一般会关注这几个关键点:

  • 电源网络:确认AVDD、DVDD、IOVDD是否独立LDO供电,滤波电容是否足够。
  • 复位引脚:XSHUTN或RESET_N,确认上拉/下拉电阻是否正确。
  • MIPI差分对:确认D0P/D0N、D1P/D1N、CLKP/CLKN等差分线是否等长,阻抗是否匹配(通常100Ω差分阻抗)。
  • I2C引脚:确认SCL/SDA是否有上拉电阻(通常1.5kΩ~4.7kΩ)。

1.3 I2C通信调试实战

I2C是Sensor和SoC之间最常用的控制接口。Sensor的寄存器配置、增益设置、曝光控制,全走I2C。如果I2C不通,Sensor就像个哑巴,你喊它它不理。

在瑞芯微平台上,调试I2C最常用的工具是i2c-tools。这套工具集包含i2cdetect、i2cget、i2cset、i2cdump等命令,非常实用。

I2C调试的基本步骤:

  1. 确认I2C总线编号:在瑞芯微平台上,Sensor通常挂在I2C2或I2C3上。用i2cdetect -l列出所有I2C总线。
  2. 扫描设备地址:用i2cdetect -y <bus_number>扫描总线上的设备。Sensor的I2C地址通常是0x30、0x36、0x6C等。
  3. 读取寄存器:用i2cget -y <bus_number> <device_addr> <reg_addr> w读取寄存器值。
  4. 写入寄存器:用i2cset -y <bus_number> <device_addr> <reg_addr> <value> w写入寄存器值。

举个例子,假设Sensor的I2C地址是0x36,挂在I2C3上,我想读取芯片ID寄存器(地址0x0000):

# 扫描I2C3总线,看0x36设备是否存在
i2cdetect -y 3

# 读取0x0000寄存器的值(16位地址,16位数据)
i2cget -y 3 0x36 0x0000 w

# 写入0x0000寄存器为0x1234
i2cset -y 3 0x36 0x0000 0x1234 w

调试技巧:我习惯在驱动初始化函数里,第一步就读Sensor的芯片ID。如果读回来的值和数据手册对不上,说明I2C通信有问题。这时候别急着调驱动,先用i2c-tools在用户态验证一下。很多I2C问题其实是硬件问题——上拉电阻没焊、电平不匹配、或者地址搞错了。

常见的I2C调试问题:

  • 设备扫描不到:检查I2C地址是否正确(7位地址还是8位地址?Sensor数据手册通常给的是7位地址,但i2cdetect显示的是8位地址,左移了一位)。
  • 读取返回0xFF:大概率是设备没应答,检查电源和复位。
  • 读取返回0x00:可能是寄存器地址不对,或者设备处于休眠状态。
  • 写入后读取不变:检查寄存器是否只读,或者需要先解锁。

嗯,I2C调试说难不难,说简单也不简单。关键是要有耐心,一步一步排查。我见过太多人一上来就怀疑驱动代码有问题,结果最后发现是I2C地址写错了——数据手册上写的是0x30,但那是7位地址,i2cdetect要用0x60才能扫到。

本章小结:MIPI CSI-2是Sensor和SoC之间的数据通道,上电时序是Sensor正常工作的前提,I2C是控制Sensor的命脉。这三件事搞不定,后面的ISP调试根本无从谈起。下一章,我们会深入Sensor的寄存器配置,教你如何让Sensor输出正确的图像格式。