
拿到一块带RK3588的开发板想驱动一枚OV13855摄像头第一件事不是马上敲代码而是把MIPI摄像头驱动的链路完整拆开看一遍。这篇文章的起点就是手头这块香橙派5RK3588以及插在MIPI CSI接口上的OV13855模组。这里说的驱动并不只是某几个文件而是一整套从sensor寄存器到内核视频设备的完整通路。我会从硬件链路讲起再讲设备树、内核驱动、调试命令和常见坑最后给出可直接落地的操作步骤。适合正在搞RK3588平台摄像头移植、或者刚接触Linux下MIPI传感器的读者参考。很多人一上来就盯着OV13855驱动源文件结果改了寄存器表还是不出图问题往往出在更上游的CSI2 D-PHY配置、电源时序或者media controller link没建立。所以这篇文章的目标很简单让你清楚RK3588平台上MIPI摄像头驱动到底是怎么工作的OV13855在香橙派5上应该怎么接、怎么配、怎么调以及遇到黑屏、花屏、绿屏时从哪下手。1.1 MIPI CSI-2与D-PHY摄像头驱动绕不开的底层协议MIPI摄像头链路物理层叫D-PHY协议层叫CSI-2。你可以把D-PHY理解成一条多车道的高速公路OV13855通过差分信号对把图像数据传到RK3588每个lane其实是一对差分线。RK3588平台上sensor一般用4条数据lane加上1条时钟lane每个lane都工作在高速脉冲模式下。摄像头驱动要做的第一件事就是让RK3588的PHY和OV13855的PHY进入同一套协议节奏先上电再给时钟等sensor稳定然后启动MIPI发射。这个顺序如果错了后面全乱。CSI-2协议规定了数据包头、帧起始、行包结束和虚拟通道。OV13855输出的RAW数据会按行打包每个包里有数据标识、像素数据和校验码。RK3588一侧的摄像头接口需要根据sensor输出的lane数、data type、RAW bit depth来解析这些包。驱动代码里常常看到的“MIPI data type”就是用来告诉接收端每个包里的数据是RAW10、RAW8还是YUV422。所以你在OV13855驱动里看到的不是简单的图像尺寸而是格式、lane数和MIPI交通规则这几样东西。还有一个容易被忽略的是D-PHY的时钟频率。MIPI数据流不是凭空跑的它必须依据时钟lane的差分信号来采样。OV13855在13M全分辨率下需要的吞吐量决定了时钟频率如果设备树里给的mclk不对或者摄像头供电电压纹波太大D-PHY会直接失锁现象就是stream on成功但一帧数据也拿不到。1.2 OV13855与RK3588如何匹配分辨率、RAW格式与lane数OV13855是一颗常见的13MP CMOS图像传感器标称4224x3136输出RAW10 Bayer模式。RK3588内置ISP同时也有一路独立的CIF采集控制器。OV13855的raw输出可以通过CSI-2直接进RK3588的ISP再由ISP输出线性化的Bayer图像也可以在不需要ISP处理时直接让CIF采集。驱动层通常会把sensor注册为v4l2 subdevISP或者VICAP注册为video设备两边通过media controller连接。这样做的意义是sensor只管按时输出数据RK3588的ISP再根据场景做曝光、增益和噪声处理。OV13855模组在香橙派5上的接口一般走4条lane。4 lane的理论吞吐能力远高于13M30fps RAW10的需求但实际还要看D-PHY档位和时钟约束。更关键的是ov13855的驱动会把“当前使用几lane、RAW是10bit还是10bit压缩到8bit”写进寄存器。RK3588接收端则必须和sensor约定一致否则PHY可能在数据包边界上错位导致图像出现斜纹或撕裂。开发板上的摄像头模组还涉及FPC排线、供电和I2C地址。OV13855的I2C地址通常可以通过模组上的地址电阻配成0x36或0x37香橙派5官方的摄像头底板一般会给出固定配置。如果你用的是第三方模组第一件事就是确认地址否则后面写设备树全是白费力气。2. 摄像头驱动的代码骨架sensor驱动、设备树、ISP与media controller缺一不可真正意义上的MIPI摄像头驱动不是一个文件而是一层一层的组合。最底层是sensor驱动它负责I2C读写寄存器中间层是设备树它告诉内核硬件怎么连接上层是RK3588的ISP和CIF驱动它们负责接收数据并输出给用户态。只有把这三层同时理顺v4l2-ctl才能抓到图。2.1 ov13855 sensor驱动寄存器表与subdev回调在Linux内核里ov13855驱动通常以ov13855.c的形式编译。它的核心工作可以分成三块第一通过I2C读取Sensor ID来确认设备存在第二把一组初始化寄存器写入sensor配置曝光、增益、帧率、lane数和数据格式第三向Linux V4L2框架注册subdev操作集包括s_power、s_stream、get/set_fmt这些标准回调。你去看ov13855.c源码时会看到一大片纵向排列的寄存器数组挺吓人其实结构很简单每一行都是“寄存器地址值”。比如0x0103写成0x10, 0x03这是software reset0x0100写0x00是stream off写0x01是stream on。驱动里s_stream函数会被上层调用它先根据用户选择的分辨率设置mode再执行寄存器表最后通过0x0100寄存器打开MIPI输出。这个动作看似简单却是调试中问题最多的地方。sensor驱动还有一个隐蔽角色它必须在打开电源后等待sensor稳定。OV13855的驱动通过msleep实现上电延时如果延时太短sensor内部PLL可能还没锁定I2C读取ID就会失败。很多黑屏问题不是I2C不通而是reset释放后给的时间不够。此时你在dmesg里会看到“ov13855 identify failed”之类报错。2.2 设备树把引脚、电源、时钟和pipeline都串起来设备树在这里是把OV13855“焊”到RK3588平台上的蓝图。一个典型节点包含compatible、reg、reset-gpios、pwdn-gpios、clocks、avdd-supply、dovdd-supply等属性。compatible必须和驱动里的of_device_id完全匹配通常是ovti,ov13855。reg就是I2C地址。reset和pwdn两个GPIO控制着sensor的硬件逻辑pwdn是高还是低reset是高还是低不同模组不一致必须以官方底板原理图为准。时钟部分OV13855需要一颗MCLK一般在24MHz左右。RK3588的CRU可以提供这个时钟通过设备树的clocks和assigned-clock-rates属性配置。如果MCLK没配好sensor的PLL不会工作i2cdetect照样能看到设备地址但stream on后不会出帧。这是最典型的“看起来活着其实没干活”的坑。设备树中更关键的是port连接关系。一个sensor端口要连到CSI2 D-PHY portD-PHY另一头再连到RK3588的camera controller。这样media controller才能知道数据往哪儿走。在部分RK3588 SDK设备树里sensor节点下有 port { ov13855_out: endpoint { remote-endpoint mipi_dphy0_input; }; }; 然后D-PHY节点里有对应endpoint指回来。只要这个link断掉内核就不会把sensor注册到media0拓扑里v4l2-ctl --list-devices里可能看不到完整链路。2.3 media controller拓扑link谁和谁的关系V4L2的media controller设计思路是把每个硬件单元当成一个实体实体之间有link。sensor是第一个实体MIPI D-PHY是第二个ISP或CIF是第三个最终video device是第四个。调试时你经常用media-ctl来查看和配置这些实体链接命令是media-ctl -p -d /dev/media0。在RK3588平台上sensor驱动成功probe后你会在media拓扑里看到一个ov13855 entity。它下面会列出pad 0对应sensor输出端。如果sensor和D-PHY之间的link是红色禁止状态说明驱动加载顺序或者设备树端口没配对。此时需要手动用media-ctl修复 media-ctl -d /dev/media0 -l ov13855 0-0036:0 - csi2 dphy0:0 [1] 后面的[1]表示enable link。这招在调试时很管用因为有时驱动probe成功了link却因为固件默认配置没有自动使能。了解media controller可以帮你少走很多弯路。3. 在RK3588开发板上把OV13855跑起来一步步实操这一节完全按我自己在RK3588平台上调OV13855的实际顺序来写。环境是香橙派5这一类RK3588开发板系统内核基于Rockchip SDK预先已经编好了大多数摄像头相关驱动。如果你的内核是自己裁剪过的可能需要先补配置项。3.1 接线、GPIO与电源确认先把开发板断电把OV13855摄像头模组通过FPC排线连接到板子的CSI接口。这里要特别提醒FPC排线的金手指方向非常容易插反很多第一次上手的朋友烧过I2C引脚。插好之后先别上电用万用表测量模组供电脚的导通关系确认没有短路。官方套餐通常不会接错第三方模组则一定要核对针脚定义。上电后先不进系统直接测量OV13855电源轨有没有输出。常见是AVDD 2.8V、DOVDD 1.8V、DVDD 1.2V。部分模组还带AF落VCM供电如果拍照对焦模组没买那一路可以不接。别小看电源测量摄像头驱动报“failed to get supply”一半是设备树没写另一多半真的是硬件上电没到位。接下来进入系统先用i2cdetect扫描sensor所在的I2C总线。不知道总线号也没关系可以用i2cdetect -l列出所有总线然后逐个scan看到0x36或者0x37有地址出现说明I2C连接基本OK。如果scan不到地址优先检查PWDN引脚和RESET引脚因为PWDN拉高了sensor会进入低功耗模式I2C不响应。3.2 内核配置与编译设备树RK3588 SDK默认内核里摄像头相关驱动通常以modules方式或built-in方式存在。你需要确认几个关键配置CONFIG_VIDEO_OV13855、CONFIG_VIDEO_ROCKCHIP_CIF、CONFIG_VIDEO_ROCKCHIP_ISP。CIF是capture接口ISP是图像信号处理单元。OV13855驱动可以编为模块但调试时建议直接编译进内核否则会出现sensor subdev和ISP驱动加载顺序问题。要修改设备树时不要直接改大而全的rk3588-evb.dts建议在板级dts的根节点里追加ov13855节点或者使用dts overlay。香橙派5这类板子一般支持overlay可以编译出dtbo文件再通过启动参数加载。不过最稳妥还是改板级dts后重新编译boot.img。以常见RK3588 SDK为例编译设备树的命令大概是 make ARCHarm64 rockchip_linux_defconfig make ARCHarm64 dtbs 编译完成后会在arch/arm64/boot/dts/rockchip下生成对应dtb。你可以把dtb打包进boot分区也可以单独替换。如果内核版本支持overlay那就在overlay目录下加一个ov13855 overlay文件用fdtoverlay编译调试时可以热加载省去反复刷boot的麻烦。3.3 启动后验证驱动加载和拓扑是否正常把新内核启动到系统后第一步看dmesg。执行dmesg | grep ov13855正常情况下会看到ov13855 probe success、I2C communication okay等信息。如果没有说明设备树节点或者驱动compatible没匹配。接着查看/dev目录下有没有video设备ls /dev/video*。RK3588平台通常会有多个videoN其中RK ISP或者CIF会各占一个。然后执行media-ctl -p -d /dev/media0重点看拓扑里有没有ov13855。如果ov13855已经出现在实体列表里再查看它的输出pad有没有link到csi2 dphy。默认拓扑正常的话你还可以用media-ctl --print-dot转换成graphviz图直观一点。这一步里最容易出的问题是“sensor驱动加载了但media实体不存在”。原因多数是设备树里port节点写得不完整导致驱动虽然probe成功但没有注册完整的v4l2 subdev graph。此时回到设备树确认ov13855节点下面确实有port、endpoint和remote-endpoint。3.4 用v4l2-ctl抓一帧图确认图像数据流打通拓扑确认无误后可以用v4l2-ctl直接抓帧。先列出设备能力和格式 v4l2-ctl -d /dev/video5 --list-formats-ext 这里的video5只是一个代称具体要用实际设备号。RK3588 ISP输出因linux驱动版本不同可能是YUV或RAWOV13855走的是Bayer原始数据。如果v4l2-ctl能列出4224x3136、SRGGB10等格式说明sensor的get_fmt已经打通。设置格式并抓一张图 v4l2-ctl -d /dev/video5 --set-fmt-videowidth4224,height3136,pixelformatRG10 v4l2-ctl -d /dev/video5 --stream-mmap --stream-count1 --stream-toframe.raw 命令里的RG10是V4L2常用的RAW Bayer 10bit像素格式名。抓下来的raw文件没有图像头需要用支持raw Bayer的工具查看。如果抓到的是全黑或全绿说明Bayer顺序没配好。4. 调试实录驱动不出图时按这个顺序排查调试MIPI摄像头驱动最高频的问题就是“stream on之后卡住或者抓到全黑”。我把实际经验整理成了五个排查阶段下面的顺序是我每次调新模组都会走一遍的路径照着做能节省不少时间。4.1 先看硬件环境再谈代码遇到不出图先别改代码。我见过很多次是因为CSI接口的FPC排线松了、摄像头没插到底。你可以轻压排线重新上电再跑一遍i2cdetect。硬件排查的基本原则I2C能识别不保证MIPI能出数据但I2C识别不到一定可以先查电源、时钟、复位和地址。如果I2C能识别但stream on失败要看sensor的pwdn和resetGPIO是不是被复用成其他功能。RK3588的GPIO功能复用很灵活同一个引脚可能被I2C、UART或者PWM占用。设备树里一旦配置冲突GPIO可能拉不对状态sensor就一直被复位。此时打开设备树找pinctrl-0确认mclk、pwdn、reset相关引脚没有被其他模块引用。4.2 通过dmesg定位v4l2_subdev_call失败点当stream on失败时内核日志会给出不少线索。执行dmesg | tail -100关注以下关键词ov13855、csi2 dphy、rkisp、rkcif、mipi、PHY。最常见的错误有两类一类是“failed to enable sensor power”问题在supply获取失败另一类是“stream start failed”问题在sensor寄存器序列执行失败或者PHY没有启动。如果日志里出现“sensor not found”或“identify failed”多半是地址错误、复位脚没有拉起来或者MCLK没有输出。用示波器量一下sensor的MCLK引脚比较直接频率应该在24MHz附近且有稳定幅度。没有示波器就打开debugfs或者读CRU寄存器查看CLK_MIPI_CAMERAOUT是否被使能。4.3 用i2ctransfer和寄存器读回定位sensor状态i2cdetect只能看到I2C地址真正要确认sensor处于正常模式还需要读寄存器。OV13855的芯片ID一般放在0x3000附近可以用i2ctransfer直接读 i2ctransfer -f -y 0 w20x36 0x30 0x00 r2 这条命令表示往I2C总线0上的0x36设备先写两个字节寄存器地址0x3000再读两个字节。如果读回的值和驱动里chip_id不一致说明地址不对、sensor没上电或者寄存器映射不同。这里的总线号和地址要按实际情况改。如果ID正确再读0x0100看stream状态。0x0100为0x00时stream off0x01时stream on。调试时可以直接写0x00再写0x01观察dmesg里有没有MIPI error。还可以读0x0103如果一直是0xff说明sensor可能在复位状态或者I2C总线有问题。4.4 花屏、偏色、帧率低的针对性排查花屏分好几种。如果是斜条纹、一行行错位多半是MIPI lane数配置不匹配。OV13855驱动里寄存器配置为4 lane但PHY或者DTS里只接了2 laneRK3588接收到的数据就不完整。这时候要检查sensor驱动里的mipi_lane_num。偏色和绿屏问题通常在Bayer顺序。OV13855输出的Bayer pattern有GBRG、GRBG等变体RK3588 ISP端要根据sensor的CFA pattern做处理。如果颜色整体偏紫或者整幅图发绿试着把media-ctl里的Bayer order换一个值。还有一种常见问题RAW10数据被当成RAW8解析图像会明显变暗、细节丢失要检查像素格式是不是RG10。帧率上不去的问题先别怀疑主控性能。用v4l2-ctl --get-fmt看一下当前的分辨率再算一下RAW10的数据量。如果分辨率设置到了4224x313630fpsMIPI时钟却不够帧率会掉到24或者更低。调整方法往往不是把MIPI clock硬拉高而是通过修改sensor寄存器里的vblank、hblank来改变帧率。还有一点如果在同一组MIPI通道上接了多路sensor需要看CSI2虚拟通道和数据仲裁是否合理。5. MIPI摄像头驱动调试的个人经验与建议我调试MIPI摄像头驱动时吃过最大的亏是“贪快”设备树、内核、驱动源码一次性改好几个地方结果出了问题完全不知道从哪里查起。后来养成一个习惯每次只改一个变量验证一个变量。比如先单独验证I2C通信再验证stream on再验证图像格式每一步都要有中间结论。这个习惯救了我很多次。另一个很实用的小技巧是在第一次加载sensor驱动前先用系统抓一份完整的“正常启动dmesg”然后加载驱动后再抓一份。两个日志做对比任何多出来的报错都是线索。很多内核驱动在调试时会输出大量debug信息默认level打不出来别急着加printk先打开动态调试echo file ov13855.c p /sys/kernel/debug/dynamic_debug/control。这样可以拿到寄存器读写日志不用反复编译内核。还有一个关于设备树的建议不要把陌生模组的DT节点直接复制到一个新板子上。哪怕引脚看起来一样也要逐个确认power supply名称、GPIO active level和MCLK频率。RK3588平台电源域比较多某个supply如果设备树里没定义驱动probe时不会立刻报错直到stream on时才告诉你“regulator not found”。这种问题最难查最好一开始就对着原理图把设备树属性写全。如果你想把这套流程延伸到其他RK3588开发板只需要关注两点sensor的供电和GPIO定义是否一致以及MIPI D-PHY连接到的camera controller编号。其余部分比如ISP配置、media controller拓扑和调试命令都能复用。就调试方法而言OV13855只是MIPI摄像头驱动的一个代表换一颗sensor套路几乎不变。