2. TI Sitara图形子系统架构

在 TI Sitara(如 AM335x、AM437x、AM57x 等)这类面向工业 HMI 的 SoC 中,“图形”并不是一个单独的硬件模块,而是一条从 CPU/GPU 到屏幕的完整数据通路。理解这条通路,是后续做图形加速、双缓冲、DMA 搬运和带宽估算的基础。本节把这条通路拆成五个关键角色:GPU、显示控制器(Display Controller)、DSS(Display Subsystem)、帧缓冲(Framebuffer)以及它们共同依赖的 DDR 内存带宽。

一、五个角色的职责边界

GPU 负责“画”。在 Sitara 系列中常见的是 PowerVR SGX 系列(如 SGX530),它执行 OpenGL ES 的绘制命令,把三角形、纹理、混合结果渲染成像素,写入一块内存区域。GPU 的输出不是直接给屏幕的,而是先落到内存里的渲染目标(Render Target)。

显示控制器负责“扫”。它按像素时钟节奏,从内存中读取已经准备好的图像数据,按行、按帧输出 RGB 或 YUV 时序信号。它不关心图像是怎么画出来的,只关心“从哪里读、读多大、什么格式、什么时序”。

DSS 是显示子系统的总称,通常包含显示控制器、图层管理器(如 LCDC 的多个 overlay)、时序发生器、像素时钟源以及到 PHY/引脚的输出路径。可以把它理解为“显示控制器 + 图层合成 + 输出接口”的集合体。在 AM335x 中,LCD 控制器就属于 DSS 的一部分。

帧缓冲是内存中的一块(或多块)像素缓冲区,是 GPU 与显示控制器之间的“交接区”。GPU 往里面写,显示控制器从里面读。它既是数据载体,也是同步点。

DDR 带宽是这条通路的公共资源。GPU 渲染要读写纹理、顶点、颜色缓冲;显示控制器每帧都要把整屏数据读一遍;CPU 还要访问代码和数据。三者共享同一套 DDR 控制器,带宽一旦被某一方占满,其他方就会等待,表现为掉帧、撕裂或延迟。

Sitara 图形数据通路:GPU → 帧缓冲 → DSS → 屏幕 GPU (SGX) 顶点/片元处理 纹理采样 · 混合 输出到渲染目标 帧缓冲 Framebuffer Buffer A(前台) Buffer B(后台) 格式:RGB565 / ARGB8888 地址:物理连续或 IOMMU 映射 DSS 显示子系统 显示控制器 LCDC 图层/Overlay 合成 时序发生器 RGB / LVDS 输出 LCD 面板 / 工业显示屏 像素时钟 · 行场同步 · 数据使能 DDR 内存与带宽仲裁 GPU 读写纹理/颜色缓冲 · LCDC 每帧读全屏 · CPU 访问代码数据 共享同一 DDR 控制器,带宽不足时出现等待与掉帧 关键参数:像素时钟 × 每像素字节数 × 刷新率 渲染写入 扫描读取 像素时序输出 纹理/缓冲读写 每帧全屏读取 双缓冲切换点 VSYNC 时交换前台/后台地址 带宽估算示例(假设值,用于理解量级): 1024×600 @ 60Hz,RGB565(2 字节/像素):1024 × 600 × 2 × 60 ≈ 73.7 MB/s(仅显示扫描读取) 若 GPU 同时以 30fps 渲染同尺寸 ARGB8888(4 字节/像素):1024 × 600 × 4 × 30 ≈ 73.7 MB/s(写入)

二、数据是怎么流动的

以一次典型的 HMI 界面刷新为例:应用调用 OpenGL ES 绘制一帧,GPU 从 DDR 读取纹理和顶点数据,完成光栅化后把像素写入后台帧缓冲。绘制完成后,应用通过 DRM/KMS 或 Framebuffer ioctl 提交页面翻转请求。显示控制器在下一个 VSYNC 到来时,把扫描地址从 Buffer A 切换到 Buffer B,于是新一帧被“扫”到屏幕上。整个过程里,GPU 写、LCDC 读、CPU 调度,三者都在争抢 DDR 带宽。

