ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

深入解析MIPI DSI与CSI-2:物理层共享与协议层的本质分水岭

2026/9/17 8:04:06 拓冰建站 浏览量
深入解析MIPI DSI与CSI-2:物理层共享与协议层的本质分水岭 1. 从一个常被误读的标签说起搞显示和摄像头的工程师大多见过这两张图一张是手机屏幕模组背面排线一端伸进屏幕玻璃另一端贴着 SoC另一张是摄像头板卡感光芯片旁边拉出几条差分对线到主控端。前者写着 DSI后者写着 CSI-2。许多刚入门的朋友跑来问我“DSI 和 CSI-2 不是差不多吗反正都是 MIPI接口看起来都一样把他们当成双向口对待行不行”这个问题我听过太多次了。包括我自己刚做嵌入式显示时也被这两兄弟坑过仗着懂 DSI上手就去调 CSI-2结果被时序和包结构折腾得够呛。后来在方案公司连轴调试了两年模组才慢慢摸清这所谓“孪生协议”背后本质性的差异。本文继续我们“深入 MIPI DSI 显示技术栈”系列这次专门把 DSI 和 CSI-2 拉到同一张桌子上逐层拆讲它们看似相同的底层物理架构以及走向截然不同方向的分水岭。如果你正准备做 FPGA 接入 MIPI、想理解 DRM 驱动中竖屏改横屏为什么跟协议时序相关或者单纯被 ST7701S 这类 DSI 屏幕的初始化代码吓到那么这篇内容应该能帮你把碎片拼成一个完整的底座。我尽量把话讲得直接该贴曲线的贴曲线该给代码的给代码不整虚的。咱们从最底层的物理层开始一步步往上走到协议帧再看它们分别在显示链路与摄像头链路上是怎么“换班”的。2. 共享的物理血脉D-PHY 与包结构2.1 D-PHY先记住共同的底层词汇不管是 DSI 还是 CSI-2它们传输数据用的大多数是同一套 MIPI D-PHY 物理层规范。D-PHY 最简单的描述就是用一对差分信号线传时钟每一对差分线传一个数据 Lane数据通道数据 Lane 可以有1条、2条、4条加起来用。为了让信号有确定的参考点发送端在进入高速模式时会先发出一段 LP-000 到 LP-111 的进入序列随后推上两根线上的差分电压形成高压摆快速跳变的 HS 差分信号。很多初学者拿到一份屏幕规格书看到 MIPI_D0P、MIPI_D0N、MIPI_CLKP、MIPI_CLKN 就发怵。其实这就是 D-PHY 在硬件上的全部家当一对时钟、最多四对数据。至于 CSI-2 侧摄像头模组同样会把它的输出接到主控的 MIPI_CSI_RX 引脚上同样也是时钟差分对加数据差分对。这个物理层的一致性是它俩被称作“孪生”的根源。所以如果只是在电路图上看到接口定义你很难第一时间分清 DSI 和 CSI-2。真正的判定逻辑在于这条链路谁发时钟、谁收数据以及协议层在启动后怎么对齐 Lane。举个例子DSI 是主控端主动产生时钟并送往屏幕CSI-2 虽然是摄像头传感器主动送数据回来但时钟仍然由传感器侧发送主控只需要按接收方要求配置 lane 数量和速率匹配。本质上两条链路的源端不一样但 D-PHY 那套 LP/HS 切换规范是完全复用的。2.2 高速模式与低功耗模式的切换假设你现在拿示波器去点 DSI 或者 CSI-2 的时钟通道大概率会看到这样一段波形一段时间电平停在低位然后忽然出现十几纳秒的跳变序列紧接着是一长串连续翻转的差分方波最后又落回低电平。这个“低电平——高速差分方波——低电平”的过程就是 D-PHY 的 LP 模式与 HS 模式切换。LP 状态下D-PHY 用单端电平传控制信息电压摆幅很小目的是省电HS 状态下两条差分线进入差分驱动模式速率大幅拉高数据真正开始跑。解析进入 HS 的序列时我建议直接拿逻辑分析仪抓 T-LPX、THS-PREPARE、THS-ZERO 这些时间参数。DSI 屏幕规格书通常会给出一个最小 T-LPX 要求比如 50nsCSI-2 传感器文档则可能要求更严格的 T-LPX 上限因为传感器端往往对时序抖动更敏感。很多新手在 FPGA 里搭建 D-PHY 发送逻辑时热衷于把差分信号第一时间拉到满幅却忽略了进入序列时长过短会导致接收端同步失败。我第一次调 ST7701S 屏幕时画了近一周的板子加电后屏幕只有背光没有画面正是因为在进入序列上偷了 10ns。2.3 包结构的相同基因短包与长包再上一层的包结构DSI 与 CSI-2 也长得几乎一模一样都使用 8bit 数据类型的短包Short Packet和长包Long Packet。短包由 4 个字节组成数据标识Data Type、两个数据字节、一个 ECC 字节长包则在包头之后接上若干数据字节再以 16bit CRC 作为包尾。如果你之前接触过 DSI 驱动代码打开 ST7701S 的初始化数组会看到类似 0xE0、0x11、0x29 这种命令序列里面很多其实都是 DCS 写短包命令。而 CSI-2 抓包时你会看到大量 Frame Start帧起始、Frame End帧结束短包穿插在整个图像数据流之间。可见短包承载控制与同步信息长包承载像素或图像数据这层基因两兄弟是同一个模板。但为什么到了更高协议层一个跑去控制屏幕另一个跑去传图像呢关键在于它们的设计使命——DSI 本质是“显示命令与像素的公路”CSI-2 本质是“传感器数据的传送带”。底层长得再像往上走就会分道扬镳。3. 本质差异第一刀数据流方向与传输目标3.1 单向链路背后的设计动机在电子系统里最简单也是最重要的区别就是方向。如果让我用一句话概括 DSI 与 CSI-2 的本质差异那就是DSI 是下行链路DownlinkCSI-2 是上行链路Uplink。这句话看着简单实际上决定了后面所有控制模型、包定义、时序设计的走向。DSI 的主处理器永远是发送方屏幕面板永远是接收方。这意味着链路建立后SoC 的 DSI 控制器按预定的行、场时序不断打包像素长包通过 D-PHY 发送给屏端驱动 IC。屏幕从不主动发起数据传输最多通过 Acknowledge应答回传一两个状态比特或者通过 I2C 的 CCI 接口回读寄存器。反过来CSI-2 的传感器是发送方主控 SoC 是接收方。传感器按帧率不断输出整帧图像数据主控需要准备好足够大的接收缓冲区并在每一帧的 Frame Start 包到来时开始采集。有些朋友会觉得“那我把 DSI 和 CSI-2 接到一起不还是能点亮屏幕吗”——硬件上也许差分信号能连通但协议层面你缺了最关键的东西DSI 的时序包需要主控严格按照消隐区插入 HSA/HBP/HFPCSI-2 则默认不存在这种行消隐概念它只会按帧速率打断。你把一个 DSC 压缩的 CSI-2 流接到 DSI 接收端屏端根本解析不出有效像素屏幕上出来全是噪声。3.2 屏幕时序与传感器帧结构的核心差别DSI 在视频模式Video Mode下几乎就是把传统 RGB 并行接口的时序翻译成了串行差分格式。每一行数据发送前控制器会先发一个 HSSHorizontal Sync Start短包然后发送 HBPHorizontal Back Porch时长对应的消隐数据接着发送像素长包最后是 HFPHorizontal Front Porch。这种结构保证屏幕驱动 IC 能从一串连续字节流中准确恢复出每一行的起始位置和有效像素长度。而 CSI-2 根本不关心“行”的概念它只关心“帧”。数据流以 Frame Start 短包开始紧接着传输整个图像传感器的所有行数据最后以 Frame End 短包收尾。在帧内部CSI-2 还允许嵌入行号、曝光时间、增益等元数据这些在 DSI 的视频模式里几乎见不到。这么设计的原因很实际显示面板需要严格控制行同步信号否则画面会产生撕裂、偏色、滚动条而摄像头传感器只要保证每一帧完整行数据可以由接收端自行重新排列因为后端 ISP 往往需要整帧才能完成去噪、插值。所以你会看到DSI 在驱动层特别强调时序参数CSI-2 则在驱动层强调缓冲区管理和帧同步。3.3 用户视角下的“孪生”如何走向不同工具链正因为方向与目标不同针对 DSI 的调试工具更关注显示时序波形和初始化序列针对 CSI-2 的调试工具则更关注数据速率、帧同步信号和图像质量。网上搜“MIPI 时钟波形”能看到很多人拿着示波器去测 DSI 时钟通道观察 HS 频率是否与面板要求的像素时钟匹配。而搜“MIPI CSI 调试”大家讨论的重点往往是曝光不生效、图像有一条绿线、或者信号质量导致的花屏。这两个问题的本质已经不再是“MIPI 协议一家人”能解释的了。你需要理解 DSI 的链路控制能力才能校准行场时序你需要理解 CSI-2 的物理层鲁棒性才能解决高速传输抖动。我在后续章节里会沿着这条线继续拆。4. 命令通道与控制模型CCI 与 DCS 的南辕北辙4.1 DSI 的命令模式与 DCS 指令DSI 协议一个非常重要的特征是支持命令模式Command Mode。所谓命令模式可以理解为 SoC 直接向屏幕上挂着的寄存器写入参数屏幕芯片根据这些参数决定刷新方式、扫描方向、色彩格式等。这块通常通过 DCSDisplay Command Set指令完成例如 0x06 表示进入睡眠模式0x11 表示退出睡眠0x29 表示打开显示。网上关于 ST7701S 的初始化序列本质就是一堆 DCS 写指令的组合。我摘一段常见代码static const struct st7701s_cmd st7701s_init_cmds[] { {0xFF, 0x77, 0x01, 0x00, 0x00, 0x10}, {0xC0, 0x3B, 0x00}, {0xC1, 0x0D, 0x02}, {0xC2, 0x31, 0x05}, {0xC3, 0x15, 0x0A}, {0xC4, 0x20, 0x08}, {0xC9, 0x00, 0x00}, {0xCD, 0x08}, {0xE1, 0x10, 0x00}, {0xE3, 0x00, 0x00}, };这段命令不是随便填的它对应了 ST7701S 内部电源、时序、Gamma 等多个模块。DSI 控制器在发送这些命令时会根据目标是 6 位还是 8 位数据长度选择 DCS 长写包 0x39、短写包 0x05 等类型。换句话说DSI 不仅承载像素流还承载控制流这和它作为显示链路的主控权是分不开的。4.2 CSI-2 的控制流走 I2CCSI-2 在物理链路之外的另一个协议通道是 CCI也就是 Camera Control Interface本质上就是标准的 I2C 总线。摄像头传感器的寄存器配置比如曝光时间、增益、输出分辨率全部通过 I2C 写入。因此传感器厂商提供的 datasheet 里往往有一个长长的寄存器表但你很少能看到类似 DSI 的 DCS 指令数组。这就造成了很大的调试习惯差异DSI 屏幕不亮时你会先查初始化命令有没有正确发出去使用逻辑分析仪去核对 MIPI 总线上的短包内容CSI-2 模组出图异常时你先怀疑 I2C 配置是否生效或者时钟频率与数据速率是否匹配。光谱迥异但背后都是“主控如何控制远端芯片”的两种不同路线。4.3 回读与应答能力的差异DSI 是允许少量回读数据的。屏幕驱动 IC 可以通过 Acknowledge 信号在 BTABus Turnaround机制下把数据交回主控。这项能力在屏幕初始化后经常用来读取错误状态寄存器但注意DSI 的视频模式为了避免打断画面通常很少频繁切换 BTA。除非你显式驱动控制器进入命令模式并请求响应否则屏幕一般不会主动发数据。CSI-2 则根本没有这种“反向”通道设计。图像数据永远从传感器流向主控寄存器配置永远从主控流向传感器互不交叉。这从物理拓扑上就决定了 CSI-2 链路是绝对的单向数据流而控制信号完全依赖额外 I2C 总线。很多项目会把 I2C 挂在同一个连接器上但 I2C 并不是 MIPI 链路的一部分只是和 CSI-2 并行存在。理解这一点后你再回头去看“MIPI DSI 竖屏改横屏显示”这类驱动开发需求会发现问题往往落在两层一层是 DSI 控制器发送的初始化命令里是否设置了扫描方向另一层是 DRM 驱动里是否反转了坐标轴。它们看着都和“MIPI”相关但你们真正需要调的是协议内容而不是物理时序。5. 从协议到实际工程C 代码、DRM、VBT 与竖横屏5.1 用 DSI 面板驱动串起整个链路ST7701S 实例当你在 Linux 内核 DRM 子系统里写一个 DSI 屏幕驱动工作通常分成三步第一步通过 DSI 命令模式发送初始化寄存器序列第二步提供一组 display timing时序参数告诉 DRM 核心该以什么节奏向面板刷新数据第三步在 mode_set 阶段使能 Video Mode让 DSI 控制器按 timing 参数持续输出像素流。以 ST7701S 为例常见的 480x854 屏幕初始化完成后mode_set 阶段会设置水平有效像素 480、垂直有效 854以及 hfp、hsync、hbp、vfp、vsync、vbp 等边界值。当初我为这款屏调竖屏转横屏显示时折腾了很久才明白DRM 里的 mode 结构体可以通过调整 rotation property 来设置 DRM_MODE_ROTATE_90但屏幕驱动 IC 内部的扫描方向也需要相应改变否则就会出现坐标轴错位和图像镜像问题。// DRM panel helper 中常见的时序配置示例 static const struct display_timing st7701s_timing { .pixelclock { 24500000, 27150000, 30000000 }, .hactive { 480, 480, 480 }, .hfront_porch { 17, 20, 23 }, .hsync_len { 1, 2, 3 }, .hback_porch { 34, 40, 44 }, .vactive { 854, 854, 854 }, .vfront_porch { 8, 10, 12 }, .vsync_len { 1, 2, 3 }, .vback_porch { 12, 16, 20 }, };这里需要格外注意的是 pixelclock。许多人以为屏幕是 480x854刷新率 60Hz乘一下就完事但实际上行消隐和场消隐都会占用带宽。例如上述结构体里水平总周期约为 48020240542垂直总周期约为 85410216882那么实际 pixelclock 542 * 882 * 60 ≈ 28.7MHz。你如果只按 4808546024.6MHz 设置DPHY 时钟跟不上需求屏幕边角就会出现偏移甚至闪烁。5.2 VBT你问的那串“MIPI 时序导入 BIOS”有人搜“如何将 MIPI 的时序导入 BIOS 的 VBT”这个属于 x86 平台下比较冷门的高级玩法。VBT全称 Video Basic Table是主板 UEFI 固件里存放显示模式相关参数的结构。Intel 的 DSI 方案在早期并不像 ARM SoC 那样灵活内核驱动在初始化 MIPI 面板时需要从 VBT 里读取面板的时序、接口类型、端口掩码等信息。如果你想在 Windows 下点亮一块自定义分辨率的面板通常需要修改 VBT 并重新刷入 BIOS将 active width、height、refresh rate、lane count 等都写成你要的数值。Linux 下则更推荐直接在 Device Tree 里描述信息绕开 VBT 的机制。操作层面先用工具把 BIOS 镜像解包找到 VBT Header再改对应偏移处。这件事风险极高操作不当可能导致主板无法点亮内置屏幕建议只在备机上折腾并且一定预先备份固件。我的体会是与其去改 VBT不如在驱动侧绕过它。现在很多开源内核补丁会主动忽略 VBT 里的 MIPI 参数改用模块加载参数或 DMI quirk 覆盖。VBT 更适合作为 ODM 出厂默认配置不适合做太多运行期修改。5.3 DRM 中竖屏与横屏的坐标变换回到竖屏改横屏这个高频需求。DRM 驱动里屏幕的旋转通常分为三种实现层面第一层是面板驱动 IC 初始化指令里的扫描方向这是最低层第二层是 DRM 核心的 rotation 配置会调整 KMS 扫描输出坐标第三层是应用层比如 X11 或 Wayland 合成器里也会做旋转。如果你只在应用层旋转而面板驱动 IC 没有同步修改扫描方向那么屏幕刷新方向不会真正变化最终图像要么花屏要么坐标错乱。最可靠的路径是在 panel 驱动初始化序列里把 ST7701S 的扫描方向寄存器改为横屏模式同时在 DRM connector 上设置 rotation 属性让 framebuffer 的扫描方向和显示面板方向一致。两个方向必须严格匹配否则你看到的会是上下颠倒或镜像内容。// DRM 连接器设置旋转属性示例 struct drm_connector_state *conn_state ...; conn_state-rotation | DRM_MODE_ROTATE_90;从协议角度理解DSI 这条链路本身并不区分竖屏或横屏所有旋转信息都藏在命令内容和驱动配置里。CSI-2 摄像头侧没有类似“屏幕旋转”的概念它只是把感光芯片的原始像素按帧序排列ISP 端再根据 sensor mounting 角度做 90/180/270 度的旋转。6. FPGA 实现与电气级调试Retimer、时钟波形的硬核挑战6.1 为什么 FPGA 实现 MIPI 容易发疯“FPGA 实现 MIPI”这个词条常年热门。FPGA 的优势是灵活能用逻辑自定义包结构但 MIPI D-PHY 对高速差分信号有极严格的要求一般 FPGA 普通 GPIO 根本跑不了 1Gbps 以上的差分速率。你需要在 FPGA 里例化厂商提供的 PHY 硬核或软核比如 Xilinx 的 MIPI D-PHY IP、Lattice 的 MIPI D-PHY 核再配合 PCB 上严格的差分走线等长控制才有可能把 MIPI 链路稳定跑起来。更现实的做法是用转换芯片把 MIPI 转成并行 RGB 接口再进 FPGA。我做过一个项目主控端只有 MIPI DSI 输出面板是传统 24bit 并口 RGB中间用 SSD2828 把 DSI 转成 RGB 并口信号之后 FPGA 从并口读取像素。这种方案避开了 FPGA 直接串行解串的高速难题调试难度直线下降。如果你执意用 FPGA 直接实现 MIPI建议先吃透 D-PHY 的基本时序参数T-LPX、THS-PREPARE、THS-ZERO、THS-TRAIL、TCLK-PREPARE 等等。在 RTL 代码里这些参数要么用本地时钟计数实现要么从外部寄存器配置。我见过太多人把 THS-ZERO 配成 0结果接收端根本没有足够的建立时间链路偶发失步。6.2 Retimer 与信号完整性“MIPI retimer”是高频关键词。Retimer 和 Redriver 是两种不同的信号补偿方案。Redriver 只是简单地调整驱动电压摆幅和预加重但它不能恢复时钟Retimer 内部有 CDR时钟数据恢复功能相当于把信号重新整形、重新定时。对于长走线或者经过连接器的 MIPI 链路使用 Retimer 能显著降低抖动。不过 Retimer 不是万能的。若你的 DSI/CSI-2 链路本身速率过高超过 Retimer 支持的上限照样会引入额外时延。选型时注意看它是否支持你要的 D-PHY 版本是 D-PHY v1.2 还是 v2.0lane 数是否足够。市面上很多 Retimer 面向 C-PHY如果你用 D-PHY 接口就要特别核对配置。用示波器看 MIPI 时钟波形时除了扫幅值还要看眼图的“眼睛”是否张开足够大。高速差分信号经过长线缆后如果眼图中心区域小而模糊多半是信号完整性问题Retimer 或改善阻抗匹配能救回来但再多的软件配置也救不回来。这条路没有任何捷径可走。6.3 DSI Studio 与 CSI 调试工具的使用经验DSI Studio或者说同类协议的调试上位机是显示链路调试的好帮手。它通常能连接到 DSI 分析仪或模拟器读取链路初始化序列、发送 DCS 命令、模拟视频模式时序。你可以在 PC 上先把初始化序列跑通再把同样的命令应用到嵌入式平台能省下很多刷机时间。CSI-2 调试则更依赖逻辑分析仪和示波器专门的 CSI-2 分析仪能抓取带时间戳的帧头和帧尾包。排查 CSI-2 无图或者图像错乱时我习惯先抓时钟线波形确认频率再看数据 Lane 是否有接收错误。socket 上偶尔出现的 CRC 校验错误多半是因为物理层长度不匹配或串扰而不是协议写错。7. 常见问题排查速查显示与摄像头链路怎么对症下药在实际调试中把 DSI 和 CSI-2 混为一谈导致的问题往往很典型。我整理了一张速查表按症状、方向、排查动作列出症状链路类型优先检查项屏幕只有背光无画面DSI初始化命令是否发送成功HS 时钟是否输出先看 DCS 写包是否被屏端 ACK 拒绝屏幕画面有残影或滚动DSI时序参数HFP/HBP/VFP/VBP是否正确pixelclock 是否满足实际总周期计算画面上下颠倒或镜像DSI扫描方向寄存器配置DRM rotation 是否设置正确两者是否一致屏幕不时闪一下DSI是否突发插入了 BTA 操作视频模式是否被打断LP 切换频繁触发摄像头不出图CSI-2I2C 是否读到 sensor ID时钟线频率是否在规格内CSI-2 接收端 lane 数是否匹配图像有花屏或撕裂CSI-2数据 Lane 差分走线等长示波器查眼图CRC 错误率偶发掉帧CSI-2主控 DMA 带宽是否足够帧缓冲是否不够大是否在帧传输中读到缓冲区备份排查 DSI 时我特别喜欢在驱动里加一条读取屏端状态寄存器的命令通过 DCS 回读确认屏是否进入正常状态。比如很多 IC 会有 0x0A 表示读状态如果返回值和期望不一致基本可以判定初始化序列没生效。CSI-2 侧则不太需要在线读寄存器因为 I2C 一直能读写主控对 sensor 的状态其实非常透明。还有一个坑是“Lane 数不匹配”。DSI 屏有 1-lane、2-lane、4-lane 多种配置CSI-2 摄像头也有 2-lane、4-lane 之分。主控的 D-PHY 接收/发送端必须和另外一侧保持一致。很多新手把模组连上后软件没设置 lane 数结果用默认的 4-lane 模式实际却只接了 2-lane链路完全无法建立。关于 MIPI 时钟波形我一定要再强调一次MIPI 接口引脚定义图上除了时钟差分对、数据差分对还存在 LP 信号逻辑分析仪不会撒谎示波器探头一定要用差分探头单端探头带来的地弹噪声会让你误判信号质量。实际测 ST7701S 屏的时候单端探头看到的是满满噪声差分探头一上去眼图立刻清晰了。驱动层面还有一个高频问题CSI-2 的嵌入数据格式没打开导致主控解析出来的帧有元数据干扰。CSI-2 允许传输嵌入式数据Embedded Data这些数据通常跟着 Frame Start/End 短包后面。如果 ISP 的 DMA 配置没有跳过这些字节图像里就会混入怪异数据条带。解决办法是查看 sensor 手册确定嵌入式数据长度并在 CSI-2 接收控制器里配置对应的可跳转字段。最后说一点关于“本质差异”的个人理解。底层的 D-PHY 一样包结构相似这是 MIPI 联盟刻意设计的复用性降低芯片成本也降低工程师学习门槛。但 DSI 一定要服务好显示面板所需的严格行场时序CSI-2 一定要适应传感器流数据的突发性与帧完整性。这个目标分工造成了控制接口、包类型、同步策略、回读方式一系列差异。平时做项目时我的选择标准也很简单凡是需要把像素内容送到屏幕上的老老实实看 DSI 的视频模式和命令模式凡是需要把传感器图像抓回来处理的走 CSI-2 并认真确认物理层信号质量和 DMA 带宽。不要因为“长得像”就在硬件上拿 DSI 口接 CSI-2 传感器也不会被“MIPI 一家亲”这种话说服。如果要问我后续还能往哪个方向深入我建议可以先从 C-PHY 入手它和 D-PHY 的关系就像串行与并行观念的再一次革命或者研究 DSI 的 DSC 压缩流它跟 CSI-2 的 RAW 数据在压缩策略上的差异同样能带来新的思考。踩过这些坑之后你会更理解 MIPI 联盟为什么在两条链路之间反复复用底层规范却又始终保留着各自协议层中的那一堵墙。