
清空记录
历史记录
取消
清空记录
历史记录

RKISP内核驱动的解析与实战系列文章,为了方便读者更清晰分模块了解,此篇文章将分为上、中、下三篇发布,本篇为上篇。
本篇将以RK3576(ISP39)+Linux Kernel6.1的完整源码为基础,从驱动架构全景、设备初始化Probe流程、Media子设备拓扑、中断处理以及ISP39专属硬件特性等维度,全方位拆解RKISP整套驱动逻辑。如果你正在从事具身智能、机器人视觉、自动驾驶、无人机感知或工业视觉检测等领域的嵌入式开发,这篇文章将是你的绝佳参考。
关注「触觉智能」公众号,回复关键词“客服”,联系客服即可获取瑞芯微RK开发板/核心板相关资料,可对接技术支持团队,咨询项目选型与项目需求。
前20位申领资料,可获赠开发板大额折扣。机会有限,先到先得!
一、摄像头链路配置参考
RK3576摄像头链路的配置原理大体与RK3588类似,只是节点下标与硬件对应不同,此处提供RK3576的链路图,其余参考RK3588即可。
适用平台:RK3576/ISP39内核版本:Kernel6.1
源码路径:drivers/media/platform/rockchip/isp/
配套代码目录:kernel-6.1/drivers/media/platform/rockchip/isp/
驱动版本:v2.6.0+(该版本首次完整支持ISP39硬件)
二、驱动架构全景
RKISP驱动遵循V4L2标准分层设计,从用户态到硬件寄存器分为五层,层级清晰解耦:
┌──────────────────────────────────────────────────────────┐│ 用户态层 (Camera HAL3) │├──────────────────────────────────────────────────────────┤│ /dev/video* /dev/v4l2-subdev* 设备节点 │├──────────────────────────────────────────────────────────┤│ V4L2 / Media Controller 媒体框架层 │├──────────────────────────────────────────────────────────┤│ rkisp 驱动总入口层 ││ (dev.c / rkisp.c / hw.c / regs.c) │├─────────────┬────────────── ┬─────────────────────────────┤│ rkisp.ko │ 捕获通道 │ 3A / 参数管理 ││ 主驱动模块 │ capture.c │ isp_params.c / stats.c ││ │ capture_v39.c │ isp_params_v39.c ││ │ │ isp_stats_v39.c │├─────────────┴────────────── ┴─────────────────────────────┤│ CSI-2 接收 │ Bridge桥接 │ IOMMU │ DMA Rx ││ csi.c │ bridge.c │ rkisp_mmu │ dmarx.c │├───────────── ┴──────────────┴────────────┴──────────┤│ ISP39 硬件寄存器底层 ││ (regs.c / regs_v3x.h) │└─────────────────────────────────────────────────────┘
在驱动头文件common.h中定义了全系列ISP硬件版本枚举,RK3576平台专属ISP39对应宏ISP_V39 = 0xa0:
// common.henum rkisp_isp_ver { ISP_V10 = 0x00, ISP_V12 = 0x20, ISP_V13 = 0x30, ISP_V20 = 0x40, ISP_V21 = 0x50, ISP_V30 = 0x60, ISP_V32 = 0x70, ISP_V32_L= 0x80, ISP_V33 = 0x90, ISP_V39 = 0xa0, // RK3576平台专用ISP ISP_V35 = 0xb0,};RKISP完全基于V4L2 Media Controller框架实现,注册大量v4l2_subdev子设备与video输出节点,完整数据流链路如下:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ Sensor │ │ MIPI D-PHY │ │ CSI Subdev ││ 图像传感器 │────▶MIPI物理层──────▶ rkisp-csi子设备 │└──────────────┘ └──────────────┘ └──────┬───────┘ │ ▼┌───────────────────────────────────────────────────────┐│ ISP Subdev (rkisp-isp-subdev) ││ 端口:SINK(0)输入 | SINK_PARAMS(1)参数 | SOURCE_PATH(2)图像输出│ │ SOURCE_STATS(3)3A统计输出└──┬──────────────┬──────────────┬──────────┴───────────┘ │ │ │ ▼ ▼ ▼┌────────┐ ┌──────────┐ ┌───────────┐│ MP │ │ SP │ │ LDC ││ mainpath│ │ selfpath │ │ ldcpath ││ /dev/ │ │ /dev/ │ │ /dev/ ││ video0 │ │ video1 │ │ video2 │└────────┘ └──────────┘ └───────────┘┌──────────┐ ┌───────────┐│ params │ │ stats ││ 参数下发 │ │ 3A统计上报 │└──────────┘ └───────────┘
各video设备节点功能对照表(定义于capture.h):
宏定义 | 设备节点名称 | 核心用途 |
MP_VDEV_NAME | rkisp_mainpath | 主输出通道,支持YUV/Raw原始图像输出 |
SP_VDEV_NAME | rkisp_selfpath | 自缩放通道,输出小尺寸预览图 |
LDC_VDEV_NAME | rkisp_ldcpath | 镜头畸变校正专用输出通道 |
FBC_VDEV_NAME | rkisp_fbcpath | ISP39新增,图像压缩输出通道 |
BP_VDEV_NAME | rkisp_bypasspath | Bypass直通通道,输出未经ISP处理原始数据 |
DMATRX0_VDEV_NAME | rkisp_rawwr0~3 | HDR多路DMA原始数据写入通道 |
设备节点可在系统路径/sys/class/video4linux/下查看,全部挂载至media graph媒体拓扑链路中。
三、Probe设备上电初始化全流程
驱动入口函数为dev.c内rkisp_plat_probe(),通过DTS中compatible字符串匹配硬件平台:
// hw.c{ .compatible = "rockchip,rk3576-rkisp", .data = &rk3576_isp_match_data },RK3576完整ISP设备树节点(rk3576.dtsi:3302):
rkisp: isp@27c00000 { compatible = "rockchip,rk3576-rkisp"; reg = <0x0 0x27c00000 0x0 0x7f00>; interrupts = , // mipi_irq , // mi_irq ; // isp_irq interrupt-names = "mipi_irq", "mi_irq", "isp_irq"; clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>, <&cru CLK_ISP_CORE>, <&cru CLK_ISP_CORE_MARVIN>, <&cru CLK_ISP_CORE_VICAP>; clock-names = "aclk_isp", "hclk_isp", "clk_isp_core", "clk_isp_core_marvin", "clk_isp_core_vicap"; power-domains = <&power RK3576_PD_VI>; iommus = <&rkisp_mmu>; status = "disabled";}; rkisp_plat_probe()(dev.c:911)从上电到注册完整子设备执行链路:
rkisp_plat_probe├── rkisp_attach_hw() // 绑定物理硬件设备(hw.c)│ ├── of_find_device_by_node(hw_node)│ └── rkisp_hw_probe() // 硬件底层初始化├── devm_kzalloc(sw_base) // 分配软件影子寄存器缓存├── rkisp_vs_irq_parse() // 解析VSYNC帧同步中断├── media_device_init() // 初始化Media设备框架├── v4l2_device_register() // 注册标准V4L2设备├── pm_runtime_enable() // 开启电源管理 runtime├── rkisp_register_platform_subdevs() // 核心:批量注册所有子设备│ ├── rkisp_register_isp_subdev() // ISP核心子设备│ ├── rkisp_register_csi_subdev() // CSI MIPI接收子设备│ ├── rkisp_register_bridge_subdev() // ISP与ISPP桥接子设备│ ├── rkisp_register_stream_vdevs() // MP/SP/LDC图像捕获通道│ │ └── (版本分发) rkisp_register_stream_v39()│ ├── rkisp_register_dmarx_vdev() // DMA原始数据写入节点│ ├── rkisp_register_stats_vdev() // 3A统计上报节点│ ├── rkisp_register_params_vdev() // 3A参数下发节点│ ├── rkisp_register_luma_vdev() // 亮度统计通道│ └── rkisp_register_pdaf_vdev() // PDAF对焦数据通道(可选)├── isp_subdev_notifier() // 异步探测Sensor图像传感器└── media_device_register() // 完成Media设备注册
该函数建立逻辑驱动与物理ISP硬件的绑定关系,核心硬件结构体rkisp_hw_dev:
// hw.cstruct rkisp_hw_dev { const struct isp_match_data *match_data; struct platform_device *pdev; void __iomem *base_addr; struct clk *clks[RKISP_MAX_BUS_CLK]; enum rkisp_isp_ver isp_ver; struct rkisp_device *isp[DEV_MAX]; // 最多DEV_MAX个虚拟ISP设备 int dev_num; u32 unite; // 图像拼接模式:无拼接/双ISP拼接/单通道拼接 bool is_mmu; struct rkisp_monitor monitor; // 硬件看门狗监控 // ...};RK3576 ISP硬件匹配时钟配置(hw.c:929):
static const struct isp_match_data rk3576_isp_match_data = { .clks = rk3576_isp_clks, .num_clks = ARRAY_SIZE(rk3576_isp_clks), .isp_ver = ISP_V39, .clk_rate_tbl = rk3576_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk3576_isp_clk_rate),};static const char * const rk3576_isp_clks[] = { "clk_isp_core", "aclk_isp", "hclk_isp", "clk_isp_core_marvin", "clk_isp_core_vicap",};RK3576 ISP共5路独立时钟域,对比RK3588精简冗余拼接时钟;其中clk_isp_core_marvin、clk_isp_core_vicap为ISP39全新硬件时钟。
RK3576 DTS定义rkisp_vir0 ~ rkisp_vir5共6路虚拟ISP,全部共享同一块物理ISP硬件,通过rockchip,hw = <&rkisp>绑定物理节点:
物理ISP硬件 ──→ rkisp_vir0 ──→ rkisp_vir0_sditf ──→ vpss0_in (ISPP后处理) │ rkisp_vir1 ──→ rkisp_vir1_sditf ──→ vpss1_in │ rkisp_vir2 ──→ rkisp_vir2_sditf ──→ vpss2_in │ ... └ rkisp_vir5 ──→ rkisp_vir5_sditf ──→ vpss5_in
每一路rkisp_virN通过sditf(子设备接口)桥接对应VPSS图像后处理单元。
多虚拟ISP核心作用:支持多路Sensor、多规格图像流分时复用单块ISP硬件,由上层AIQ 3A算法做时间片调度,是双摄、多摄方案的核心底层支撑。
该结构体是ISP图像处理管线的逻辑抽象,定义于rkisp.h:136:
struct rkisp_isp_subdev { struct v4l2_subdev sd; // 标准V4L2子设备实例 struct media_pad pads[RKISP_ISP_PAD_MAX]; // 4个媒体端口 struct v4l2_mbus_framefmt in_frm; // Sensor原始输入图像尺寸 struct ispsd_in_fmt in_fmt; // 输入图像格式 struct v4l2_rect in_crop; // ISP_ACQ输入裁剪区域 struct ispsd_out_fmt out_fmt; // ISP输出图像格式 struct v4l2_rect out_crop; // ISP_IS输出稳定裁剪区域 atomic_t frm_sync_seq; // 帧同步序列号};端口定义
enum rkisp_isp_pad { RKISP_ISP_PAD_SINK, // Pad 0:图像输入(CSI/DVP数据源) RKISP_ISP_PAD_SINK_PARAMS, // Pad 1:3A参数下发输入口 RKISP_ISP_PAD_SOURCE_PATH, // Pad 2:处理后图像输出(MP/SP/LDC) RKISP_ISP_PAD_SOURCE_STATS, // Pad 3:3A统计数据输出口 RKISP_ISP_PAD_MAX};ISP内部两级裁剪逻辑:
+---------------------------------------------------------+| Sensor原始图像 in_frm || +---------------------------------------------------+ || | ISP_ACQ (黑电平校正专用裁剪) | || | in_crop 裁剪有效像素区域 | || | +--------------------------------------------+ | || | | ISP_IS (图像防抖稳定裁剪) | | || | | out_crop 最终输出分辨率裁剪 | | || | | | | || | | ──→ MP (mainpath) 输出YUV/Raw原图 | | || | | ──→ SP (selfpath) 缩放预览图 | | || | | ──→ LDC (ldcpath) 畸变校正图 | | || | +--------------------------------------------+ | || +---------------------------------------------------+ |+---------------------------------------------------------+
ISP_ACQ(in_crop)从Sensor原始画面截取有效像素,用于黑电平校正BLS、坏点修复DPCC;
SP_IS(out_crop)图像防抖裁剪,裁剪后分辨率直接输出至三路捕获通道。
// rkisp.h#define CIF_ISP_INPUT_W_MAX_V39 4672#define CIF_ISP_INPUT_H_MAX_V39 3504#define CIF_ISP_INPUT_W_MAX_V39_UNITE 8192 // 双ISP拼接模式宽#define CIF_ISP_INPUT_H_MAX_V39_UNITE 6144 // 双ISP拼接模式高
规格总结:单ISP最大支持4672×3504(约1600万像素);开启Unite双ISP拼接模式最高支持8192×6144(约5000万像素)。
五、CSI-2接收子设备(csi.c)
CSI子设备专门管理MIPI CSI-2接收端硬件,核心工作:
1.D-PHY物理层初始化、MIPI Lane通道数量配置;
2.MIPI数据类型(DT)解析(RAW10/RAW12/YUV422等);
3.虚拟通道VC路由分配;
4.MIPI数据包错误检测、异常硬件复位恢复。
CSI设备结构体:
// csi.hstruct rkisp_csi_device { struct v4l2_subdev sd; struct media_pad pads[CSI_PAD_MAX]; int lanes; // MIPI通道数量 u32 datatype; // MIPI数据类型 u32 channel; // MIPI虚拟通道VC bool is_csi3; // CSI-3协议标识 // ...};rkisp_fwnode_parse()(dev.c:690)解析DTS端点MIPI总线配置:
static int rkisp_fwnode_parse(struct device *dev, struct v4l2_fwnode_endpoint *vep, struct v4l2_async_subdev *asd){ struct rkisp_async_subdev *rk_asd = container_of(asd, struct rkisp_async_subdev, asd); // MIPI sensor总线配置由D-PHY层单独处理,此处仅处理并行/BT656 if (vep->bus_type != V4L2_MBUS_BT656 && vep->bus_type != V4L2_MBUS_PARALLEL) return 0; rk_asd->mbus.type = vep->bus_type; return 0;}中断入口rkisp_mipi_v3x_isr():
1.解析phy锁失、溢出、数据包校验错误等状态位;
2.错误计数累计超过RKISP_CONTI_ERR_MAX (50)自动复位MIPI硬件;
3.向上层上报V4L2_EVENT_FRAME_SYNC帧同步事件,供给3A算法使
至此,上篇内容告一段落。我们从驱动架构全景出发,依次剖析了摄像头链路配置、Probe初始化流程、ISP 核心Subdev子设备以及CSI-2接收模块,为理解RKISP驱动奠定了坚实基础。
产品简介
