尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ov13850 MIPI RAW Sensor驱动调试:从设备树到60fps帧率实现

ov13850 MIPI RAW Sensor驱动调试:从设备树到60fps帧率实现 简介OV13850互补金属氧化物半导体图像传感器的驱动与配置代码包面向嵌入式与驱动开发人员用于解决传感器寄存器初始化、时序适配、分辨率与帧率切换、曝光与增益调节等实际问题。压缩包内为一个C源代码文件整体约12KB代码涵盖寄存器读写封装、移动行业处理器接口数据通路配置、曝光与增益控制逻辑以及每秒60帧模式下的时钟和通道设定可对照数据手册逐项核对。已有292人学习适合需要快速移植传感器驱动或优化成像质量的开发者。通过阅读该代码能掌握传感器上电初始化、原始数据输出、自动曝光与增益控制策略同时理解色彩空间、白平衡等后续处理思路为ISP调试、驱动二次开发提供参考也可作为CMOS驱动框架的学习范例。1. 从一个 rar 包看懂 ov13850 MIPI RAW Sensor 驱动在联发科平台上把 60fp 调出来拿到这个 rar 包的时候里面装着 ov13850_mipiraw_Sensor.rar、HPJ_OV13850.xml 以及配套的寄存器配置。做过 Sensor 驱动的人一眼就能看出来这是一整套摄像头驱动工程的交付物驱动源文件 ov13850_mipi_raw.c、设备树 dtsi 里的 sensor 节点、以及供 HAL 和 ISP 框架使用的 XML 描述文件。目标也很直接在 MTK 平台上让 ov13850 这颗 1300 万像素的 MIPI RAW 传感器跑出 60fps 的图像。ov13850 是 OmniVision 的 1/3.06 英寸 13M 像素传感器走 MIPI CSI-2 接口输出 RAW10 格式。区别于 YUV SensorRAW Sensor 内部不做 ISP所有降噪、坏点校正、色彩处理都在 SoC 端完成。这就意味着 SoC 端的 lane 数、数据速率、Bayer 格式解析必须全部对得上任何一环出错表现就是 probe 失败、黑屏、花屏或者颜色偏到没法看。这篇笔记适合 BSP 驱动工程师、Camera AE 工程师阅读也适合刚拿到 Sensor 包还不知道从哪个文件下手的新手。下面按“嵌入工程 → dtsi 节点 → 寄存器与帧率 → XML 解析 → 排错 → 验证”的顺序展开最后落到 60fps 到底怎么调出来、怎么验证。2. 把 rar 包落进工程ov13850 的 dtsi 节点、驱动结构与 probe 流程拿到包之后第一件事不是看代码是把文件放到对的位置。Sensor 驱动其实由三部分组成设备树里的节点、内核里的驱动源文件、上层 HAL 用的 XML 描述。三者各管一段任何一部分放错位置摄像头都点不亮。2.1 文件落位驱动、头文件、XML 分别放哪MTK 平台常见的内核目录是 kernel-4.19/drivers/misc/mediatek/imgsensor/src/common/v1_2不同 SoC 版本目录会有一点出入但结构大同小异。常见做法是先把 rar 包解压再把驱动改名为平台要求的规范格式放入 imgsensor 目录XML 文件则放进 HAL 层的 sensor 配置目录。# 解压后先看目录结构 unzip ov13850_mipiraw_Sensor.rar -d ov13850_pkg find ov13850_pkg -type f # 把驱动和头文件复制到内核算子目录 cp ov13850_pkg/ov13850_mipi_raw.c \ kernel-4.19/drivers/misc/mediatek/imgsensor/src/common/v1_2/ cp ov13850_pkg/ov13850_mipi_raw.h \ kernel-4.19/drivers/misc/mediatek/imgsensor/src/common/v1_2/ # XML 一般放进 HAL 层配置目录 cp ov13850_pkg/HPJ_OV13850.xml \ vendor/mediatek/proprietary/custom/mtXXXX/hal/imgsensor/驱动和头文件负责的是寄存器操作、分辨率切换、曝光与增益控制XML 负责告诉 HAL 和 ISP 这颗 Sensor 的物理尺寸、输出能力、裁剪窗口。如果 XML 没配编译能过、probe 也能过但拍照时取景范围、出图尺寸会是错的等到调效果时才发现就晚了。放完之后要确认 imgsensor 目录下的编译配置是否包含新驱动。这一步容易翻车因为各平台对驱动文件名的扫描方式不一致有的平台按厂商 ID 自动匹配有的必须手动改 Makefile。我的习惯是看目录里已有的 Sensor 是怎么注册的照抄一个最像的然后编译一次确认没有 undefined symbol。2.2 dtsi 里 sensor 节点的三个关键电源、reset、mclkdtsi 是设备树源文件摄像头相关节点一般在 arch/arm64/boot/dts/ 对应的平台 dtsi 里。以 MTK 平台为例会有 camera_main / camera_sub / camera_main_2 等节点ov13850 当主摄还是副摄决定改哪个节点。dtsi 节点配置直接决定硬件能不能正常上电启动其写法如下pio { camera_main_mclk_pins: camera_main_mclk_pins { pinmux PINMUX_GPIO0__MCLK; slew-rate 1; bias-disable; }; }; mtk_camera { camera_main: camera_main { compatible mediatek,camera_main; pinctrl-names default, mclk_on, mclk_off; pinctrl-0 camera_main_mclk_pins; pinctrl-1 camera_main_mclk_on; pinctrl-2 camera_main_mclk_off; reg-vdaf-supply mt6353_vcama1_reg; reset-gpio pio 14 0; }; };这里三个关键点电源、reset 引脚、MCLK。电源指 AVDD、DOVDD、DVDD 三路不同平台 regulator 名不一样但原理相同2.8V 模拟供电、1.8V IO 供电、1.2V 核心供电基本是这类 RAW Sensor 的三脚标配。reset 引脚注意默认电平OV 系 Sensor 一般是 RESET 拉低复位上电时序里要先拉低再拉高出图前保持高电平。MCLK 一般给 24MHz作为 Sensor 内部 PLL 的参考时钟。dtsi 里 MCLK 引脚配置如果和实际硬件不符就会出现“今天 probe 成功、明天 probe 失败”这种玄学问题根源往往是时钟树没配置好。我的排查习惯是改完 dtsi 后先看 log 里有没有 csi 时钟相关 error没有再继续往下走。2.3 probe 流程为什么读不到 sensor id 会翻车驱动里的 probe 流程一般长这样初始化 i2c 总线、申请 GPIO、拉起电源、给 MCLK、等待稳定、读 Sensor 的 ID 寄存器、比对驱动固化的 sensor_id。ov13850 的 ID 通常在 0x00 和 0x01 寄存器里读回来的值和驱动定义不一致Sensor 就被判定为不存在probe 直接失败。读 ID 失败的原因通常有三个第一是 i2c 地址不对OV 系列 Sensor 一般有多个地址可选驱动里 I2C 地址和硬件接法不一致ID 一定错第二是上电时序没等够reset 拉起来后要有毫秒级稳定时间太快去读就会失败第三是电源电压错误比如 DOVDD 给了 1.2VSensor 的 IO 部分根本没工作读出来全是 0xFF。常见做法是改驱动里的 probe 日志把期望 ID 和实际读到值都打出来。读回 0xFF 或 0x00 说明时序或 I2C 问题读到某个固定怪值说明数据线接错或地址选错。另外 MTK 平台后续还会用 sensor 的 tgt ID 和 CSI 通道做匹配驱动里的 csi 通道和 lane 数也要和 dtsi 一致否则 probe 过了但刷不出图更难受。3. 寄存器与 60fpsov13850 的 mode table 和 PLL 频率公式标题里的 60fp 是最让人兴奋也最容易理解错的部分。先说结论1300 万像素全尺寸输出时这颗 Sensor 通常只能跑 30fps 左右要跑到 60fps一般得把输出分辨率降到 1080P 或以下这并不丢人。60 帧意味着每帧只有约 16.6ms 的曝光时间预算对 AE 算法、SoC 端降噪、HDR 复合都提出了新的限制条件。3.1 帧率公式先把 PCLK 对齐再谈 60fpsSensor 的帧率不是拍脑袋配出来的而是由一组时钟参数算出来的。核心公式是 PCLK 除以每帧总像素数。每帧总像素数等于 HTS每行总长度乘 VTS每帧总行数其中 HTS 和 VTS 都能通过寄存器设置这就是帧率控制的基础。/* 帧率计算的基础公式所有 sensor 驱动通用 */ /* pclk mclk × PLL_multiplier / PLL_divider */ /* frame_rate pclk / (HTS × VTS) */ /* HTS 是每行总长度VTS 是每帧总行数单位都是 pixel clock 周期 */调整帧率最直接的办法是改 VTS。VTS 越大每帧总行数越多帧率越低VTS 越小帧率越高。但 VTS 不能无限小它必须大于等于该分辨率下垂直方向的有效行数否则图像底部会被截断或者出现滚动噪声。所以拿到一组 60fps 的寄存器值第一件事就是把 PCLK、HTS、VTS 代进公式验算一遍。如果算出来是 59.94 或 60.03说明这套设置在理论上是成立的。如果算出来只有 45fps说明驱动里只是把曝光行减半了并没有真正把帧率提上去。这种“假 60 帧”在 AE log 里表现为帧率在 45 到 60 之间跳很多人反复调参数都找不到原因结果是 mode table 里的 framelength 根本没改对。MIPI lane 速率也要和 PCLK 配合。RAW10 格式下单条 lane 的理论数据率约等于 PCLK 乘以 10 再除以 lane 数。lane 速率过高信号完整性崩掉画面出现竖条纹和随机噪点lane 速率过低数据传不过来取景掉帧。所以改帧率不是只改一组寄存器而是把 PCLK、lane 速率、平台端 csi 配置一起对。3.2 mode table 的结构与 60fps 的关键参数 HTS/VTS驱动里通常有一个 mode table按分辨率从高到低列出 mode每个 mode 包含该模式下的宽高、HTS、VTS、曝光行上下限。以常见的 1080P60 模式为例驱动代码大致长这样/* ov13850 驱动里 mode table 的一段典型结构 */ static const struct imgsensor_mode_info ov13850_mode_info[] { { .pclk 480000000, /* PCLK 480MHz */ .linelength 2688, /* HTS */ .framelength 1480, /* VTS决定帧率 */ .startx 0, /* 裁剪起点 */ .starty 0, .grabwindow_width 1920, /* 实际输出宽度 */ .grabwindow_height 1080, .max_framerate 600, /* 60.0fps */ }, { .pclk 480000000, .linelength 2688, .framelength 1908, /* 同样 PCLKVTS 放大到 30fps */ .grabwindow_width 4208, .grabwindow_height 3120, .max_framerate 300, }, };1080P 模式的 framelength 是 1480全尺寸模式是 1908PCLK 相同所以帧率不同。这就是通过 VTS 控制帧率的典型做法。但要注意从模式一到模式二是全尺寸输出不是简单裁剪sensor 内部的 crop 窗口起始地址、输出尺寸寄存器都要一起变不能只改 framelength。另一个容易被忽略的是曝光行限制。60fps 下 framelength 只有 1480AE 最大曝光行就只能到 1480 减去若干保留行。室内暗光时曝光时间不够要么补光要么调高增益这是 60fps 的天然代价。如果 AE 端曝光上限没有跟着 mode 切换出现画面过曝后无法收暗的现象那就是在尝试把曝光行写到超过 VTS 的位置。3.3 60fps 的代价binning、裁剪还是降曝光ov13850 要跑 60fps通常不是靠寄存器硬拉而是靠输出模式本身的取舍。第一个方向是 2x2 binning四像素合一把 13M 变成 3M 左右输出数据量降到四分之一帧率自然上去。第二个方向是裁剪输出只取 sensor 中间一块 1080P 区域视场角变窄但画面依然是中心区域全分辨率读出。第三个方向是全像素降曝光硬跑高帧率工程上很少用因为读出噪声和模拟增益在这种模式下会比较难看。实际驱动包里一般会把 binning 和裁剪两种模式都放出来XML 里对应多个 sensor mode。这时要注意binning 模式下的有效像素尺寸和全尺寸模式不一样SoC ISP 的坏点表、去马赛克参数都要跟着换。效果工程师调噪点和色彩时发现切模式之后画面突然变脏多半就是 ISP 参数没有跟随模式切换。60fps 还有一根暗线AE 的帧率信息。AE 进程一般从驱动上报的 max_framerate 来调度算法如果驱动在 1080P 模式上报的是 30fps 而不是 60fps即便寄存器真的跑到了 60fpsAE 还是按 30fps 的曝光策略走实际表现是忽亮忽暗、闪烁。所以 mode table 里的 max_framerate 字段必须和寄存器实际帧率一致这一点很多人验证完寄存器就忘了。4. HPJ_OV13850.xmlsensor 配置的“上层建筑”与 XML 解析内核驱动的寄存器配置只是下半部分上半部分是 HAL 和 ISP 用的 XML 描述。文件名里的 HPJ 通常是模组厂商代号OV13850 是 Sensor 型号。XML 做错了摄像头也能出图但出图尺寸、裁剪窗口、旋转方向、像素格式都是错的图像效果会差非常多。4.1 XML 里到底定义了哪些东西sensor id、尺寸、裁剪窗这类 XML 在不同平台之间结构会有差异但核心字段基本一致Sensor 名字和 ID、支持的分辨率列表、每个模式下的输出尺寸、裁剪窗口起始坐标、输出像素格式。典型结构如下sensor_config nameov13850_mipi_raw/name sensor_id0x1385/sensor_id mode_list mode width4208/width height3120/height crop_x0/crop_x crop_y0/crop_y bayer_formatBGGR/bayer_format max_framerate30/max_framerate /mode mode width1920/width height1080/height crop_x1144/crop_x crop_y1010/crop_y bayer_formatBGGR/bayer_format max_framerate60/max_framerate /mode /mode_list /sensor_configcrop_x 和 crop_y 是 sensor 全尺寸读出的起点偏移必须和驱动 mode table 里的 startx、starty 对应上。驱动裁剪起点是1144, 1010XML 里写成0, 0出来的图就歪了预览画面会偏到某一角。这种问题 log 里不一定有报错只有对比过输出图像才能发现所以交叉比对是少不了的。Bayer 格式字段更不能错。OV13850 输出 RAW 的 BGGR、GRBG、RGGB、GBRG 四种顺序在 ISP 里对应完全不同的颜色插值逻辑。格式写错颜色会变成奇怪的补色红旗变绿旗。这种问题经常被误判为 ISP 调不好颜色其实只是 XML 里一个字符串的事。4.2 怎么打开和编辑 xml从 vim 到 python 解析“xml文件怎么打开和编辑”是新手高频问题。这类 XML 就是纯文本用 vim、Notepad、VS Code 都能打开不需要专门工具。但直接手改容易改坏标签闭合后面解析时报错我一般用脚本检查一遍结构再提交到工程里。# 用 python 检查 sensor XML 的结构合法性 import xml.etree.ElementTree as ET xml_path HPJ_OV13850.xml tree ET.parse(xml_path) # 解析失败会抛异常适合快速检查 root tree.getroot() # 遍历每个 mode检查宽高和帧率是不是数值 for mode in root.findall(.//mode): w int(mode.findtext(width)) h int(mode.findtext(height)) fps int(mode.findtext(max_framerate)) print(fmode: {w}x{h}{fps}fps) # 检查裁剪起点是否有值 crop_x int(mode.findtext(crop_x)) crop_y int(mode.findtext(crop_y)) if crop_x 0 or crop_y 0: raise ValueError(crop 坐标不能为负)这个脚本用标准库解析 XML验证语法合法性把每个模式的宽高和帧率打印出来方便肉眼核对还对裁剪起点做了范围检查。跑完没有异常说明 XML 结构上没问题但不能保证逻辑正确还得和驱动 mode table 逐项对。日常维护中我习惯把 XML 和驱动里的 mode table 做一次交叉比对比对的维度是分辨率列表是否一致、每个模式的帧率是否一致、裁剪窗口是否一致、Bayer 顺序是否一致。四项全对上才算对齐。手工比对太累可以把上面的脚本扩展一下自动读驱动里的 mode table 做 diff效率高很多。4.3 解析失败和“orm 读取实体类的 xml 错误”之类的坑XML 解析报错最经典的有两类。一类是编码问题文件头声明的 encoding 和实际不一致比如文件用 UTF-8 保存却声明了 GBK解析到中文注释时直接崩。另一类是标签闭合问题多一个空格少一个斜杠解析器就在意想不到的地方报错。这些本质都是 XML 文本本身不合法表现方式和“orm 读取实体类的 xml 错误”很接近。排查时不要盯着第几行看先把文件丢给格式化工具。xmlstarlet 或 Python 的 ET.parse 会给出相对明确的错误位置。手边没有工具的话用 VSCode 打开也能看到标签高亮异常。有一种常见情况文件带着 BOM 头BOM 会导致解析器第一行报错解决方法是把文件另存为 UTF-8 without BOM。还有一个容易忽略的坑是注释里的特殊字符。比如注释里写了“--”就可能让解析器提前结束注释段后面的内容突然变成元素报错信息莫名其妙。这类问题肉眼很难看出来但报错行号一对照就能发现。我的习惯是驱动 XML 里尽量不写中文注释避免编码和特殊字符一起出问题。5. 避坑ov13850 MIPI RAW 调试中常见的翻车现场与排查方法驱动调试的坑很多这里挑真正高频、并且每一条都能直接照做的来说。每条按“现象 → 原因 → 解决”来写方便实际排查时对照抄作业。5.1 probe 失败读不到 sensor id现象log 里出现 sensor id mismatchprobe 直接失败Camera HAL 报 device open fail。原因大部分情况是 i2c 地址错误、电源时序不对或者 reset 引脚配置动作反了。OV13850 的 i2c 地址一般有多个可选项由硬件引脚电平决定驱动里写死的是预期地址硬件接法和预期不符时读出的 ID 就是错的。解决先查硬件原理图确认 sensor 的 i2c 地址选择引脚是高还是低。然后系统起来后用 i2c-tools 直接读 sensor 寄存器把读到的值和驱动里的 sensor_id 对比。读回 0xFF 说明 sensor 没起来回头查电源、时钟、reset读回非预期值改驱动里的地址或者硬件改线。5.2 花屏、偏色、暗电流RAW 格式和 lane 速率现象probe 成功取景有画面但画面撕裂、有条纹或者整体颜色完全不对偏绿偏红甚至出彩条。原因mipi lane 数不匹配、lane rate 不匹配、RAW 格式对齐出错。比如驱动里配置了 4 lane平台端 csi 只有 2 lane 在工作数据传不完整就会出现撕裂。颜色不对则要看 Bayer 格式sensor 输出的 bayer 排列和 ISP 端配置不一致出补色是必然的。解决先从驱动里 lane 相关寄存器开始查把 lane 数和平台端 csi 配置调成一致。再看 RAW 是 RAW10 还是 RAW8MIPI 数据位宽对不上也是花屏源。最后把 ISP 端 bayer 顺序换一下试通常改一个寄存器就能验证是不是这个问题不需要整个工程重编。5.3 60fps 掉帧VTS 和 AE 曝光在抢参数现象标称 60fps 的模式预览实际只有 40 到 50 帧AE log 里曝光行经常撞到 VTS 上限。原因AE 的曝光行上限没有跟随 60fps 模式调整。驱动 mode table 的 framelength 是 1480AE 最大曝光行还按 30fps 模式的 1908 来曝光行超过 VTS 时 sensor 输出帧率会被曝光时间钳住掉回 30fps。解决把 AE 最大曝光行设成 framelength 的 80% 左右或者直接检查驱动上报的 max_framerate确保 60fps 模式下 AE 内部知道这是高速模式。另一种常见做法是加专门的 60fps 曝光表让 AE 切换模式时自动加载对应曝光限制而不是沿用默认表。5.4 XML 里的尺寸和驱动 mode table 对不上现象拍照尺寸正常但预览视场角偏小或者拍照和预览的画面范围明显不一致。原因XML 里的裁剪窗口和驱动 mode table 裁剪参数不统一。常见情况是驱动里改成裁剪到 1080PXML 还写着全尺寸的起始坐标上层拿到的图像位置偏了。解决回到 4.2 的交叉比对思路把 XML 的 crop_x/crop_y 和驱动 mode table 的 startx/starty 一一对应。不确定哪个对就先用 sensor 输出一张全尺寸 raw 图从 raw 图中心位置反推裁剪窗口的真实坐标再回头改 XML。5.5 点不亮时先查上电时序而不是代码逻辑现象寄存器配置看着没错probe 却时好时坏或者换一台机器就完全起不来。原因上电时序不满足 sensor 手册要求。OV13850 这类 RAW sensor 对 AVDD、DOVDD、DVDD 的上电顺序有要求reset 释放时机也有窗口。驱动里 reset 释放太早sensor 内部 LDO 没稳定就会出现概率性启动失败。解决对照手册确认上电顺序和时序参数在驱动里加 msleep 或 usleep 等待。调试阶段可以把逻辑分析仪挂在电源和 reset 引脚上看实际波形确认延迟足够后再从软件层面优化。这个坑最容易让人怀疑代码逻辑其实根源在硬件时序。6. 验证与进阶点亮之后的 raw 图像检查与 60fp 的压测习惯点亮只算完成一半。验证阶段我的固定动作是三件事拍 raw 图验颜色、看 AE log 验帧率、最后跑一小时的稳定性测试。拍 raw 图验颜色把 raw 数据用工具转成可预览的 bmp 或 png看灰阶卡和色卡是否正常顺便检查有没有明显坏点和竖纹。这一步能验证 Bayer 顺序对不对也能验证 lane rate 是否稳定。只有个别像素异常多半是 sensor 坏点需要靠 ISP 坏点表补偿如果是整片区域花掉回头查 mipi lane 速率和时钟。raw 图还有一个用途确认裁剪窗口坐标。全尺寸 raw 图拍一张看画面中心对应 sensor 的哪个位置就能反推 XML 里的 crop_x/crop_y 填得对不对。看 AE log 验帧率需要抓 sensor 的 framelength 和曝光行两个字段算实际帧率有没有到 60。用平台自带的 camera log 工具抓就行关键是看数值是不是稳定在 60 附近。有跳变说明 AE 模式和寄存器没配合好回到 5.3 排掉。这里要注意一个细节60fps 模式下曝光行占用率通常只有 70% 左右如果看到曝光行已经顶到 1400 行说明现场光线太暗AE 正在极限拉伸帧率随时可能掉下去。稳定性测试别偷懒。60 帧模式连续跑至少一小时重点观察三个指标温度起来后帧率是否下降、画面是否出现噪点暴增、probe 是否偶发失败。这类问题往往在十几分钟不出现半小时后才暴露。第一次交付 60fp 方案时就是热机后帧率从 60 掉到 55查了一个下午才发现是电源纹波偏大导致 lane rate 不稳定这种场景只有长时间跑才能复现出来。进阶方向方面内核驱动稳定之后可以尝试两个方向一个是动态帧率切换让 30fps 和 60fps 模式按场景自动切换另一个是 HDR 多帧输出60fps 模式下做短长曝光合成。两个方向都依赖寄存器、XML、AE 三者配合底层基础扎实了后面无非是再加几组 mode 的问题。调 ov13850 这几年最大的教训是每次改完寄存器先验算一遍帧率公式再编译。寄存器数组一长人眼很难看出哪一行改错但公式一算PCLK、HTS、VTS 三者不协调立即现形。这个习惯帮我躲过了很多次反复编译的循环也希望帮到你。本文还有配套的精品资源点击获取
返回列表