1. RK平台Camera子系统全景

做Camera驱动开发,第一件事不是写代码,而是先把整个链路看清楚。我刚开始接触RK平台时,也犯过这个错误——上来就对着datasheet调寄存器,结果图像出不来,查了三天才发现是MIPI时钟配错了。所以这一章,我们先搭个全景图。

1.1 硬件架构:从镜头到内存

一个典型的RK Camera硬件链路,可以拆成四段:

  1. 镜头+传感器:把光信号转成电信号,输出RAW图
  2. MIPI CSI-2 传输:传感器通过差分信号对,把数据传给SoC
  3. RK ISP:做去噪、坏点校正、自动白平衡、色彩还原
  4. DDR/内存:ISP处理完的数据,送到显存或系统内存

你想想看,这四段里任何一段出问题,最终图像都会翻车。我个人习惯,拿到一个新板子,先拿示波器量MIPI clock lane有没有波形——这一步能排除一半的硬件问题。

关键节点速查表

节点接口/协议常见问题
Sensor → SoCMIPI CSI-2 (1-4 Lane)极性反、电压不匹配
SoC → ISP内部总线 (AXI/AHB)时钟门控未开启
ISP → DDRDMA / AXI带宽不足、帧率掉

1.2 软件栈:分层解耦

RK的Camera软件栈,从底层到上层大概分五层。我画了个简图,你一看就明白:

RK Camera 软件栈分层架构 应用层 (Camera HAL / App) 框架层 (Android Camera Framework / V4L2) 驱动层 (V4L2 Subdev / ISP Driver / Sensor Driver) 硬件抽象层 (RK ISP T-Engine / RkAiq) 硬件层 (Sensor / MIPI PHY / ISP / DDR) 说明:Sensor Driver 和 ISP Driver 通过 V4L2 Subdev 机制通信,RkAiq 负责 3A 算法

这里我想强调一点:Sensor驱动在驱动层,它只负责配置传感器寄存器、控制帧率和曝光。ISP的3A算法(自动曝光、自动白平衡、自动对焦)在RkAiq里跑,跟Sensor驱动是分开的。我曾经遇到一个坑——有人把3A逻辑写死在Sensor驱动里,结果换了颗Sensor,整个驱动都得重写。千万别这么干。

1.3 MIPI CSI/DSI 协议基础

MIPI CSI(Camera Serial Interface)是Camera数据从Sensor到SoC的传输协议。DSI(Display Serial Interface)是显示用的,但它们的物理层是一样的——D-PHY。

说白了,MIPI就是一组高速差分信号对。一个Lane包含一对D+和D-。CSI-2协议最多支持4个Data Lane + 1个Clock Lane。

MIPI CSI-2 关键参数

  • 每Lane速率:常见 400 Mbps ~ 2.5 Gbps
  • 分辨率越高,需要的Lane数越多:1080p@30fps 一般用2 Lane,4K@30fps 需要4 Lane
  • 数据类型:RAW8/RAW10/RAW12/YUV422等

嗯,这里要注意:MIPI的时钟是DDR(双倍数据速率)的,也就是说每个时钟周期传2个bit。我调试时习惯先确认Clock Lane的频率对不对,用示波器看波形是不是方波,有没有过冲。

1.4 RK ISP Pipeline 简介

RK的ISP(Image Signal Processor)是一个硬件模块,它把Sensor出来的RAW数据,处理成人眼能看的YUV或RGB图。Pipeline大致是这样的:

  1. BLC(黑电平校正):去掉Sensor的暗电流噪声
  2. DPC(坏点校正):把死点、亮点替换掉
  3. AWB(自动白平衡):让白色在不同光源下看起来是白的
  4. Demosaic(去马赛克):从Bayer阵列插值出RGB
  5. CCM(色彩校正矩阵):把Sensor的RGB映射到标准色域
  6. Gamma / Tone Mapping:调整亮度和对比度
  7. 输出:YUV或RGB送到显示或编码器

避坑提醒

我曾经调试一个项目,图像偏绿,查了三天。最后发现是ISP的AWB参数没加载,Sensor的RAW数据直接输出了。记住:ISP的tuning参数(也就是3A算法参数)必须跟Sensor匹配,不同Sensor的tuning文件不能混用。

RK的ISP Pipeline在驱动层面,是通过V4L2 Subdev来管理的。Sensor注册为一个subdev,ISP也注册为一个subdev,它们通过media controller框架连接。你写Sensor驱动时,只需要把数据格式、帧率、曝光时间这些参数配好,剩下的ISP处理由RkAiq自动完成。

好了,这一章的全景图就搭到这里。你心里有了这个框架,后面写驱动时就知道每一行代码落在哪个位置了。