这里有一个容易被忽略的细节:显示控制器的读取是持续且刚性的。只要屏幕在刷新,它每帧都必须把整屏数据读完,否则就会出现欠载(underflow),表现为画面闪烁或花屏。而 GPU 的写入是突发且可调度的。因此,在带宽紧张时,系统通常优先保障显示扫描,GPU 渲染则可能被推迟,导致帧率下降。

三、帧缓冲的三种典型组织方式

第一种是单缓冲:GPU 直接画到显示控制器正在扫描的那块内存。成本最低,但绘制过程中屏幕可能读到“半成品”,出现撕裂。工业 HMI 中一般不用。

第二种是双缓冲:两块缓冲区,GPU 画后台,LCDC 读前台,VSYNC 时交换。这是最常用的方案,能消除撕裂,代价是内存占用翻倍,且交换时机必须与 VSYNC 对齐。

第三种是三缓冲:在双缓冲基础上再加一块,允许 GPU 在等待 VSYNC 期间继续渲染下一帧,减少 GPU 空转。代价是内存和延迟增加,适合对帧率稳定性要求高的场景。

四、内存带宽:最容易被低估的瓶颈

很多工程师在调 HMI 时只关注 GPU 频率和驱动,却忽略了带宽。实际上,当分辨率、色深、刷新率提高后,显示扫描本身就会吃掉可观的带宽。以 1024×600、RGB565、60Hz 为例,仅扫描读取就约 73.7 MB/s;如果 GPU 同时以 30fps 渲染 ARGB8888,写入又是约 73.7 MB/s;再加上纹理采样和 CPU 访问,总需求很容易超过 200 MB/s。对于 DDR2/DDR3 的 Sitara 平台,这个量级已经需要认真对待。

降低带宽压力的常用手段包括:降低色深(ARGB8888 → RGB565)、降低刷新率、使用 GPU 的 tile-based 渲染减少重叠写、把不常变的 UI 元素预合成到一张背景图、以及避免每帧全屏重绘。在 AM335x 这类平台上,还可以利用 LCDC 的硬件光标和 overlay 图层,把部分合成工作从 GPU 转移到显示控制器,从而减少 GPU 的读写量。

判断带宽是否成为瓶颈,可以观察三个现象:一是 GPU 渲染时间正常但帧率上不去;二是画面在动画时出现规律性抖动;三是系统日志中出现 LCD underflow 或 sync lost。此时应优先检查显示扫描带宽和 GPU 写入带宽的叠加值,而不是盲目提高 GPU 频率。

五、DSS 与显示控制器的配置要点

在设备树中,DSS/LCDC 节点通常需要配置像素时钟、时序参数(hactive、vactive、hfront porch、hsync、vfront porch、vsync)、输出格式和帧缓冲地址。以 1024×600 面板为例,典型时序为:hactive=1024,hfp=40,hbp=40,hsw=20;vactive=600,vfp=10,vbp=10,vsw=5。像素时钟约 45 MHz 左右(具体以面板手册为准)。这些参数一旦配错,屏幕会不亮、偏移或抖动。

帧缓冲的物理地址必须与显示控制器对齐。在启用 IOMMU 的平台上,GPU 使用虚拟地址,而 LCDC 通常需要物理地址或经过映射的地址。双缓冲切换时,要确保新地址已经写完并且 cache 已刷到 DDR,否则屏幕可能读到旧数据或未完成的数据。这是实际调试中最常见的“画面不动”或“画面错位”原因之一。

六、把五个角色串起来看

回到整体:GPU 是生产者,帧缓冲是仓库,DSS/LCDC 是消费者,DDR 带宽是运输能力。生产、仓储、消费、运输四者必须匹配。任何一个环节成为瓶颈,最终都表现为屏幕上的异常。理解这条链路之后,后续做 OpenGL ES 加速、DRM 页面翻转、DMA-BUF 共享以及带宽优化时,就能明确每一步在改什么、影响谁。