ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

RK3568平台AHD转MIPI CSI驱动开发与调试实战

2026/9/2 23:32:27 拓冰建站 浏览量
RK3568平台AHD转MIPI CSI驱动开发与调试实战 简介针对瑞芯微RK3568平台嵌入式开发者的xs9922b驱动源码包它解决了AHD摄像头信号转成MIPI接口的驱动适配问题已经在真实板卡上完成调试并通过验证能够支持四路AHD摄像头同时接入稳定实现视频流采集。整个压缩包内共有两个文件一个是点C的驱动源文件承担设备初始化、寄存器读写以及链路控制等核心逻辑另一个是点H的寄存器配置文件集中管理多路通道的时钟、增益与输出参数包体只有十二KB结构非常精简方便直接查看和移植到不同内核版本。目前已经有一百五十六人学习浏览适合正在调试RK3568摄像头通路、需要接入多路AHD视频的嵌入式驱动工程师也适合对AHD转MIPI方案做技术预研的开发者。拿到这份代码后可以对照寄存器配置快速理清xs9922b的上电初始化流程再结合MIPI CSI驱动完成设备树与链路的对接直观复现四路AHD摄像头的取流效果从而大幅缩短驱动调试和适配周期。1. 项目概述与方案背景1.1 这套链路到底解决什么问题先说结论这个项目是在瑞芯微 RK3568 平台上把一路通过同轴电缆传输的 AHD 模拟高清摄像头信号转换成为 MIPI CSI 信号接入 RK3568 自带的 ISP最终在 Linux 系统下通过 V4L2 框架正常取流显示。AHDAnalog High Definition是一种基于同轴电缆传输高清视频的模拟技术最高支持 1080P30fps传输距离在普通同轴线缆下可以做到 200 米以上。相比直接使用 MIPI 接口的数字 sensorAHD 方案最大的优势是线缆成本低、抗干扰能力强、布线灵活在车载环视、倒车影像、工业视觉后装改造等场景里几乎是标配方案。而 RK3568 这颗芯片虽然自带多路 MIPI CSI 和 ISP但它本身不能直接解码 AHD 信号所以必须在中间接一个桥接芯片把模拟信号转成芯片能吃的数字 MIPI 输入。xs9922b 就是这颗桥接芯片业内也有类似型号比如 TP2815、NVP6324 等但它们的工作逻辑基本一致AHD 信号进来芯片内部做模拟解码、均衡、去隔行部分型号支持然后按标准 MIPI CSI-2 协议把图像数据打包输出给 SoC。我用的这个 9922 是四通道输入的型号单颗芯片最多支持四路 AHD 摄像头通过内部切换或者多路同时输出到 MIPI。这套方案适合谁来参考主要是三类人一是在做车载电子、安防后装产品的嵌入式工程师二是想把老式模拟摄像头原封不动接入现代 SoC 平台的开发者三是在 RK3568 或者类似瑞芯微平台上做 Camera 驱动开发、还不太清楚 MIPI 桥接芯片怎么接 ISP 链路的人。这篇就把我从设备树配置到驱动调通、再到实际取流验证的整个过程拆开讲涉及到的坑尽量都写出来。1.2 为什么选择 RK3568 做这个平台RK3568 在国产 SoC 里属于比较万金油的存在四核 A55 处理器内置 0.8TOPS NPU带多路 MIPI CSI、MIPI DSI、PCIe、GbE跑 Linux 内核主线和 Rockchip SDK 都很顺手。关键是这颗芯片的 ISP 和 MIPI 控制器做得比较成熟v4l2 框架下的文档和示例代码比很多小厂芯片齐全得多对做驱动接入的工程师来说省去了大量从零读 datasheet 的精力。我选 RK3568 还有一个原因它的 MIPI CSI 通道数足够多可以方便地验证多路接入。xs9922b 转出来的 MIPI 信号一般是 4 laneRK3568 的 CSI DPHY 支持 4 lane 输入芯片内部可以直接对接。如果用的是更早的 RK3288 那种平台虽然也能接但 DPHPHY 的时钟范围和数据率限制更多调起来会更费劲。2. 驱动框架与设备树设计2.1 驱动整体结构从 I2C 到 media controller这类型桥接芯片的驱动本质上就是一个标准的 V4L2 subdev 驱动。它在 Linux 内核里被识别为一个 I2C 客户端设备然后通过 v4l2_subdev 接口对外暴露控制能力与 RK3568 的 DPHY、ISP 实体一起组成一条 media pipeline。整体结构可以拆成三层看I2C 通信层负责访问 xs9922b 内部寄存器完成芯片初始化包括 AHD 制式选择、MIPI 输出模式配置、通道使能等等。MIPI 配置层负责告诉芯片以怎样的格式输出 MIPI 信号包括 lane 数量、连续时钟还是非连续时钟、YUV422 还是 YUV420、数据率上限等这些参数必须和 RK3568 DPHY 侧匹配。V4L2 subdev 层实现 get/set 格式、s_stream 等回调让上层可以把 subdev 和 DPHY、ISP 实体link起来最终通过 /dev/video0 出图像。驱动源码里最核心的结构就是 v4l2_subdev_pad_opsstatic const struct v4l2_subdev_pad_ops xs9922b_pad_ops { .init_cfg xs9922b_init_cfg, .get_fmt xs9922b_get_fmt, .set_fmt xs9922b_set_fmt, .get_selection xs9922b_get_selection, }; static const struct v4l2_subdev_video_ops xs9922b_video_ops { .s_stream xs9922b_s_stream, .g_mbus_config xs9922b_g_mbus_config, };s_stream 回调里面做的是最脏的活拉高芯片的复位脚然后按预先写好的寄存器表逐个写入最后等待 AHD 信号锁定。这里有个细节不同厂家的 AHD 摄像头可能不是同一制式有的走 AHD 1080P有的走 AHD 720P还有的混用 TVI、CVI所以驱动里通常在 probe 阶段先默认配置成 AHD 模式再在 s_stream 时做一次制式自动检测读到当前输入信号是 720P 还是 1080P然后动态调整输出时序。9922 的寄存器里有一个状态位专门表示信号锁定状态驱动里要轮询这个状态位直到锁住再继续往下走否则上层开流的时候很容易拿到花屏或者黑屏的数据。2.2 设备树配置要点RK3568 上接 MIPI 摄像头有一套固定的流程化配置主要涉及设备树里的 i2c 节点、mipi_dphy 节点、csi2 节点、isp 节点四大部分。我把关键 node 写成简化版贴出来i2c4 { status okay; pinctrl-names default; pinctrl-0 i2c4m1_xfer; xs9922b: xs9922b30 { compatible vs,xs9922b; reg 0x30; pinctrl-names default; pinctrl-0 xs9922b_pwdn; reset-gpios gpio3 RK_PA6 GPIO_ACTIVE_LOW; pwdn-gpios gpio3 RK_PA7 GPIO_ACTIVE_HIGH; rockchip,camera-module-index 0; rockchip,camera-module-name default; rockchip,camera-module-facing back; rockchip,camera-module-interface mipi; port { xs9922b_out: endpoint { remote-endpoint mipi_in_ucam0; >struct xs9922b_mipi_config { u32 lane_count; u32 data_type; u32 vc; u32 width; u32 height; u32 fps; }; static const struct xs9922b_mipi_config xs9922b_mipi_cfg { .lane_count 4, .data_type 0x1e, // YUV422-8bit .vc 0, .width 1920, .height 1080, .fps 30, };第三块是输出时钟。MIPI 的 bit clock 由芯片内部 PLL 提供这个频率取决于输出分辨率、帧率和 lane 数。公式很简单clock_lane width * height * fps * bits_per_pixel / lane_count。比如 1080P30fpsYUV422 一像素按 16bit 算4 lane 情况下大概需要 1920108030*16/4 ≈ 248.8 Mbps/lane再加上 HSA/HBP/HFP 这些消隐时间实际 lane rate 通常要到 400~500Mbps 才稳。芯片寄存器里 PLL 的分频系数要和这个目标频率匹配这个值往往不是随便填的建议参考芯片专门的 MIPI PLL 计算工具或厂商的参考配置表。3.2 与 RKISP 的对接和流控逻辑驱动写完后真正让它出图还需要打通 RKISP 的链路。这一步很多人会挂在 media controller 拓扑不正确上。RK3568 的媒体拓扑大概长这样media-ctl -p # 典型输出节选 # - entity 1: xs9922b 0-0030 # pad0: Source [fmt:UYVY8_2X8/1920x1080] # - m00_b_mipi_dphy0:0 [ENABLED] # - entity 2: m00_b_mipi_dphy0 # pad0: Sink # pad1: Source # - m00_b_csi2:0 [ENABLED] # - entity 3: m00_b_csi2 # pad0: Sink # pad1: Source # - rkisp-isp0:0 [ENABLED] # - entity 4: rkisp-isp0 # pad0: Sink # pad1: Source # - rkisp_mainpath:0 [ENABLED]在正式跑采集之前先通过 media-ctl 把格式统一设好media-ctl -d /dev/media0 -r media-ctl -d /dev/media0 -l xs9922b 0-0030:0 - m00_b_mipi_dphy0:0[1] media-ctl -d /dev/media0 -l m00_b_mipi_dphy0:1 - m00_b_csi2:0[1] media-ctl -d /dev/media0 -l m00_b_csi2:1 - rkisp-isp0:0[1] media-ctl -d /dev/media0 -V xs9922b 0-0030:0[fmt:UYVY8_2X8/1920x1080] media-ctl -d /dev/media0 -V m00_b_mipi_dphy0:0[fmt:UYVY8_2X8/1920x1080] media-ctl -d /dev/media0 -V m00_b_csi2:0[fmt:UYVY8_2X8/1920x1080]这里有一个容易忽略的点RK3568 的 rkisp 输入格式和 xs9922b 输出的格式必须严格匹配否则会出现“链路建立成功但 video 节点无数据”的情况。xs9922b 输出 YUV422 的时候sink 侧要选 UYVY8_2X8 而不是 NV16 之类因为桥接芯片没有经过 ISP 的 debayer 处理输出本身就带色彩顺序ISP 侧要做的是把这种排列顺序直接透传而不是把它当成 Bayer raw 再插值。如果在 format 上不匹配RKISP 的采样器会直接丢掉数据表现就是 v4l2-ctl 里能设置格式但不报错实际一开流就卡住在 DQBUF 上。4. 实测过程中的问题与排查4.1 黑屏不是最可怕的花屏才是我调试期间遇到最多的问题不是完全没有数据而是“有数据但是图像不对”。做一个简单的记录现象根因处理方式I2C 探测不到设备地址不对或复位脚没有释放用 i2cdetect -y 扫描实际地址确认 reset 引脚电平状态MIPI 报 protocol errorDPHY 的 lane 数和芯片输出不一致核对>dmesg | grep -i mipi # [ 300.123456] csi2_dphy0: recovery done # [ 300.234567] csi2_dphy0: protocol error, lane 3出现 protocol error 时优先检查芯片 MIPI 配置里的 hssettle 参数。这个参数决定 D-PHY 接收端采样窗口的建立保持时间RK3568 的 DPHY 里有一个对应的寄存器字段一般从 0 到 15 可调值太小会采样到跳变沿上的毛刺值太大又会错过数据位。我这边最终调在 7 的位置比较稳定但这个值跟 PCB 走线长度、芯片类型都有关系不能照搬只能通过改写设备树里 dphy 节点的 hssettle 属性或者在内核里通过 debugfs 接口实时改来试。4.2 图像色彩问题一次典型的排障过程还有一次印象很深的是图像出来整体偏绿。当时我先怀疑是 ISP 的 AWB 在乱搞毕竟 AHD 模拟摄像头输出的色域和直接数字 sensor 不一样ISP 拿不到 sensor 的色温信息自动白平衡可能会跑飞到阴森绿。但关了 3A 之后问题依旧我这才把注意力转回 xs9922b 的输出格式上。这个芯片的 MIPI 输出在 YUV422 下有两种字节序一种是UYVY一种是YUYV另外还有 CSC 矩阵可配。RKISP 侧默认按 UYVY 解析但 9922 有些固件默认输出的是 YUYV 顺序这就导致 U 和 V 分量错位表现出来就是绿色满屏。最后在芯片寄存器里把输出格式从 YUYV 切到 UYVY或者反过来在 media-ctl 里把 sink 格式改成 VYUY图像就恢复正常了。这个问题在 TP2815、NVP6324 这类芯片上也一样常见建议调试时把格式切换当成第一排查项不要一开始就去折腾 ISP 的调色参数。5. 验证与收尾建议驱动和设备树全部就位后我习惯用最朴素的工具链验证先v4l2-ctl --list-formats-ext看格式再用media-ctl -p确认链路最后开 gstreamer 管线直接在屏幕上预览确认实时性和颜色都正常。v4l2-ctl -d /dev/video0 --set-fmt-videowidth1920,height1080,pixelformatUYVY v4l2-ctl -d /dev/video0 --stream-mmap --stream-count30 gst-launch-1.0 v4l2src device/dev/video0 ! video/x-raw,formatUYVY,width1920,height1080 ! videoconvert ! autovideosink通过这种集合方式验证过之后基本可以确认整个链条是通的。我把整套驱动源码和设备树整理放到了项目仓库基于 4.19 内核、Rockchip SDK 编译验证Linux 下直接 make menuconfig 打开对应的 I2C 设备驱动即可编入。最后再补充几个我在这次调通之后总结出的实操建议。第一xs9922b 这类桥接芯片的驱动在 RK3568 上其实没有太多玄学核心就是 I2C 能通、MIPI 格式能对齐、s_stream 的时序能对上。如果始终不出图先检查 I2C 和格式对齐这两层不要急着去动 ISP 的调参因为大概率问题在前面。第二设备树里 reset-gpios 和 pwdn-gpios 一定要根据实际硬件去确认特别是电源域有的板子是 3.3V 供芯片有的是 1.8V电平不匹配可能导致 I2C 能通但 MIPI 完全无输出。第三如果打算量产建议在驱动里把制式检测做成动态的不要写死 720P 或 1080P 单制式不然工厂产线上换摄像头批次之后很容易出现莫名其妙的图像异常。这个项目后续还可以扩展的方向很多比如把 AHD 四路同时接入 RK3568 的四个 DPHY做成四路环视或者在驱动里加上视频流诊断功能实时检测信号丢失和恢复事件方便做产品的故障上报。就目前这套驱动的基础框架而言改成其他 AHD 桥接芯片也只需要修改寄存器映射和格式配置这两个表框架本身完全具备复用价值。本文还有配套的精品资源点击获取