ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MIPI CSI-2与RAW10实战:带宽计算、打包格式与调试优化

MIPI CSI-2与RAW10实战:带宽计算、打包格式与调试优化 做嵌入式视觉的朋友基本都遇到过这么一个问题明明用的是 MIPI CSI-2 接传感器RAW10 数据也确实在链路上传着可要么画面花屏、错位要么提了分辨率之后带宽死活不够再要么换一颗传感器之后整条链路都得重新调。MIPI CSI-2 本身是 Camera 接口的事实标准而 RAW10 又是大多数 CMOS 图像传感器的原始输出格式这俩组合基本是嵌入式视觉项目里最常见、也最容易出设备差异问题的地方。这篇不打算讲协议规范的全文翻译就针对“RAW10 怎么从传感器搬到主控途中怎么算带宽、怎么打包、怎么优化”这条主线把实际调板子和写驱动的经验一并整理出来适合正在做摄像头驱动、ISP 接入、或者打算在医学影像/工业检测里走原始数据链路的工程师参考。1. RAW10为什么是摄像头链路的“默认选项”1.1 RAW图就是感光元件的“原话”先对齐一个基础概念CMOS 传感器表面是感光像素阵列每个像素前面覆盖着滤色片最常用的就是 Bayer 图案也就是 R、G、B 按 2×2 排列成一组绿色占一半红蓝各占四分之一。感光像素把光信号转成电荷再通过 ADC 变成数字值这个“ADC 输出”就是 RAW 图。RAW 图本身没有颜色只有每个像素对应的光强数字化结果ISP 拿到之后再做去马赛克、白平衡、降噪、Gamma 等一系列操作才得到常见的 YUV 或 RGB 图。RAW10 的意思就是这个 ADC 量化位数是 10bit每个像素用一个 10bit 的数字量表示亮度敏感度。为什么是 10bit 而不是 8bit 或者 12bit因为这个位数和传感器本身的信噪比、动态范围有关。普通 8bit 在暗光下量化台阶太粗容易出 banding 和色阶断裂12bit 数据量更大但很多场景下传感器的模拟噪声并不能完全发挥 12bit 的优势RAW10 成了成本和画质之间一个非常均衡的点。你去看市面上主流安防、车载、内窥镜传感器输出 RAW10 的比例非常高。1.2 为什么是RAW10而不是RAW8、RAW12/16如果单纯从数据量角度RAW8 最小RAW12、RAW16 更精细但 RAW10 成了很多项目的默认选项原因有这么几个第一RAW10 是 10bit对应传感器 ADC 的典型设计。很多传感器的原生量化精度就是 10bit你让它输出 RAW8 相当于直接砍掉两位信息暗部细节和噪声性能都会打折扣输出 RAW12 反而可能是从 10bit 数据上做高位补零或插值信息量并没有真的增加带宽却增加不少。第二RAW10 在 MIPI CSI-2 协议里有比较灵活的打包方式可以做到无损的 4 像素塞进 5 字节相比 RAW16 直接省下 37.5% 的链路带宽。这一点在后面会展开讲在链路带宽有限的前提下这种打包带来的收益非常可观。第三从产业链成熟度看从传感器到 ISP、SoC、FPGA 的 MIPI IP对 RAW10 的支持都最齐全。做板级集成的时候少碰兼容性玄学比多得几位数据量重要得多。举个直观的数字。一颗 1080P 传感器输出 30fps如果用 RAW81920 × 1080 × 30 × 8bit 497,664,000 bit/s ≈ 498 Mbps如果用 RAW101920 × 1080 × 30 × 10bit 622,080,000 bit/s ≈ 622 Mbps如果用 RAW161920 × 1080 × 30 × 16bit 995,328,000 bit/s ≈ 995 Mbps同样一处链路设计RAW10 比 RAW16 省的带宽是非常直观的而且信息量相比 RAW8 又有所提升所以大家在项目规格书的 sensor 输出格式栏看到 RAW10 的频率最高一点不意外。1.3 从RAW10到医学3D数据流的下半场这里多说一句最近很多医学影像项目里前端采集恰恰就是 RAW10 走 MIPI 进来后端再做三维重建。比如内窥镜、OCT、病理切片扫描这类设备前端传感器通过 MIPI CSI-2 把 RAW10 帧数据快速送到主控然后经过 ISP/预处理后把一组连续断层或序列帧堆叠成体素数据保存成 NIfTI.nii这类格式最后交给 OpenGL 做体绘制的 3D 渲染生成医学三维图像。也就是说MIPI CSI-2 RAW10 经常只是整条图像流水线的入口。你把这个入口的带宽和延迟控制好了后面做体素重建、GPU 渲染才会有一个稳定的数据源。这也是我为什么一直强调 RAW10 传输链路不能只盯着“能通”这一个标准要连带宽余量、格式一致性、帧率稳定性一起考虑因为这些都会直接影响最终三维重建的质量。2. 带宽预算是怎么算的一个案例走完整个流程2.1 先搞懂MIPI D-PHY的几个基础参数MIPI CSI-2 的物理层最常见是 D-PHY另外还有 C-PHY但 D-PHY 适用面最广。一条 D-PHY lane 本质是差分线对有 HSHigh Speed和 LPLow Power两种模式。HS 模式是高速差分信号真正搬数据LP 模式功耗低用来做帧同步等控制。真正的图像数据在 HS 模式下传输而且用的是 DDR 双沿采样也就是说时钟 lane 的上升沿和下降沿都各采一次数据。每条 lane 能跑多快不同版本和不同芯片厂商能力不一样。老的 MIPI D-PHY 规范一条 lane 大概是 800Mbps 到 1Gbps现在很多 SoC 的 CSI controller 单 lane 都能跑到 1.5Gbps 甚至 2.5Gbps传感器端输出能跑到多少要查具体型号的 datasheet不是所有 sensor 都支持很高的 HS 时钟。很多人低估了“传感器端速率上限”这个约束在 SoC 侧配了很高的 lane rate结果 sensor 端跟不上时序就乱了这也是一种常见坑。另一个关键参数是 lane 数。CSI-2 接口可以是 1-lane、2-lane、4-lane甚至更多。lane 越多并行传输能力越强但 PCB 布线难度和功耗也会增加。对于 1080P30fps 的 RAW104-lane 是相当宽裕的配置对于低分辨率或低帧率场景2-lane 也够用。2.2 一个完整的带宽计算案例直接拿 1080P30fps RAW10 做例子把整条链路带宽预算一遍。第一步计算纯图像数据量分辨率1920 × 1080 2,073,600 像素帧率30 fps位深RAW10紧凑打包后每像素 10bit原始数据率2,073,600 × 30 × 10 622,080,000 bit/s 622.08 Mbps这个 622.08 Mbps 是纯有效像素数据。但 MIPI CSI-2 传输不是裸数据直接摆上去它要按协议打包。每一帧图像一般会有帧起始码FS、帧结束码FE每一行数据可能分成多个 long packet每个 long packet 有 4 字节包头、有效负载、2 字节 CRC 尾巴行与行之间还可能有 HBlank 和 VBlank。这些 blanking 时间不是空转而是协议要求的光标区间同时也是 sensor 输出数据所必需的时间余量。所以实际需要的链路带宽不能只算 622Mbps一般建议至少预留 20% 到 30% 的余量。保守估算就是623 Mbps × 1.25 ≈ 778 Mbps如果链路配置成 2-lane那么每条 lane 需要承载约 389Mbps对 D-PHY 来说只要选一个 400Mbps 左右的 lane rate 就够了。如果用 1-lane单 lane 要跑到 778Mbps这在很多传感器上已经很吃力了所以通常至少上 2-lane 或 4-lane 才稳一点。反过来如果你已经定了 lane 数和 lane rate怎么判断是否够用可以用这个式子反推最大可支持分辨率 lane数 × 单lane速率 × 打包效率 ÷帧率 × 位深举个例子。4-lane每 lane 跑 1Gbps那么总有效带宽是 4Gbps。RAW10 紧凑打包在某些实现里会有少量协议开销取打包效率约 90%那么有效数据带宽约 3.6Gbps。如果要跑 60fps、RAW10可支持像素数 3.6Gbps ÷60 × 10bit 6,000,000 像素/帧对应大概是 2688 × 1944 这个档位也就是 5MP 级别所以你看 5MP60fps 的 RAW104-lane 1Gbps 配置也就刚够再往上就得管控 blanking 或者降低帧率。这个“反推式”计算在握项目规格的时候最实用能一句话判断传感器选型靠不靠谱。2.3 如果带宽不够先想清楚是哪一项在卡脖子碰到带宽不够的情况我习惯先按三个方向排查像素数、帧率、位深。像素数能不能降分辨率用 ROI 只出画面中心帧率场景是不是真的需要 60fps降到 30fps 能省一半带宽位深这里能不能接受 RAW8或者改用 RAW10 紧凑打包而不是高位的 RAW12很多人在链路带宽不够的时候直接就去调 lane rate这其实是最后一步。前面三板斧“降低像素数、降低帧率、压缩位深”不花钱也不动电路效果立竿见影。尤其是做双目或多目系统的时候两路 RAW10 同时传带宽冲突特别明显用 ROI 帧率控制往往比硬怼 lane rate 更实际。还有一个指标是 HS 时钟的选择。D-PHY 的 clock lane 也是差分线HS 模式下时钟频率等于数据 lane 的 bit rate但是因为是 DDR 双沿实际总线频率是数据速率的一半左右。配置的时候要注意 PLL 的参考时钟、倍频系数和目标 lane rate 之间是否整除不然可能配出一个很尴尬的分数频率导致数据时序抖动变大误码率升高。3. RAW10打包格式同样10bit数据带宽可能差37%3.1 松散打包的真相RAW10 不是天生只有一种字节排列方式。最常见的两种是松散打包loose packing和紧凑打包packed packing。松散打包的意思是每个 10bit 像素放在一个 16bit 的容器里低 10 位是有效数据高 6 位补零。这样做优点是对齐简单一个像素一个半字处理器取数据的时候不需要做位拼接操作DMA 搬运也很方便。但代价就是浪费带宽。前面算了 RAW10 紧凑方式 622Mbps如果用松散方式等效数据率是2,073,600 × 30 × 16 995,328,000 bit/s ≈ 995Mbps同样是 RAW10松散打包比紧凑打包多了大约 60% 的链路带宽消耗。这在 2-lane 或者 1-lane 的低速链路上基本是灾难性的本来能跑 60fps 的配置选错打包格式可能连 30fps 都稳不住。3.2 紧凑打包的字节流布局紧凑打包就是把多个 10bit 像素掰开按位拼接塞进 8bit 字节流里。RAW10 的一个典型做法是 4 个像素打包成 5 个字节。因为 4 × 10 40bit 5 × 8bit数学上刚好对齐所以它是无损的而且没有浪费。具体布局是这样的假定连续像素记为 P1、P2、P3、P4每个 10bitByte0 P1[9:2]也就是 P1 的高 8 位Byte1 P1[1:0] 6 | P2[9:4]即 P1 低 2 位拼上 P2 的高 6 位Byte2 P2[3:0] 4 | P3[9:6]即 P2 低 4 位拼上 P3 的高 4 位Byte3 P3[5:0] 2 | P4[9:8]即 P3 低 6 位拼上 P4 的高 2 位Byte4 P4[7:0]即 P4 低 8 位这个布局在实际代码里很常见做软件解包的时候就是反复的移位和或操作。如果你是在 FPGA 里做接收端也要严格要求字节序和位序一致否则图像数据会整体错位画面上出现非常典型的斜向条纹或像素点错乱。为什么说选错打包格式会造成 37% 的带宽差距对比 RAW16 来算RAW10 每像素 10bit紧凑打包后每像素实际占 10/8 1.25 字节RAW16 每像素 16bit占 2 字节。用 RAW10 比用 RAW16 省下的带宽是 1 - 1.25/2 37.5%。如果你在 SoC 里把 RAW10 当作 16bit 去接收这是新手非常容易犯的错误不仅要多占带宽还要多占内存空间后面的 ISP 处理也会出错。3.3 两种打包对DMA和内存带宽的影响打包格式不只影响 MIPI 链路还会影响内存侧。MIPI 接收控制器拿到数据之后DMA 会把数据写到 DDR 里。松散打包因为每个像素占 2 字节DMA 非常高效字节对齐度好但内存占用大紧凑打包则每 5 字节对应 4 像素DMA 到 DDR 时可能出现 5 字节不连续对齐的情况需要控制器或驱动层做适配。很多 SoC 的 CSI 驱动在配置 DMA 时都会要求指定数据的打包格式。如果配置成 RAW10 packedDMA 会按打包后的字节数写到内存此时 driver 计算 buffer size 时要按宽 × 高 × 10 / 8 计算而不是按宽 × 高 × 2。假如 buffer size 配小了DMA 写内存会越界轻则崩溃重则踩坏其他内存数据。这一点我在多个平台上都踩过新手最容易忽略。另外要注意有些 ISP 或预处理模块直接接受紧凑打包的数据有些则需要先解包成 16bit 再说。这两者之间会多一次内存带宽消耗。做一个大数据量项目时这个中间转换层也可能成为瓶颈所以要提前想清楚自己的处理链路是“紧凑直通”还是“先解包”。3.4 选错打包格式的典型症状这里整理几个我在项目里真实遇到过的症状供大家排查参考画面整体偏色但亮度正常很可能打包/解包时高位或低位拿错了绿色通道或红蓝通道的像素值整体被位移图像出现周期性斜条纹大概率是 4 像素 5 字节的位拼接错位了也就是字节序或位序不对图像每隔几列就出现一个异常亮/暗点多半是解包时的掩码错了某个 bit 位被重复读取或漏读图像有重复行或行错位可能是 DMA 的 stride 配置不对行字节数和实际打包宽度不匹配画面只有一半或者顶部花屏大概率 buffer size 不够或者行缓存/帧缓存的同步信号不匹配这些现象看起来五花八门但追根溯源基本都是“打包格式不一致”导致的。所以拿到一个新 sensor SoC 平台时第一件事就是把 sensor 侧输出的 data type 和 SoC 侧配置的 data type 对齐MIPI CSI-2 协议定义了每种格式对应的数据类型代码RAW10 的 data type 是 0x2B很多人一开始都不知道查这个东西。4. 带宽优化技巧从协议层到系统层的六种实战打法4.1 技巧一用虚拟通道VC共享物理链路MIPI CSI-2 支持虚拟通道Virtual Channel, VC的概念。一条物理链路可以被分成最多 4 个逻辑通道每路 sensor 或者同一个 sensor 的不同数据流可以打上 VC 标签。接收端根据 VC ID 把数据分发到不同的内存缓冲区或者处理模块。这个特性的最大价值在于让多颗传感器共享同一条 MIPI 物理链路省 lane 也省 PCB 走线空间。比如双目光学模组两颗 sensor 各走 2-lane 会比较吃紧但如果它们各自输出 RAW10 低帧率可以合并后走单颗 4-lane 的物理接口。只要每一路画面在时序上错峰或者总带宽加起来不超过链路容量就可以这么干。不过 VC 合并要小心一点多路 sensor 的 HS 信号如果同时出现控制器侧的压力会很大而且空帧、错误包之间会出现优先级竞争。建议帧率错开给每一路配好帧同步避免同帧发送碰撞。4.2 技巧二ROI裁剪 变速帧率ROIRegion of Interest是传感器普遍支持的功能只输出画面中一部分区域其余区域直接丢弃。这在带宽受限时非常实用。比如一台检测设备如果检测目标只占画面的中心区域那么把 sensor 配成只输出这个区域不但省了链路带宽还降低了后端 ISP 的处理压力。帧率也可以配合场景动态调整。高动态场景用 60fps静态场景直接降到 10fps平均功耗和带宽都能大幅下降。很多 sensor 支持通过 I2C 控制输出帧率I2C 的修改在当前帧结束后才生效有些主控直接可以做动态调帧率。ROI 降帧率这种方式最大的好处是不需要协议层面的改动纯粹是 sensor 侧配置改动风险很低。4.3 技巧三传感器内置DPCM压缩很多中高端传感器内部有 DPCM差分脉冲编码调制压缩模块可以在 RAW10 的基础上进一步减少输出 bit 流。DPCM 的基本思路是预测相邻像素值只输出残差。因为图像相邻像素之间通常很平滑残差的动态范围小可以做到接近 50% 的数据缩减而且肉眼几乎看不出质量损失。是否用 DPCM 取决于你的后端能不能处理。有些 SoC 的 MIPI 接收端直接支持 DPCM 解压有些则不支持需要把 raw 数据送到 CPU/GPU 做软件解压。医学影像这类对无损要求高的场景慎用有损压缩必须确认是 DPCM 无损变长编码还是有损变长编码。4.4 技巧四合理管理HS/LP时间和EOTPMIPI D-PHY 在每一帧或者每个 packet 传输之间会有 HS - LP 的状态切换。LP 状态功耗非常低但状态切换有延迟也需要一定的时间开销。如果你频繁地在 HS 和 LP 之间切换实际有效带宽会被压缩。典型的做法是让每帧的数据尽量连续输出减少不必要的 LP 插空。EOTPEnd of Transmission Packet是可选发送的包尾主要用于表明 HS 传输结束位置。某些平台为了简单会关闭 EOTP但关闭之后接收端对数据结束位置的判定会依赖自己的 HS 边界检测偶尔会出现残留帧尾像素。项目里建议保持收发两端的 EOTP 配置一致别一边开一边关。4.5 技巧五从像素时钟和PLL层面降功耗链路带宽的计算最终要落到传感器输出的像素时钟和 MIPI HS 时钟上。sensor datasheet 通常会给出一个推荐的 pixel clock 范围如果你的帧率和分辨率定下来了pixel clock 可以配置到最低可行值从而降低 sensor 内部数字逻辑和 MIPI 发送端功耗。同时 MIPI HS 时钟也不建议无脑配最高。4-lane 能跑完的数据非要用 2-lane 去跑HS 时钟会翻倍功耗和信号完整性都会变差。合理的做法是“够用 20% 余量”不要追求极限速率。系统级测功耗的时候lane rate 降 200Mbps 往往就能看到整板电流有可观下降。4.6 技巧六端到端数据流优化RAW10到3D体数据的流水线思路这一节换个角度。有时候“带宽”瓶颈不在 MIPI 链路上而是整条数据流水线中间的搬运和存储。特别在做医学 3D 影像这类应用时前端 RAW10 数据通过 MIPI 进来后面还需要把多帧序列堆叠成体素数据比如 NIfTI 格式再做 OpenGL 体渲染。如果每个环节都频繁拷贝、转换系统内存带宽会先撑不住。一个高效的流水线做法是在 MIPI 接收阶段就把紧凑 RAW10 尽可能保留为紧凑格式不要过早解包成 16bit。ISP 输出灰度或单通道图时保存成 8bit/16bit 体积序列再把这些序列帧在 GPU 侧直接构建 3D texture交给 OpenGL 的 shader 做 ray casting 体绘制。这样避免在 CPU 上做大数组的多次拷贝也避免反复搬运 RAW10 到 RGB 到 volume 的多级中间格式。医学项目里常见的数据流是这样的传感器 RAW10 通过 CSI-2 送往主控 → CIS/ISP 处理后得到序列帧 → 序列帧重采样/堆叠为体素体积 → 保存为 NIfTI 或通用 volume 数据 → OpenGL 创建 3D texture → 渲染管线中做传递函数和光照模型最终生成三维医学图像。这条链路的瓶颈往往不是某一处计算慢而是每一层都在搬数据。所以做优化时先把“零拷贝”做起来能省掉 30% 到 50% 的系统级延迟。5. 调试实录花屏、错位、断流问题到底出在哪5.1 物理层问题排线、差分对、信号完整性常见的 CSI 调试问题物理层的占比相当高。MIPI 差分对布线要求等长、等间距、远离时钟源和电源噪声。实测中如果摄像头排线过长超过 10cm 且没有屏蔽HS 信号容易衰减表现为偶发花屏、丢帧甚至完全黑屏。排查时最快的方法是拿示波器看 HS burst 的眼图。D-PHY 高速差分信号正常是大约 200mV 的差分摆幅如果电压明显偏低、眼图交叉点移动优先怀疑排线屏蔽和阻抗匹配。有些开发板为了省成本没用阻抗控制到了量产阶段出现信号问题代价会大得多所以早期打板时就要确认 MIPI 差分线阻抗控制一般 100 欧姆差分是否落实。布线阶段还有一个小点MIPI 的 clock lane 和数据 lane 之间误差控制要求比较高尤其时钟相对数据的 skew 大了之后数据采过来就是对不齐的。很多平台允许 per-lane 的相位调整一旦画面出现“一行数据错到另一行”的现象可以把 lane 的 geck 值微调一下。5.2 配置层问题寄存器、时序、数据类型不匹配物理层没问题的情况下配置层最容易出岔子。新接一颗 sensor 和 SoC需要同时确认三组配置sensor 输出格式RAW10, data type 0x2B传感器端 MIPI lane 数和 HS 速率SoC 端 CSI controller 的 lane 数、数据类型、DMA buffer 大小这三者任何一项不匹配都会出现奇奇怪怪的画面问题。比如有的平台把数据类型配置成了 RAW8但 sensor 实际送的是 RAW10结果每 5 字节被读成 4 字节图像就出现类似“像素灰阶被压成 8bit 并且丢位”的效果看起来像是整体颜色变暗、层次变少。配置时序也要注意。sensor 上电之后不是马上就能出图的很多 sensor 需要等待垂直消隐或者水平消隐稳定后MIPI 输出才完全合规。如果 SoC 端在 sensor 没有完全稳定时就打开 CSI接收端可能捕捉到半帧数据或者同步码错误。项目里最常见的做法是先让 sensor 跑一段时间再通过 I2C 读取一个寄存器确认状态之后才使能 CSI 接收。5.3 常见问题速查表我把这些年调试中常见的问题整理成一个速查表方便大家现场对照现象可能原因排查方向完全黑屏CSI 接收不到数据传感器未出图或 MIPI lane 配置错误先用示波器确认 HS burst 是否周期出现查 sensor 寄存器是否进入 streaming 状态花屏、周期性条纹打包格式/位序不对核对 sensor 输出 data type 与 SoC 接收配置是否一致检查代码解包掩码图像偏色高位/低位错位或 Bayer 排列不对RAW10 的高位和低位顺序是否颠倒Bayer 顺序要在 ISP 侧配对偶发丢帧、闪断HS 信号质量差干扰检查排线屏蔽、差分走线用手按压排线看现象是否变化画面卡死或 DMA 越界buffer size 配小或 stride 不对检查宽高 × 10/8 字节数是否算对stride 是否按打包宽度对齐两路 sensor 互相干扰VC 冲突或帧同步没做确认 VC ID 分配唯一且帧同步信号已连接避免同帧竞争低帧率但带宽报表超了blanking 时间过长检查 sensor 的水平/垂直 blanking 配置是否过大适当压缩 blanking 时间到高分辨率就灰屏链路理论带宽不足重新做带宽预算逐步降低帧率/ROI 或增加 lane 数排查的顺序我一般这样走物理层先看信号再看配置最后看 DMA/内存。先通过示波器确认 MIPI 线上确实有正确频率的 HS burst否则容易在驱动层浪费很多时间。还有一个比较隐蔽的点MIPI CSI-2 的 clock lane 极性。有的平台可以配置 clock lane 的 polarity如果你的 sensor 和主控之间对时钟沿的约定不一致数据就会整体偏移半拍导致画面看起来像是每个像素的左右顺序反了或者“水波纹”状干扰。遇到这种问题在 SoC 侧把 clock lane polarity 反转一下试试比改硬件快很多。最后说两句自己的体会做 MIPI CSI-2 调通的次数多了以后我最大的体会是这个领域没有太多高深玄学绝大多数问题都落在“物理信号、协议配置、带宽预算”这三件事上。把 RAW10 的打包逻辑吃透把链路带宽算式刻在脑子里再有一个示波器和一个能抓协议的逻辑分析仪基本就能覆盖日常开发里九成以上的问题。还有一个小建议是做事别怕在早期多测一版 PCB 的 MIPI 走线尤其是做四层板以上的系统MIPI 差分对附近不要走高速开关信号。改板子虽然痛但比量产之后信号有问题到处救火舒服太多。我第一次做双目模组时就是因为偷懒把两路 MIPI 差分线并行走了一段结果跑 RAW1060fps 时画面总是一条条闪线最后只能重新布局。希望读到这里的朋友能和当年的我一起少踩几个类似的坑。
返回列表