当前位置: 首页 > news >正文

●从零理解 DSI 屏幕撕裂:一条数据流水线的故事

1. 整个系统在干什么

你的板子在做一件事:把 HDMI 输入的画面缩小后,显示在一块 MIPI DSI 小屏幕上。

数据流是这样的:

HDMI 源(笔记本) → rk628 芯片 → DSI 面板
720×720 (缩小到) 360×360
41.877 MHz 360×360 11 MHz

rk628 内部有一个缩放器(Scaler),负责把 720×720 的帧缩小成 360×360。缩放器输入侧跑 HDMI
时钟(41.877MHz),输出侧跑 DSI 时钟(11MHz)——这就是一切撕裂的根源。

---
2. 为什么要缩放?为什么时钟不一样?

HDMI 源输出的是 720×720@60fps,像素时钟 41.877MHz。你的面板只有 360×360 像素,它的
datasheet 规定像素时钟必须是 11MHz。如果让面板直接接收 720×720
的信号,它根本显示不了——分辨率不匹配,时钟也不匹配。

所以缩放器必须介入:用 41.877MHz 的速度读入一帧,用 11MHz
的速度缩放后写出到面板。两个速度不一样,缩放器内部有一个叫 FIFO(先入先出缓冲区)
的东西来缓冲数据。

读写比值是 41.877/11 ≈ 3.8:1,意味着缩放器每 1 个像素写出,就要读入约 3.8 个像素(其中
2.8 个被缩小算法丢弃了,因为 720→360 是 2:1 缩小)。

---
3. 撕裂是怎么发生的?

直观类比:想象两台跑步机并排放着,左边跑 41.877 km/h,右边跑 11
km/h。你在左边的跑步机上画一幅画,画完传给右边继续画。左边的人画得快,右边的人画得慢。如
果两边没有任何同步信号,右边的人可能在你画到一半就开始往面板上"发表"——结果就是:

面板显示的画面:
┌──────────────────┐
│ ← 第 N 帧内容 │ ← 上半部分正常
│ │
├──────────────────┤ ← 这就是"撕裂线"
│ ← 第 N+1 帧内容 │ ← 下半部分是下一帧
└──────────────────┘

在 DSI video mode 下,缩放器不需要等面板说"我准备好了"——它按固定的 60fps
节奏持续往面板灌数据。如果缩放器内部的 FIFO 在某一个瞬间恰好读完旧数据、塞入新数据的时候
和面板的扫描线重合,屏幕上就会出现新旧帧各占一半的撕裂。

轻微撕裂是因为 FIFO 大小足够深(缓存了若干行像素),新旧数据切换的时机绝大多数时候落在消
隐区(面板不显示的区域),偶尔被扫描线抓到。

---
4. Command Mode vs Video Mode

这是 DSI 协议的两种传输模式:

Video Mode(视频模式):
- DSI 控制器像 HDMI
一样,按固定时序(hfront/hsync/hback/vfront/vsync/vback)不停地发像素
- 面板被动接收,不受面板内部控制
- 优点:简单,不需要额外同步信号
- 缺点:不理会面板内部刷新状态,容易撕裂

Command Mode(指令模式):
- DSI 控制器只有收到 write_memory_start 指令时才发一帧数据
- 面板刷完一帧后通过 TE(Tearing Effect)引脚发信号:"可以发下一帧了"
- 优点:永不撕裂(严格同步)
- 缺点:需要 TE 引脚硬件连接

你一开始的 dsi,video-mode 走的是 video mode。去掉之后走 command mode。但你没有 TE
引脚——面板虽然内部配置了 TE,但 rk628 芯片收不到——所以 command mode
变成了"没有同步信号的盲发模式",撕裂仍然存在(只是位置变了)。

---
5. Blanking Porch 到底在干什么?

每显示一帧,面板都会经历这样的过程:

← visible area → ← 消隐 →
┌──────────────────────────────┐
Scan ──→│======= 显示区 =======│ HSync │←── 一行结束,回扫
└──────────────────────────────┘
hdisplay hfp/hsync/hbp

← visible area → ← 消隐 →
┌──────────────────────────────┐
Frame──→│======= 显示区 =======│ VSync │←── 一帧结束,回扫
└──────────────────────────────┘
vdisplay vfp/vsync/vbp

消隐区(Blanking) 就是面板不显示的区域——电子束(或数字扫描指针)从一行末尾回到下一行开
头、从一帧底部回到顶部的时间。

那 blanking porch 和撕裂有什么关系?

缩放器的 FIFO 每次从"旧帧→新帧"切换数据时,会产生一个"脏数据窗口"。如果这个窗口能和消隐
区对齐,就算新旧数据混在一起也不会显示出来——因为消隐区面板本来就不显示。

这就是我调 vback-porch / vfront-porch 的原理:

- 调大 vback-porch:让消隐区更长,把撕裂线推到消隐区里藏起来
- 调大 vfront-porch:消隐区位置移动,看撕裂线能不能被覆盖
- 但 vtotal = vactive + vfp + vsync + vbp 是固定的(由 clock / htotal / 60fps
决定),所以加大 back 就要减 front
- 最终目标:把撕裂线推到 vfp+vsync+vbp 覆盖的区域里,不让它在显示区出现

---
6. 为什么自测模式不撕裂?

rk628 的自测模式(Color Bar)是芯片内部生成纯色条纹,直接输出到 DSI
发送器——完全绕过了缩放器和 HDMI 接收器。没有跨时钟域问题,没有
FIFO,没有新旧帧切换——所以永远不撕裂。

这也反证了:你的 DSI PHY、lane
配置、面板本身的初始化都是对的。问题只在缩放器的跨时钟域同步上。

---
7. 为什么改了 hsync-active / vsync-active 撕裂位置会变?

缩放器内部有一个函数叫
calc_dsp_frm_hst_vst,它计算缩放器从输入帧的哪个位置开始读取数据。这个计算依赖于 src/dst
的 hsync/vsync 极性、htotal、vtotal、时钟频率等参数。

改变极性相当于改变了缩放器识别的"帧起点"。帧起点变了,FIFO
新旧数据切换的时机就变了,撕裂线的位置也跟着变了。这在调试上是一个信号:你对时序的任何微
调都在影响撕裂位置,说明你还没有找到精确的对齐点,但方向是对的。

---
8. 最终的解决方案分层

┌─────────────┬─────────────────────────────┬─────────────────┬────────────────────┐
│ 方案 │ 原理 │ 效果 │ 前提 │
├─────────────┼─────────────────────────────┼─────────────────┼────────────────────┤
│ 接 TE 线 │ 面板每帧结束发脉冲,主机严 │ 彻底消除 │ 需要硬件 TE 引线 │
│ │ 格同步 │ │ │
├─────────────┼─────────────────────────────┼─────────────────┼────────────────────┤
│ 调 blanking │ 让 FIFO │ 可消除肉眼可见 │ 需要精确计算/反复 │
│ │ 脏数据窗口落入消隐区 │ 撕裂 │ 调试 │
├─────────────┼─────────────────────────────┼─────────────────┼────────────────────┤
│ 改 dst │ 让输入输出时钟域成整数倍 │ 降低 FIFO │ 面板 datasheet │
│ clock │ │ 碰撞概率 │ 通常不允许 │
├─────────────┼─────────────────────────────┼─────────────────┼────────────────────┤
│ 双缓冲/帧缓 │ 写完一帧再读 │ 彻底消除 │ rk628 │
│ 冲 │ │ │ 硬件不一定支持 │
└─────────────┴─────────────────────────────┴─────────────────┴────────────────────┘

你的情况是:TE 没有,clock 不能改,只能调
blanking。这个调试过程本质是用消隐区去"盖住"撕裂线,反复调 vback/vfront/vsync
就是在移动盖子。

http://www.jsqmd.com/news/1106881/

相关文章:

  • 微信聊天记录备份指南:如何安全保存你的数字记忆?
  • AI缺席的艺术:守护留白的智能
  • 通过 Reqable 处理 MessagePack 请求与响应:实战指南与代码优化技巧
  • 所谓同步,指的是协同步调。
  • 2026年东莞食堂承包公司最新排名 挑选靠谱合作方看这份就足够
  • 全媒体广告投放中,如何用“数据归因”打破跨平台流量壁垒?
  • 【窗口函数】ROWS_NUMBER练习题
  • 别再忽视文档了:用AI知识管理实现同源多站发布,降低成本提升信任
  • 看门狗定时器WDT讲解
  • 重庆綦江家具行业的人才培养之道:以专业赋能,铸就本土服务标杆
  • Windows 11系统精简终极指南:使用tiny11builder让旧电脑焕发新生
  • 实验结果“看天吃饭”?抗体批间差异的根源剖析
  • 居民社区小程序积分系统模板分享
  • KLayout完整指南:如何免费打造专业级版图设计流程
  • Shell脚本精读 · S06-03 | 条件与控制流综合:读 30 行脚本的判断链
  • python Flask开发基础教程
  • Phalcon Compliance:高性能链上合规引擎,守护 Web3 的信任与增长
  • 2026 年目前哪个 GEO 优化系统功能最全面?
  • 一个没做安全防护的IoT设备,被客户骂了一下午
  • Diablo Edit2:5大核心技术突破重塑暗黑破坏神II角色编辑体验
  • 终极跨平台B站观影指南:让你的游戏机变身视频中心
  • 洛谷-P11403 [RMI 2020] 软盘 / Floppy 题解
  • 高光谱相机全解析:技术分类、主流品牌与选型指南
  • 连锁超市收银系统选什么?四大品牌深度横评与避坑指南
  • Java Stream、File与IO-核心场景实战
  • NifSkope 3D模型编辑器:专业游戏模型处理完全指南
  • 国内物流包装垂直随机振动试验优先选用 GB/T 4857.23-2021 附录 D 说明
  • 【课程设计/毕业设计】基于 SpringBoot 的校园日常行为规范评分归档系统的设计与实现 基于 SpringBoot 的中小学学生品行综合考评管理系统【附源码、数据库、万字文档】
  • 越华环保集团资质元数据治理体系与项目准入校验架构设计
  • 第一章Netty,Selector写入内容过多问题