资讯详情

资讯详情

MIPI多路合一技术解析:从协议基础到FPGA实现与RK3588适配

我接到过不少类似的项目咨询客户的需求各不相同但开场白往往出奇一致 我就想把两路MIPI信号合成一路插到主控上。 当我说这个需要FPGA做协议级处理时对面的反应通常是反问一句 不能做一根转接线解决吗回答当然是不能。MIPI多路合一从来不是普通转接线它牵扯时钟恢复、数据对齐、协议重写、调度缓存难度完全不是物理上多焊几根线能覆盖的。这篇文章我把整个思路讲透覆盖MIPI DSI/CSI协议的基础认知、FPGA实现多路合一的方案以及RK3588等平台上屏驱动适配的实操经验给打算做类似项目的朋友一套可落地的参考。你在网上搜mipi dsimipi协议fpga实现mipi的时候可能会看到一堆Demo和开源项目但很少有一篇文章把多路合一到底合的是什么讲清楚我争取在这里把它讲明白。1. 先把路字拆开MIPI的物理通道和虚拟通道根本不是一回事1.1 一个最容易混淆的概念Lane 和 Channel很多人一上来就说四路MIPI合成一路但我发现他们口中的路往往不是同一个东西。在MIPI体系里物理上你有D-PHY的lane也就是那对差分线协议上你有Virtual Channel虚拟通道。这两个概念经常被混用但真实的含义差得远。概念作用类比Lane物理差分传输线对D-PHY下一路数据lane跑一路连续比特流高速公路的一条车道Virtual ChannelVC在一条lane的比特流内部通过包头里的ID字段区分属于哪一路数据这条车道上的不同货车车身上喷着不同的运输公司编号Multi-Lane PortSoC的MIPI控制器往往支持多个lane组合成一条物理口比如4-lane DSI一条4车道的路货物并行装载做过FPGA的人都知道一条MIPI 4-lane DSI物理上就是4根差分数据线加1根差分时钟线速率跑到1000Mbps per lane的时候4根线加起来带宽是4Gbps时钟是DDR每根数据线双边沿采样。这个带宽听上去很大但问题是这4个lane上跑的是同一数据流的切片不是4路互相独立的数据流。换句话说你有4条lane不等于你能接4个摄像头 lane是车道不是独立的路。1.2 CSI与DSI协议里如何区分多路CSI-2和DSI协议都支持Virtual Channel机制。每个数据包的头部都有一个VC字段接收端靠这个ID把复用到同一组物理lane上的不同数据流拆开。这个机制在相机场景里尤其常见一颗CSI-2发送器可以同时传两路摄像头画面系统端靠VC ID区分A相机和B相机。这也带来一种可能两路物理MIPI线各自跑的是不同摄像头的画面到了FPGA里我们完全可以不做物理上的电平合并而是把两路数据都解出来之后在像素层重新打成一个视频流再用同一个DSI端口送出去。这就是协议级的多路合一。当然这要求你手上有能同时接收多路MIPI输入、再生成一路输出的设备。很多SoC的MIPI控制器是固定功能的端口数量有限且不能把两路输入在内部直接合并成一路输出所以FPGA成了这类场景最常用的方案。1.3 需求从哪里来多屏拼接与多路输入的典型场景实际项目中对我说多路合一需求的场景主要分三类。第一类是车载或工控上常见的多屏拼接比如两块720x1280的竖屏要拼成一个1280x1440的异形大屏主控只有一路DSI口。这时候功能上要求把两块屏的像素数据分时发出去由驱动板侧把两块屏当作一个大屏来寻址。这种需求下合的难点不在物理层而在视频时序两路输入的行场同步要对齐输出帧率要一致否则拼接边界会出现撕裂。第二类是摄像头输入的合并。工业检测里经常要接多路摄像头信号到一个SoC的同一个CSI控制器或者做虚拟通道重映射。这比显示更适合用VC机制处理因为CSI-2本来就是为多摄像头场景设计的。第三类是带宽叠加。比如一片1080p的屏单路4-lane DSI带宽不够跑60Hz需要双口DSI同时各喂一半画面这对驱动IC和SoC都提出了双链路支持的要求。很多屏驱IC有split mode但要求主控侧按规则交叉输出左右半屏不是简单拿一根线接上就能分。这三类需求覆盖了我接触到的90%以上的多路合一项目。共同点非常明显全都需要协议级交互物理上那些排线、转接板根本解决不了。2. 为什么普通转接线搞不定时钟恢复、数据对齐和去偏斜2.1 转接线到底做了什么转接线本质上是无源互连把所有脚一对一接上。对于并行低速信号比如RGB888加RGB时钟转接线基本可用因为建立保持时间足够宽裕扇出差一点问题不大。做硬件的老工程师都习惯用扁平排线传16bit并行RGB那个容错空间确实大。但MIPI是高速串行差分信号。拿D-PHY举例时钟lane送过来的是一对差分时钟数据lane上每个bit都是跟着这个时钟边沿有确定的相位关系的。接收端需要从比特流里恢复字对齐byte / word alignment再做跨lane的deskew校准复杂的部分全在接收端的数字逻辑里。这些活插头插座的物理连接全都不管。一旦你拿一根普通FPC排线把两路MIPI信号喂到一个单口出现的立刻是这两个现象之一要么画面完全是雪花或条纹要么终端直接报协议错误。这大概率不是信号强度不够而是所有bit的参考点乱了。高速差分线上哪怕只差几十mil的走线长度物理层采样窗口就会被破坏。2.2 重定时(DSP)与去偏斜(Deskew)的必要性MIPI规范里D-PHY每个数据lane的HS传输之前会有一段同步序列比如HS-0序列接收端要利用序列头做同步。多路物理信号合并时最麻烦的是跨lane偏斜lane-to-lane skew。两个来源的时钟域完全不同两路输入信号各自有各自的源端时钟即使标称频率相同实际相位和频率偏差也存在。直接拿一个时钟去采两路数据必然失败。这时候必须要有PLL和CDR时钟数据恢复把两路信号分别锁定到各自的时钟域再通过异步FIFO做跨时钟域搬运。这也是为什么我反复强调多路合一不是转接——你需要的是一个完整的接收器不是一个线缆。D-PHY 2.0规范里引入了deskew calibration序列用于在HS-TRAIL阶段校准lane间偏斜。但很多老一代SoC、FPGA IP核并不完整支持这套机制。我实测下来在FPGA里手写或使用第三方IP核做MIPI接收至少关心三件事HS-0的pattern对齐、I/O delay的差值设定、以及不同lane之间字节对齐的校准状态机。PCB走线等长做得再差只要逻辑层对齐能兜住系统整体还是能正常工作。2.3 数据包层面的校验就算物理层对齐了协议层还需要校验包头、CRC/ECC处理包和包之间的时序。MIPI DSI视频模式下数据包有短包和长包之分短包是同步和状态长包承载像素数据每个包都要检测ECC否则接收端可能错误解析参数。两路输入各自的包节奏不同合并时其实是在做一个多路流到单路流的多对一调度。可以用轮询、优先级或时间片策略但绝不是一个简单的MUX芯片能搞定的。MUX芯片只会选通其中一路没有办法把两路都缓冲下来再按目标时刻发出。说到底转接线只能解决脚对上脚解决不了时序重对齐“时钟域转换”协议重组而这些恰恰是多路合一的关键。3. FPGA实现MIPI多路合一的实操路线架构与缓存计算3.1 方案选型为什么是FPGA而不是ASIC或MCU明确说我见过的工程化方案里多路MIPI合一几乎都是FPGA完成的。原因有三MCU的MIPI控制器数量很少而且固定功能无法把两路输入在内部混合成一路输出小批量需求的成本和周期订一颗ASIC根本不现实FPGA的高速收发器和可编程逻辑提供了足够的自由度既能做协议解析又能做像素级处理。FPGA平台选择上Xilinx 7系列、Intel Cyclone系列的MIPI方案比较老牌文档也多但要注意IP核授权成本。国产的紫光同创Logos系列、高云等也提供D-PHY相关IP实测在常规的DSI输入采集、拼接输出场景下性能可靠。我最近的一个项目前级采集两路1080p30的MIPI CSI信号合路到一路4-lane DSI输出就是用紫光同创的FPGA实现的。3.2 核心架构接收、暂存、重打包一个完整的MIPI多路合一路径可以分为下面几个阶段多路D-PHY RX每路独立完成CDR、字节对齐、Escape模式解析协议解析与VC识别从包头提取VC编号、数据类型把载荷丢到对应FIFO缓存与重排根据输出端需要的时序从各路FIFO中取出数据按目标帧时序拼装D-PHY TX打包成DSI包格式按输出速率要求重新发送。这套架构里最难的是第3步的时序拼装。如果只是简单合路两路输入数据交替发送到同一端口需要做轮询调度但实际场景多半是像素拼接输出的一行里可能前半行来自输入A、后半行来自输入B或者两块屏的刷新时序要独立控制这就涉及帧缓存。3.3 缓存容量和带宽的计算公式我把几个关键计算写出来方便直接套用。设输出分辨率为W×H刷新率为F像素格式为RGB888每像素3字节。单帧图像无压缩数据量image_size W * H * 3 (字节)以1080p为例1920 × 1080 × 3 6220800字节约6.2MB。如果要求整帧缓存做拼接实际需要的DDR带宽至少是输入与输出两份带宽之和。输入侧总带宽带宽 1920 × 1080 × 60 × 24bit ≈ 2.98Gbps两路输入时输入侧总带宽约5.96Gbps输出侧2.98GbpsDDR总带宽至少要覆盖输入写加输出读保守估计9~10Gbps。一片DDR3-1600 x16位宽可以提供约12.8Gbps带宽勉强够用但我建议选128bit位宽DDR3/DDR4控制器的FPGA方案留出余量给刷新和仲裁。如果不需要整帧缓存只做行缓冲拼接那么线缓存大约一行数据量line_size W * 3 (字节) // 1080p为5760字节两个输入各需要一条线缓冲加上输出的行缓存总计不到20KBFPGA内部BRAM就能放下但仅适用于两路输入行时序能基本对齐的场景。我在项目中用这种方案做过两块720x1280的屏拼成1440x1280的输出两条输入的行同步信号对齐后效果稳定没出现过撕裂。3.4 时钟树与跨时钟域注意事项多路合一的另一大坑是时钟。两路输入时钟源不同输出时钟又不同中间必须有异步FIFO。曾经有个项目为了省资源我把两路输入的一小段信号直接接到输出级MUX上结果时序全都乱了画面整块整块地跳。后来老老实实做异步FIFO加水位监测问题才消失。时钟约束上也要注意MIPI RX核的参考时钟建议从可编程PLL输出不要用外部晶振随便乱配要理清bit clock和byte clock的关系比如D-PHY线速率1000Mbps时byte clock是125MHzFPGA逻辑大部分跑在byte clock域高速收发器内部才需要处理bit采样。另外多路输入时的复位设计也是要点。两路RX核的复位不能简单连在一起因为它们的CDR锁定时间可能不同。我通常给每路RX单独挂一个复位状态机检测到PLL锁定且RX同步后再释放避免其中一路还没就绪就把数据往合并逻辑里传。4. 实战落地RK3588平台上的多路MIPI屏适配4.1 RK3588的多路MIPI界面面观瑞芯微RK3588是不少国产板卡在显示控制项目里的首选它内部有多路MIPI DSI/CSI控制器官方BSP里对多屏拼接也有一定支持。实际调试时要注意一个逻辑外部FPGA合路输出到RK3588的某一DSI口后RK3588看到的是一个逻辑屏设备树仍然按照单屏去配置时序。如果你想像两个独立屏幕通过一个外部设备合在一起那样在系统中仍能看到两个framebuffer那就需要将合并显示的任务压在外部FPGA上让RK3588只输出一份完整的大画面。两类方案在设备树里的差异很大建议先明确主控侧到底是把合路设备当成单一显示器还是在软件层面做双屏扩展。4.2 设备树参数从双屏到单口显示的配置要点在RK3588 Linux下适配一块MIPI屏设备树的要点不算复杂但特别容易出问题。以下是我常用的配置思路。确认控制器节点通常是dsi0、dsi1这类节点打开对应节点设置compatible为panel-simple或具体屏厂驱动填写lane-count、lane-polarities等物理层参数配置display-timing重点是clock-frequency、hactive、vactive、各porch参数如果有初始化命令序列填入panel初始化部分。我放一个简化的设备树片段方便参考dsi0 { status okay; #address-cells 1; #size-cells 0; panel0 { compatible simple-panel; reg 0; backlight backlight; enable-gpios gpio RK_PC4 GPIO_ACTIVE_HIGH; pinctrl-names default; panel-timing { clock-frequency 66000000; hactive 720; vactive 1280; hback-porch 40; hfront-porch 80; hsync-len 24; vback-porch 14; vfront-porch 32; vsync-len 6; }; mipi_lcd_1 { mipi,cmd-type init; mipi,data-type 0x15; mipi,commands 0xB9 0xF1 0x12 0x83; }; }; };注意clock-frequency填的是像素时钟不是MIPI lane速率。很多新手在这一步写错比如把车道速率当像素时钟结果屏幕刷新率和颜色全都异常。像素时钟一般通过desired refresh rate和分辨率算出也可以从binlog或者原厂配置参考里直接抄。4.3 ST7701S驱动IC初始化踩坑记录ST7701S是我这几年用得比较多的LCD驱动IC它支持单口2-lane或4-lane MIPI输入常见分辨率是720x1280。网络上各个项目给出的初始化序列天天传真正到自己的板子上屏幕厂家不同、电源时序不同参数都要微调。我踩过几个印象很深的坑。首先ST7701S对第一个命令有特定要求大部分初始化序列以0xB9开头0xB9是用来使能扩展命令集的如果它没被正确发出后续寄存器一概不认。其次MIPI的LP到HS切换参数、以及输出极性配置要特别关注0xC0和0xFF这类寄存器。再者不要把对比度、色彩增强这类画质调试参数写进初始化序列它会让显示数据在像素层面多一层查表偏移出问题之后很难判断是调试参数改了还是协议链路不稳。调试过程中我习惯把初始化序列拆成两段第一段是所有屏共用的基础配置第二段是屏体相关的时序配置。这样换屏时只需要替换第二段排查问题也更快。4.4 调试顺序建议刚接触RK3588和MIPI屏的朋友我建议严格按照下面的顺序来调试免得绕远路。先把单屏点亮确认电源、I2C、命令序列都正常。再验证MIPI lane数据用示波器或逻辑分析仪抓HS进出场确认HS模式有正确的同步信号。然后把外部FPGA的多路合路输出接到同一点对比显示如果黑屏先查FPGA侧的DSI输出有没有按照RK3588预期的lane数和像素时钟发。最后才动设备树里的display-timing和初始化命令。按这个顺序走我还没有遇到过排查不出来的MIPI屏问题。反过来很多人一上来就同时调FPGA和SoC出了问题根本不知道是哪一端引起的。5. 常见误区与避坑清单含紫光同创FPGA实战5.1 误区一MIPI信号频率高直接用一个MUX切换芯片就行这个误区太常见了。高速MUX确实能切换差分信号但它做的事是选通不解决数据内容的协议问题。如果你的需求是两路之中的一路随时切换接入同一个主控口MUX可以如果你的需求是两路同时存在的画面叠加、拼接、融合输出给一路主控MUX完全做不到必须有协议处理。我在不少项目说明书里看到利用高速切换芯片实现双路MIPI信号复用这种说法本质上只覆盖了其中一路接入的场景根本没有实现合一。如果方案评审时有人这么写建议直接追问一句两路同时输入时切换芯片在忙什么5.2 误区二等长布线做好就不需要逻辑deskew等长布线能减少物理层面的偏斜但不能解决两个独立时钟源之间的相位差。我在紫光同创FPGA项目中用内部deskew逻辑巡检lane间offset即使两路输入走线差了100mil以上也能正常出图。等长布线当然要做但它不是协议级兜底。换句话说layout做得好是锦上添花逻辑内的deskew才是雪中送炭。实际上D-PHY接收核里的deskew更多是在靠逻辑反复检测lane上同步头的位置偏移。这个过程一旦跑通系统的鲁棒性会明显提升不会因为温度漂移或者连接器接触导致偶发性花屏。5.3 紫光同创FPGA做MIPI的三个注意点国产FPGA做MIPI最大的体验差异在工具链。紫光同创的PDS软件跟Xilinx Vivado的习惯不太一样我总结几个注意点。约束文件里差分引脚要写对IO标准如LVDS或mini-LVDS否则综合后引脚极性反了信号完全不通时钟约束要重点约束与MIPI相关的PLL输出时钟否则布局布线后的时序报告很难看频率可能跑不上去如果使用官方MIPI IP核尽量按Example Design调起仿真别从零手写D-PHY物理层。还有一点紫光同创的FPGA高速收发器对不同bank的差分信号支持有差异建议在芯片选型阶段就确认所选型号包含的serdes资源数量别到布板阶段发现资源不够再换芯片那真的会改到哭。5.4 常见问题的排查速查表现象可能原因排查方向画面全黑无信号lane极性反、设备树lane-count不对检查DSI与FPGA输出端的lane映射画面有条纹像素时钟与lane速率不匹配重新计算clock-frequency花屏协议层的ECC校验失败查数据包格式、字节对齐状态偶发闪屏异步FIFO溢出加大缓存深度加水位控制两路画面帧不同步帧缓存不足输出时序抖动增加DDR带宽调整缓存策略单路正常、合路后白屏两路输入的行场同步未对齐在FPGA内做时序同步校正这个表里的问题我基本都在实际项目中遇见过。特别是最后一个 单路正常、合路后白屏很多人查了半天以为是协议不对其实只是两路输入的行同步信号相位差太大在合并级没有做帧同步就强行拼接画面自然错乱。6. 结尾分享一点个人经验最后分享一个我自己的习惯。凡是遇到多路合一相关的需求我都先问客户一句你要的是链路层合路还是内容层合路链路层合路一根好一点的MUX芯片加合格的PCB就能搞定内容层合路无论如何都绕不开协议级处理。MIPI这套体系物理上可以靠物料堆叠解决一部分问题但真正常见的需求都压在了协议和时序这一层。所以我一直觉得MIPI多路合一不是普通转接线这句话是拿来提醒所有开发者的不要被转接两个字骗了背后全是协议工程师的头发。做了几年这类项目我最大的体会是先把协议理解到位再把缓存和时钟规划清楚剩下的无非就是一遍遍调试和验证。希望这篇总结能帮你在自己的项目里少掉点头发。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →