
1. 项目背景与整体思路RV1106 这条视觉链路要打通什么RV1106 是瑞芯微在低功耗视觉领域里很典型的一颗芯片单核 Cortex-A7、自带 0.5TOPS NPU最关键的是内置完整 ISP配合 MIPI CSI 做摄像头输入MIPI DSI 或 LVDS 做显示输出一颗芯片就能撑起“摄像头 屏幕 AI 识别”的终端产品形态。我这次项目要干的活就是把这条链路完整打通硬件上把 sensor 接进 MIPI 接口把屏幕接上 LVDS 接口软件上把设备树里的 ISP、CSI、VOP、LVDS 节点全部配好最后让系统稳定出图、屏幕正常点亮、图像效果过关。这篇文章适合正在做嵌入式视觉产品的人看尤其是刚拿到 RV1106 开发板、需要自己接一颗摄像头 sensor 或点一块 LVDS 屏幕的工程师。前提是你最好有点 Linux 驱动开发基础知道设备树是干嘛的会敲命令行能用示波器看差分信号不然硬件排查那段会比较吃力。当然如果你只是想知道 ISP pipeline 大概怎么回事、MIPI 和 LVDS 的时序怎么算也能从里面挑着看。1.1 为什么是 MIPI 进、LVDS 出接口选型的实际考量先说结论MIPI 和 LVDS 本质上是两种不同定位的接口MIPI CSI 用于摄像头输入LVDS 用于显示输出这几乎是 RV1106 这类视觉芯片最常见的组合方式。MIPI CSI 的优势是 Lane 数可配置、带宽高、引脚少一颗 1080p 的 sensor 用 2 根数据 Lane 就够跑对 PCB 面积和走线要求都比较友好而 LVDS 在工业屏、车载屏里存量极大很多 7 寸、10 寸的 LCD 模组天生就是 LVDS 接口直接用芯片的 LVDS 控制器就能点亮不需要额外加转换芯片。这里有一个容易被忽略的点很多人以为 MIPI 和 LVDS 是同一个东西毕竟都是差分信号、都有时钟和数据线。实际上两者的电气规范完全不同MIPI D-PHY 是 1.2V 左右的共模电压LVDS 也是共模 1.2V 左右、在接收端需要 100 欧姆终端电阻但 MIPI 的每个 Lane 是 8b10b 或类似编码方式承载字节流LVDS 则是固定的 7:1 串行化数据线宽度由色彩深度决定。如果搞混硬件上很可能会出现信号电平不匹配、屏幕花屏之类的诡异问题所以选型阶段就得想清楚。1.2 整体方案和开发环境我这次用的方案是 RV1106 一颗 200 万像素的 sensor走 MIPI CSI2 Lane加上一块 1024x600 的 LVDS 工业屏系统基于 Buildroot 裁剪的 Linux。整个软件栈包括内核驱动、设备树、以及瑞芯微的 RKAIQ 调优工具。SDK 里默认的 dts 一般只覆盖了官方评估板的配置换成自己的 sensor 和屏幕时几乎必然要改设备树这也是我写这篇文章的初衷把从硬件连线到设备树配置的完整过程记录下来免得后来人重复踩坑。开发环境方面我建议直接用 SDK 自带的交叉编译工具链先把默认配置编一遍确认能正常启动再动手改设备树。这样能避免“改了代码不知道是编译问题还是配置问题”的尴尬局面。下面所有 dts 片段都是我根据 SDK 里常见节点结构整理的具体节点名和文件路径不同内核版本会有差异但思路是通用的。2. ISP pipeline 拆解从 Bayer 到 YUV 到底经过了多少道工序开始配置之前我得先把 ISP 这条流水线讲明白因为很多人改完设备树发现能出图了但图像偏色、有坏点、暗角严重这些问题其实都不是设备树能直接解决的而是 ISP 参数没有调好。ISP 全称 Image Signal Processor它的输入是 sensor 直接吐出来的 RAW 数据也就是 Bayer 格式每个像素只有 R、G、B 其中一个分量后续所有处理都围绕怎么把这堆原始数据变成人眼看着正常的 YUV 或 RGB 图像。2.1 ISP pipeline 里那些核心模块在干什么常见的 ISP pipeline 大致是这样一条链黑电平校正BLC→ 镜头阴影校正LSC→ 坏点矫正DPC→ 去马赛克Demosaic→ 颜色校正CCM→ Gamma 校正 → 降噪NR→ 3A 统计。你可能听过“去马赛克”这个词它就是把 Bayer 格式每个像素缺失的两个颜色分量插值补全这是 ISP 最基础也最关键的步骤之一。坏点矫正则是把 sensor 上固定的死点、亮点找出来用附近像素替换掉不处理的话画面里会有星星点点的白点或黑点特别影响观感。这些模块里面BLC 和 DPC 属于“sensor 本身缺陷”相关的处理LSC 和 CCM 属于“镜头和色彩”相关的处理NR 和 3A 则直接影响最终画质。RV1106 的 ISP 把这一整套都固化在硬件里了软件要做的就是初始化寄存器、配置各模块的系数表以及让 3A 算法能够拿到统计信息去控制曝光增益。理解这条链路的顺序很重要因为前面的模块算错了后面再怎么调也救不回来。2.2 ISP 调试到底在调什么不是玄学是系数和曲线很多人一听到 ISP 调试就觉得是玄学其实核心就三件事一是确认 pipeline 里每个模块的开关状态和参数是否正确二是看 3A自动曝光、自动白平衡是否收敛三是针对具体场景做 tuning。瑞芯微的 RKAIQ 工具就是干这个的它通过采集不同光照条件下的 raw 图生成一组校准系数最后集成到系统里。比如自动白平衡它的原理是假设画面里的白色物体在 R、G、B 三个通道的响应应该相等通过统计每一帧图像各通道的平均值反过来推算当前光源下需要的 R/G 和 B/G 增益。如果你发现画面偏黄或偏蓝很多时候不是白平衡没跑起来而是前期 LSC 校正没做四周的色偏影响了统计结果。我当时的做法是先关掉 3A用固定曝光和固定增益拍一张标准色卡的 raw 图一级一级排查问题出在哪个模块这样比盲目调参高效得多。2.3 为什么 ISP 配置和硬件连接息息相关这里要特别强调一个容易忽略的点ISP 需要知道 sensor 输出的是什么格式、多少位深、什么时序这些信息一部分来自设备树里的 remote-endpoint 和># 以 RV1106 一侧为例具体引脚号以芯片手册为准 MIPI_CLK_P --- sensor CLK_P MIPI_CLK_N --- sensor CLK_N MIPI_D0_P --- sensor DATA0_P MIPI_D0_N --- sensor DATA0_N MIPI_D1_P --- sensor DATA1_P MIPI_D1_N --- sensor DATA1_N这里有个实操细节sensor 的输出数据和 MIPI 主控的输入数据要按 Lane 序号一一对应不能交叉接。另外MIPI 的时钟 Lane 在 HS高速模式下是一个持续的差分时钟数据 Lane 在 HS 模式下随时钟同步传输因此示波器测试时应该先测时钟 Lane时钟有、数据没有问题一般出在 sensor 驱动或 Lane 配置时钟都没有大概率是 sensor 上电时序或时钟配置不对。3.2 一步一算确定 MIPI 的 Lane 数和数据速率很多人直接抄 SDK 里的>i2c2 { status okay; sensor0: sensor30 { compatible vendor,sensor-model; reg 0x30; clocks cru CLK_MIPICSI_OUT; clock-names xvclk; pinctrl-names default; pinctrl-0 mipicsi_clk0; reset-gpios gpio2 RK_PB5 GPIO_ACTIVE_LOW; pwdn-gpios gpio2 RK_PB6 GPIO_ACTIVE_HIGH; rockchip,camera-module-index 0; rockchip,camera-module-facing back; rockchip,camera-module-name default; rockchip,camera-module-lens-name default; port { sensor0_out: endpoint { remote-endpoint mipi_in_sensor0; >csi2_dphy { status okay; ports { #address-cells 1; #size-cells 0; port0 { reg 0; mipi_in_sensor0: endpoint { remote-endpoint sensor0_out; >lvds { status okay; ports { #address-cells 1; #size-cells 0; port0 { reg 0; lvds_in_vop: endpoint { remote-endpoint vop_out_lvds; }; }; port1 { reg 1; lvds_out_panel: endpoint { remote-endpoint panel_in_lvds; }; }; }; }; panel { status okay; compatible simple-panel; power-supply vcc3v3_lcd; enable-gpios gpio0 RK_PC3 GPIO_ACTIVE_HIGH; backlight backlight; panel-timing { clock-frequency 51200000; hactive 1024; vactive 600; hback-porch 160; hfront-porch 160; hsync-len 20; vback-porch 20; vfront-porch 15; vsync-len 5; }; port { panel_in_lvds: endpoint { remote-endpoint lvds_out_panel; }; }; }; backlight { status okay; pwms pwm2 0 1000000 0; brightness-levels 0 255; default-brightness-level 128; };panel-timing 里 clock-frequency 是像素时钟它和实际分辨率、刷新率的关系是clock-frequency 约等于 hactive 加上各种 porch 和 sync 宽度再乘以 vactive 加上垂直方向上的各种宽度最后乘以帧率。1024x60060 算下来大概 51MHz 左右。如果这个值差太多屏幕要么不同步要么刷新率不对。设备树里配置完成后重点检查内核日志有没有报“failed to find panel”或者“failed to get display mode”之类的错误。5.4 设备树优化不要什么都往一个文件里塞SDK 默认的设备树文件可能包含了很多评估板的外设实际量产时应该把用不到的节点 status 设为 disabled比如把不需要的 I2C、SPI、UART 全部关掉一方面减少内核初始化时间另一方面避免引脚冲突。我在调试时曾经因为某个节点的 pinctrl 和 sensor 的 GPIO 冲突导致 GPIO 被复用成别的功能折腾了很久才发现是设备树里一个不起眼的节点抢了引脚。建议把 sensor、屏幕、背光这些外设单独拆成 dtsi 文件用宏控制是否参与编译这样代码更清晰也方便后续换屏换 sensor。版本管理上每次改动前先备份一份可用的 dts因为设备树改动对启动失败的影响非常直接改错了连系统都起不来到时候只能通过串口和 tftp 恢复代价很高。6. 调试实录从完全没图到稳定出图的过程设备树配好只是一个开始真正花时间的是调试阶段。我把这次项目里遇到的问题按现象、原因、排查方法整理成了一份速查表下面挑几个典型场景展开讲。现象可能原因排查方法sensor 在 i2cdetect 里找不到地址错误、上电时序不对、复位引脚极性反了用示波器测电源和 MCLK确认 reset/pwdn 电平i2c 正常但 MIPI 无数据Lane 数配置不一致、时钟 Lane 虚焊、端接电阻异常示波器测 CLK_P/CLK_N先确认有 HS 时钟输出能出图但画面花>