尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

STM32MP23x四路摄像头采集方案:基于CSI-2虚拟通道与DCMIPP实现

STM32MP23x四路摄像头采集方案:基于CSI-2虚拟通道与DCMIPP实现 1. 方案选型与整体设计拆解1.1 为什么“四路摄像头”在工业场景里是刚需先说清楚一个现实单目视觉在不少场景里已经不够用了。我做嵌入式视觉这几年遇到最多的需求不是“能不能接摄像头”而是“能不能同时接好几路摄像头并且每一路都能独立出图”。比如AGV机器人需要前视、后视、左右避障四路感知工业质检工位需要从四个角度拍摄同一个工件或者一台医学设备需要同时采集多个视野的内窥画面。这些场景共同的特点是对每一路的分辨率要求不一定爆炸高但对“同一时刻、独立处理、互不干扰”的要求非常高。放在以前想在一个嵌入式平台上面接四路摄像头常见的做法是找带多个CSI或者多个USB控制器的SoC然后用软件把四路拼起来。代价就是BOM成本高、PCB走线复杂、调试周期拉得很长。STM32MP23x的出现让这件事有了一个更优雅的解法它原生支持CSI-2接口并且配合DCMIPPDigital Camera Memory Interface Pixel Processor可以在单条CSI-2链路上同时解析多条虚拟通道的数据流也就是说硬件上只需要一条MIPI总线就能同时把四路相机的数据分别送到内存里为每个通道分配独立的视频管线。这个方案的核心价值我一句话总结用一条CSI-2链路换来了四路相机的独立视频流硬件简洁软件层面却不需要牺牲灵活性。之前用MP157或者i.MX系列做同类项目时我多半需要外挂FPGA做MIPI分发或者找两颗SoC分别采集再同步工程复杂度完全不在一个量级。所以当ST把DCMIPP和CSI-2多流支持放进MP23x时做四目视觉的嵌入式工程师确实应该认真看一看。1.2 多流方案对比虚拟通道与多路独立CSI的选择设计四摄系统时工程师一般会遇到三种选择路径第一种是选择自带多路CSI-2接口的SoC每一路单独接一个sensor第二种是在CSI-2链路上外接MIPI解串器把多路sensor的数据汇聚到一根总线上用虚拟通道ID区分第三种是放弃MIPI直接用USB摄像头或者网络摄像头靠CPU/网卡去并发读取。这三种路径的取舍很有意思。多路独立CSI接口的方案最直观每一路sensor的调试互不干扰出问题也好定位但代价是MCU/MPU的引脚资源、PCB布线和成本都会翻倍尤其是当四路sensor都要跑1080p30的时候板子的EMC设计和电源完整性直接成为噩梦。USB摄像头方案虽然开发最快但USB带宽是共享的四路720p基本就把USB 3.0的带宽吃得差不多了而且CPU占用率会非常高对工业场景来说延迟和稳定性也难以接受。所以我的判断很明确在STM32MP23x平台上最合理的就是第二种方案——利用CSI-2协议自带的虚拟通道机制加上一颗4到4通道的解串器。CSI-2协议本身规定了4个虚拟通道ID0到3这正好匹配四路sensor的扩展需求。各路sensor的数据在解串器内部被打上不同的虚拟通道标签然后汇聚成一条MIPI CSI-2串行流MP23x的CSI-2控制器再根据虚拟通道ID把数据分发给DCMIPP内部不同的管道。整个过程从物理层到协议层都是专门为多摄设计的不需要额外打补丁。1.3 STM32MP23x平台在四摄项目中的定位我习惯把一个嵌入式视觉项目拆成三块来看采集、处理、输出。STM32MP23x在这个项目里的定位非常明确它是采集和轻量处理的核心但不是一个跑重型AI推理的算力平台。STM32MP23x属于ST的新一代通用MPU系列使用双核Cortex-A35集成Cortex-M33实时核心还带了一个约0.5 TOPS级别的NPU。从算力上看它跑不动YOLOv8大模型但是做四路视频流的采集、格式转换、简单ISP处理、目标检测前的预处理这些工作绰绰有余。更关键的是它集成了一些对多摄非常有用的外设CSI-2摄像头接口、DCMIPP图像处理器以及充足的DDR带宽调度能力。在这种算力分配下我通常会建议把整个系统的架构定成“前端采集靠MP23x后端推理靠独立NPU或者上位机”。MP23x负责把四路sensor配置好、数据采集进内存、做好格式转换和基础的图像增强然后通过网络或者PCIe把图像数据交给上位机做更复杂的处理。这样分工既不会让MP23x的CPU被视频采集任务拖垮又能充分发挥它在多路CSI-2管理上的硬件优势。2. 硬件链路与摄像头接入细节2.1 四路sensor 解串器的典型连接方式硬件链路的搭建是四摄项目里第一个实打实的门槛。STM32MP23x的CSI-2接口支持标准的D-PHY数据通道数量通常是1到4条lane。如果我们直接把四路sensor并联到SoC的CSI-2引脚上无论是信号完整性还是协议层的虚拟通道分配都会遇到大麻烦因为每个sensor输出的是独立的CSI-2发送端它们不会自动协商虚拟通道。所以需要一颗专门的多通道解串器。我以目前市面上很常见的四通道解串器为例比如MAX96755或者MAX9286这类芯片它们的工作原理是接收来自4路sensor的GMSL2或FPD-Link串行信号在内部完成串并转换把4路MIPI CSI-2数据重新打包成一条含4个虚拟通道的CSI-2高速信号输出给SoC。同时这些解串器一般内置I2C地址转换和GPIO扩展功能解决多颗同型号sensor地址冲突的问题。连接示意大概是这样Sensor 0 ---串行链路---| |--- CSI-2 4-lane --- STM32MP23x Sensor 1 ---串行链路---| 四通道解串器 | (VC0~VC3) Sensor 2 ---串行链路---| | Sensor 3 ---串行链路---| |这里有个细节值得注意解串器和sensor之间的链路可以是GMSL2、FPD-Link或普通的CSI-2同轴线缆。对于车载级别的方案GMSL2用得最多因为它抗干扰强、支持长距离传输对于板级短距离应用直接使用CSI-2转CSI-2或者并行的DVP转CSI-2解串器就够了成本更低。我在板级原型验证阶段通常会选比较简单的解串方案先把四路图像跑出来再根据实际应用场景替换成适合量产的低功耗型号。2.2 带宽计算四路1080p30到底能不能跑硬件设计之前必须先把带宽算明白否则后面发现数据来不及传就晚了。CSI-2的带宽计算我反复做过很多次这里把公式和实例分享出来。MIPI CSI-2的带宽主要由分辨率、位深、帧率和lane数决定。以四路1080p1920x108030帧、RAW10格式为例单路数据量是1920 x 1080 x 10bit x 30fps 622,080,000 bit/s ≈ 622 Mbps注意这是比特率。四路合计就是2.488 Gbps。如果使用YUV422 16bit格式单路数据量变为1920 x 1080 x 16bit x 30fps 995,328,000 bit/s ≈ 995 Mbps四路合计约3.98 Gbps接近4Gbps。再看CSI-2 D-PHY的实际理论带宽。以4条lane、每lane 1.5Gbps的速率来计算理论总带宽是6Gbps。但CSI-2协议有开销包括包头、包尾、行消隐、帧消隐等实际有效带宽通常在理论值的80%~90%也就是4.8~5.4Gbps左右。结论就很明显了如果四路都跑1080p30 YUV4224Gbps的有效数据已经压在4.8~5.4Gbps的可利用带宽红线附近风险较大如果跑RAW10格式2.488Gbps的负载就很从容。所以我在四摄项目里总是优先建议使用RAW格式输出或者降低到720p30给链路留足余量。实际项目中还要考虑DDR带宽因为数据从CSI-2进来后在内存里存储、再被DCMIPP读取处理每一次搬运都会占用DDR带宽。四路同时跑YUV422时DDR带宽很容易成为新的瓶颈这一点本文第4章会详细讲。2.3 电源、时钟与同步设计多摄最容易忽略的细节硬件设计里比带宽更容易翻车的是电源和时钟。四路sensor同时启动瞬间电流冲击比单摄大得多。sensor内部的PLL上电时会有浪涌电流四路叠加可能导致供电电压跌落轻则图像闪烁重则sensor初始化失败。我踩过这个坑后来学乖了每路sensor的模拟电源和数字电源都单独用了一颗LDO并且在靠近sensor电源引脚的地方放了至少10uF的陶瓷电容问题才消除。时钟方面四路sensor通常需要共用同一个MCLK主时钟否则每路sensor的像素时钟频率会有微小差异最终导致四路图像的帧率不完全一致。在要求多路严格同步的应用里必须使用同一颗晶振或者同一个时钟buffer输出给四路sensor不能每路用自己的晶振。我见过一个项目因为四路sensor各自用独立晶振结果帧率差了0.3fps后处理时四路数据根本无法对齐。然后是frame sync。如果应用需要四路在同一时刻曝光需要在硬件上把sensor的FSINFrame Sync Input引脚连到一起由解串器或MPU的GPIO输出同一个帧同步脉冲。软件方面V4L2的buffer时间戳可以作为粗同步依据但真正的硬同步必须靠FSIN来实现。这也是四摄方案相比USB摄像头的一大优势帧同步在硬件层面就能做到微秒级。2.4 解串器I2C地址转换机制很多第一次做四摄的工程师会在I2C这一步被卡住四颗相同型号的sensor默认I2C地址完全一样比如都是0x3C挂到同一条I2C总线上直接冲突根本无法独立控制。解串器芯片普遍都内置了I2C地址转换功能原理是让解串器在I2C总线上作为代理根据不同的I2C地址前缀把请求转发给不同物理链路上的sensor。举个例子可以把四路sensor分别映射为0x3C、0x3E、0x40、0x42四个地址这样MPU访问0x3C时只有sensor 0响应访问0x3E时只有sensor 1响应。这个配置通常在上电初始化时通过解串器自己的I2C寄存器来完成具体寄存器地址每个厂家的芯片都不一样但思路完全一致。我在调试阶段建议先把四路sensor的地址映射关系写成一张表不仅方便自己查也方便硬件同事做连通性测试。类似这样的表物理通道解串器端口映射后的I2C地址虚拟通道IDSensor 0Port A0x3CVC0Sensor 1Port B0x3EVC1Sensor 2Port C0x40VC2Sensor 3Port D0x42VC3这个表在后面Linux设备树配置时也要用到提前理清楚能省很多排查时间。3. Linux软件栈与Multi-Stream管线配置3.1 从设备树开始的四路sensor描述STM32MP23x在Linux下的摄像头框架是标准的V4L2 Media Controller架构四路sensor每一路都是独立的subdeviceCSI-2控制器和DCMIPP是独立的video device。设备树编写是整个软件工作里最关键的一步它决定了后面用户态看到的是几个video节点以及虚拟通道如何映射。设备树的具体写法取决于内核版本和ST的BSP但核心逻辑是一样的。I2C总线下需要挂四个sensor节点每个sensor的endpoint里要指定虚拟通道ID。以sensor 0为例大致形如i2c2 { status okay; sensor0: sensor3c { compatible sony,imx335; reg 0x3c; clocks mclk_provider; clock-names xclk; reset-gpios gpioa 1 GPIO_ACTIVE_LOW; port { sensor0_out: endpoint { remote-endpoint csi2host_in0; virtual-channel 0; }; }; }; };需要注意的是虚拟通道ID必须与第2.4节那张地址映射表里列出的VC一一对应如果sensor端配了VC0但是解串器输出端的配置是VC1解码出来的图像就会串流或者完全没有数据。3.2 CSI-2和DCMIPP的media pipeline连接设备树只解决问题不解决全貌。四路sensor的数据从设备树描述的物理链路进入系统后最终呈现给用户态的是若干个video设备节点。这些节点和sensor之间是串联在media controller拓扑结构里的所以在采集之前必须用media-ctl工具把管线连接起来设置好每个节点的格式。STM32MP23x的CSI-2和DCMIPP内部会有多个入口和出口标准做法是把CSI-2的每个虚拟通道作为独立的source pad连接到DCMIPP的某个pipe入口。ST的BSP里DCMIPP通常暴露为类似“stm32-dcmipp-dma”这个driver对应多个video节点每个节点代表一条独立的捕获通道。media controller的连接示例命令大概长这样media-ctl -d /dev/media0 -l imx335 0-003c:0 - csi2host:0[1] media-ctl -d /dev/media0 -l imx335 0-003e:0 - csi2host:1[1] media-ctl -d /dev/media0 -l imx335 0-0040:0 - csi2host:2[1] media-ctl -d /dev/media0 -l imx335 0-0042:0 - csi2host:3[1]这里要注意csi2host的入口pad编号在ST的驱动里通常和虚拟通道ID一一对应所以0对应VC01对应VC1依次类推。不同内核版本里拓扑结构中的entity命名可能略有不同建议先用media-ctl -p /dev/media0打印整体拓扑确认每个entity的pad编号后再连线。格式设置上每一路都需要单独设置。比如设置sensor 0输出RAW10 1080pmedia-ctl -d /dev/media0 -V imx335 0-003c:0 [fmt:SRGGB10_1X10/1920x1080]然后把DCMIPP的每个video节点格式设置成和sensor匹配再用v4l2-ctl指定采集配置。这个过程重复四遍所有通道的格式就都对齐了。3.3 四路video节点的识别与采集命令配置好media链路后系统里会出现多个video设备。用v4l2-ctl --list-devices可以看到类似这样的输出stm32-dcmipp-dma (platform:stm32-dcmipp-dma): /dev/video0 /dev/video1 /dev/video2 /dev/video3这四个节点就是各路虚拟通道对应的采集设备。需要注意的是video节点编号和虚拟通道ID不一定按顺序对应有些BSP版本需要看driver里的实现来确认。我的做法是依次打开每个video节点获取一帧图像根据图像内容判断它对应哪个sensor然后在脚本里固定映射关系。四路同时采集最简单的方式是用四个线程分别对/dev/video0到/dev/video3执行v4l2-ctl或者直接开四个独立的进程v4l2-ctl -d /dev/video0 --set-fmt-videowidth1920,height1080,pixelformatRG10 \ --stream-mmap --stream-count100 --stream-to/tmp/cam0.raw v4l2-ctl -d /dev/video1 --set-fmt-videowidth1920,height1080,pixelformatRG10 \ --stream-mmap --stream-count100 --stream-to/tmp/cam1.raw v4l2-ctl -d /dev/video2 --set-fmt-videowidth1920,height1080,pixelformatRG10 \ --stream-mmap --stream-count100 --stream-to/tmp/cam2.raw v4l2-ctl -d /dev/video3 --set-fmt-videowidth1920,height1080,pixelformatRG10 \ --stream-mmap --stream-count100 --stream-to/tmp/cam3.raw wait如果四路能够同时稳定采集说明从硬件链路到驱动层已经全部打通接下来才进入真正的应用开发阶段。如果只有某一路出图或者某些节点一直超时大概率问题出在虚拟通道映射、I2C地址或者带宽不足这三个方向排查方法在第4章详细展开。3.4 DCMIPP的ISP与格式转换能力DCMIPP不仅仅是一个DMA搬运工它内部集成了图像信号处理能力可以完成去马赛克、坏点校正、白平衡、色彩校正、Gamma校正等基础ISP功能。单路sensor方案里这些功能可能直接在ISP芯片里完成但在多摄方案里如果每一路都外挂ISP芯片成本和功耗会成倍增加。DCMIPP的价值就在于它把ISP能力做进了SoC内部而且支持多个通道并行处理。实际配置时可以通过v4l2-ctl --list-ctrls查看每个video节点的控制项里面能看到与ISP相关的参数比如自动白平衡、曝光、增益等。四路sensor的场景下通常每一路的曝光和增益需要独立调节DCMIPP为每个通道提供了独立的控制接口这一点非常有用。不过要注意DCMIPP的算力资源是有限的。如果四路全部开启高级ISP效果比如多帧降噪、宽动态处理器的ISP负载可能会过高。我的经验是四路同时采集时基础的去马赛克和色彩校正可以全开但像多帧合成这类计算密集型功能最好只对需要重点分析的那一路启用否则帧率会明显下降。性能调优不是一锤子买卖要根据实际场景反复测试。4. 调试记录与常见问题排查4.1 问题一某些video节点始终无数据输出这个现象在四摄项目里出现频率最高。表现为v4l2-ctl --stream-mmap执行后一直阻塞或者直接报“No data available”。我排查这类问题的顺序基本固定。首先查设备树中虚拟通道ID。打开sensor节点设备树确认virtual-channel属性和实际sensor连接在解串器上的物理端口一致。然后是解串器的I2C配置用i2c-tools直接访问解串器寄存器读回它的通道状态寄存器确认四路sensor是否都有信号接入。实际操作命令类似i2cget -y 2 0x48 0x0a这条命令的具体含义要根据datasheet来查但思路是找解串器里表示“链路锁定状态”的寄存器检查是不是每一路都在PRIMARY LOCK状态。如果链路锁定正常再用media-ctl -p检查拓扑里每个sensor到CSI-2的pad连接是不是都处于enable状态。很多时候是因为连了第一路就忘了连第二路导致后面三路永远没有数据。4.2 问题二图像出现撕裂或丢帧四路同时采集时图像撕裂和丢帧通常和带宽紧张有关但具体是CSI-2带宽还是DDR带宽需要分开判断。如果CSI-2带宽不足图像会出现横条纹状的花屏因为高位的部分数据在传输时被截断。这时候优先降低数据率比如把4 lane从每lane 1.5Gbps降到每lane 1.2Gbps或者把分辨率降档来验证。如果DDR带宽不足现象更多是帧率统计值达不到预期或者DCMIPP的error计数器持续增长。在STM32MP23x上我建议通过查看video节点在/sys/kernel/debug/下的统计信息来确认丢帧。某些BSP会在debugfs里暴露DCMIPP的frame counter如果received_frame_count远大于processed_frame_count说明DCMIPP的处理能力跟不上这时候要检查是不是同时启动了太多ISP功能。如果processed_frame_count和实际frame count对不上还要查是不是DDR的QoS配置需要调整。4.3 问题三四路帧不同步硬件帧同步如果没做好四路画面的时间戳会有几十毫秒的偏移。软件层面很难完全消除这种偏移只能通过时间戳来做近似对齐。但在工业检测、运动分析类场景这种偏移完全无法接受。处理方式分两层。硬件上必须把四路sensor的FSIN引脚统接到同一根信号线上并由解串器或MPU的GPIO以固定周期发出同步脉冲。sensor端需要打开externalsync模式具体寄存器名各厂家不同但思路是让sensor的曝光开始时间由外部脉冲触发。软件上可以开启V4L2的V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC并用每个buffer的时间戳做辅助对齐。我实测过一组数据四路sensor都使用内部自由运行模式时帧间偏移最大能达到一帧半打开FSIN硬同步后偏移降到微秒级。所以如果你做的应用对多路时序有要求一定不要省这根线。4.4 问题四电容和layout导致的画质问题画质问题不是软件能完全解决的。四路sensor同时工作时电源噪声会比单摄复杂很多尤其是当四路sensor共用同一条供电轨时相互之间的干扰会直接体现在图像上——最典型的表现是图像上出现规律性横纹或者暗部噪点明显增加。我踩过最深的坑是FSIN信号线没有做包地处理直接导致画面里出现垂直方向的亮带。后来把FSIN线调整到内层两侧加地孔屏蔽问题才消失。所以提醒一下硬件同事四摄项目里FSIN、I2C、MCLK这三组信号线是最需要保护的layout阶段就要专门处理。4.5 常见问题速查表现象可能原因排查方法某一路无数据虚拟通道ID配置错误对比设备树VC和解串器端口映射表某一路无数据解串器链路未锁定读解串器链路状态寄存器图像花屏CSI-2 lane数或速率超标降低lane速率或格式位深丢帧DCMIPP处理能力不足关闭不必要的ISP功能画面横纹电源纹波示波器查sensor电源波形帧不同步FSIN未硬同步检查FSIN接线和sensor同步寄存器四路图像串流虚拟通道或实体通道错位逐路核对media-ctl拓扑这个表基本覆盖了我在四摄项目里遇到过的绝大多数问题。当然不同sensor型号、不同解串器芯片、不同BSP版本会有细微差别但排查思路是通用的。最后分享一个个人经验四摄项目启动时不要直接挑战四路同时调通我习惯先把四路sensor分别以单路模式全部点亮确认每一路能单独出图再把解串器的多流输出打开最后用media controller连接四路管线。这个顺序虽然看起来多花了时间但实际上大大缩短了总调试周期。另外调试过程中最好写一个脚本把四路media-ctl配置固化下来不然每次重启后手动敲命令一旦敲错一路排查起来非常费劲。这种项目里稳定可复现的调试步骤比什么都重要。
返回列表