概览¶
规划图形架构¶
本指南介绍如何在 SF32 器件上构建响应迅速、交互流畅的图形用户界面,重点讨论影响实际产品的工程决策:显示屏选型、帧缓冲策略、LVGL 集成、ePicasso 硬件加速、资源在内存中的布局,以及显示刷新行为。
SF32 面向紧凑型 AIoT 和可穿戴产品。此类产品既要求 UI 流畅,又必须满足严格的功耗、内存和 PCB 面积约束。图形路径将资源处理、像素合成、可选的帧缓冲压缩和面板输出分开。明确这些职责,是选择正确优化方式的关键。
当你需要作出后期难以调整的 UI 架构决策时,可参考本文,包括面板及接口、帧缓冲策略、色深、透明度、资源存放位置和刷新策略。相关图形专题文章则进一步介绍各环节的实现细节。
SF32 图形流程¶
典型的显示资源路径如下:
源图像、字体和动画
│
▼
GraphicsTool 将支持的资源转换为 eZip 或 eZip-A 格式
│
▼
压缩资源存放在 NOR Flash、PSRAM、NAND 或文件存储中
│
▼
需要时由 eZip 硬件解码器解压资源
│
▼
LVGL 或其他 UI 框架 + 图形/显示驱动
│
├── CPU 回退渲染
│
└── ePicasso 像素加速
│
▼
最终渲染位图写入绘制缓冲区或帧缓冲区
│
├── 未压缩显示路径
│
└── 可选:extDMA 将其压缩为 TurboPixel 格式
│
▼
TurboPixel 帧缓冲区存放在 PSRAM 中
│
▼
显示控制器将像素传输至面板
│
▼
SPI / QSPI / 8080 / RGB / MIPI DSI / EPD / JDI 面板
该路径可按需配置,并非所有产品都必须使用 eZip、ePicasso、TurboPixel 或完整帧缓冲区。各图形功能是否可用及其连接方式,取决于所选器件、SDK、显示接口、面板和驱动配置。当前 OpenSiFli LCDC 头文件仅在启用 HAL_EXTDMA_MODULE_ENABLED 且芯片系列条件允许时定义 LCDC_SUPPORTED_COMPRESSED_LAYER;SF32LB52x 和 SF32LB57x 被排除在外。源码注释还指出 LCPU 路径尚未启用。已发布的 SDK LCDC 功能表将 SF32LB55x 的压缩图层解压标为不支持,因此 55x 应视为有条件支持,而非已验证的完整运行时能力。请结合具体 SDK 版本、核心、构建配置和目标硬件验证;详见 TurboPixel。
| 模块 | 在流程中的位置 | 主要职责 | 不能替代 |
|---|---|---|---|
| eZip / eZip-A | 渲染前读取存储资源时 | 无损解压受支持的 eZip 图像和动画资源。 | 渲染器、最终帧缓冲区或显示控制器。 |
| ePicasso | 渲染和合成期间 | 加速内存中受支持的复制、填充、混合、变换和合成操作。 | 资源压缩或面板传输。 |
| TurboPixel | 支持的器件上,渲染后、面板输出前 | extDMA 以固定压缩比有损压缩最终位图,减少所需的 PSRAM 容量和显示读取流量。当前头文件仅在启用 extDMA 时为 SF32LB55x、SF32LB56x 和 SF32LB58x 定义压缩图层能力,并排除 SF32LB52x 和 SF32LB57x;源码注释指出 LCPU 路径尚未启用。已发布的 SDK 功能表将 SF32LB55x 标为不支持,因此 55x 仍需按具体核心、SDK 配置和目标硬件验证。 | 无损资源压缩或像素渲染。 |
| 显示控制器 | 最终输出阶段 | 在启用 TurboPixel 路径时解压,并通过面板接口传输准备好的像素。 | eZip 资源解压或图形合成。 |
应用代码描述 UI 状态和行为;UI 框架管理控件、待重绘区域和绘制;图形/显示驱动决定由 CPU 还是 ePicasso 执行操作,并协调缓冲区;显示控制器负责向面板传输像素。各模块的实现细节请参阅 ePicasso、eZip 和 TurboPixel。
首先选择显示屏¶
显示屏选择会影响几乎所有图形设计决策。优化代码之前,应明确以下面板要求:
- 分辨率。
- 色深。
- 刷新率。
- 接口类型。
- 触摸控制器要求。
- 背光或显示电源轨。
- 是否支持局部刷新。
- 面板是否具有内部 GRAM。
- 是否需要低功耗常亮显示。
小型 SPI 或 QSPI AMOLED 与 RGB、MIPI DSI、JDI Memory Display 或 EPD 面板的行为差异很大。同一 UI 框架可以适配多种显示类型,但合适的缓冲策略和刷新策略会随之变化。
关于接口选择、flush 路径设计和面板启动调试,请参阅显示控制器。
从已验证的 LVGL 示例开始¶
开始设计产品界面前,应选择能够验证图形链路中最大风险点的 SDK 示例。LVGL SDK 示例按工程任务梳理了官方的基础示例、设计工具、控件、压缩资源、动画和媒体、罗盘、游戏及手表界面示例,也说明了移植到产品时需要重新验证的开发板、版本、显示、内存和性能前提。
选择合适的 SF32 器件¶
应根据显示屏和 UI 工作负载选择芯片,而不能只看 CPU 频率。
| 需求 | 器件选型参考 |
|---|---|
| 带小型 UI 的基础蓝牙(Bluetooth)产品 | SF32LB52x |
| 入门级智能手表、徽章、标签或简单 HMI | SF32LB52x |
| UI 中传感器信息丰富的 BLE 可穿戴设备 | SF32LB55x |
| RGB 显示屏或更丰富的 LVGL 界面 | SF32LB56x |
| 适合交由 ACPU 处理的音频/图形任务 | SF32LB57x;核实 SDK 支持情况和任务分配 |
| 高分辨率显示屏或高级图形功能 | SF32LB56x 或 SF32LB58x |
| MIPI DSI 显示屏 | 根据面板和产品类别选择 SF32LB55x 或 SF32LB58x |
| 同时使用图形、音频、AI 和大容量内存的旗舰 UI | SF32LB58x |
最重要的约束包括显示接口、分辨率、内存容量、图形加速器代际、可用引脚和功耗预算。
帧缓冲区与带宽计算¶
选择面板或动画风格之前,应估算内存和传输开销:
framebuffer bytes = width x height x bytes_per_pixel
raw full-frame bandwidth = framebuffer bytes x frames_per_second
示例:
| 面板 | 格式 | 单个完整缓冲区 | 30 fps 全帧流量 |
|---|---|---|---|
| 240 × 240 | RGB565 | 约 113 KiB | 约 3.46 MB/s |
| 390 × 390 | RGB565 | 约 297 KiB | 约 9.13 MB/s |
| 454 × 454 | RGB565 | 约 403 KiB | 约 12.37 MB/s |
| 480 × 480 | RGB888 | 约 675 KiB | 约 20.74 MB/s |
缓冲区容量以 KiB(1,024 字节)表示,带宽以十进制 MB/s(1,000,000 字节/秒)表示。这些只是原始像素数据,尚未计入命令开销、对齐、缓存维护、资源读取、混合及系统中的其他数据流量。如果产品还同时运行蓝牙音频或 AI,或产生其他外部 PSRAM 访问流量,应预留余量。
理解各类缓冲区¶
UI 最终体现为内存中的像素。主要缓冲区类型如下:
| 缓冲区类型 | 用途 |
|---|---|
| 绘制缓冲区 | LVGL 或图形驱动用于渲染变化区域的临时空间。 |
| 帧缓冲区 | 作为显示源的全屏像素内存。 |
| 局部帧缓冲区 | 无法承担全屏缓冲开销时使用的较小区域缓冲区。 |
| 资源缓冲区 | 图像、字体、图标或解码后资源数据。 |
| 中间图层 | 用于混合、动画或合成的临时绘图表面。 |
完整帧缓冲区使用方便,但在大尺寸面板上可能占用过多 SRAM。一个 454 × 454 的 RGB565 缓冲区包含 412,232 字节(约 412 kB 或 403 KiB);双缓冲需要两倍容量。色深或分辨率提高后,内存占用会迅速增加。
内存紧张时,应使用局部绘制缓冲区和脏区域更新。动画要求较高且内存充足时,全屏或双缓冲策略可以让 UI 更流畅。
谨慎选择色深¶
色深会影响视觉质量、内存占用和总线带宽。
| 格式 | 每像素字节数 | 说明 |
|---|---|---|
| RGB565 | 2 | 嵌入式 UI 常用的平衡方案,内存和带宽效率良好。 |
| RGB666 | 3 或紧凑打包形式 | 色彩精度更高,但带宽占用也更大。 |
| RGB888 | 3 | 画质更高,同时增加内存和传输开销。 |
| RGB111 / 类单色格式 | 取决于器件 | 适合 EPD/JDI 等简单或超低功耗显示应用。 |
对于多数可穿戴设备和紧凑型 HMI,除非面板、UI 品质目标或产品要求需要更高色深,否则 RGB565 是稳妥的默认选择。
透明度、Alpha 与图层合成¶
透明度由 alpha 因子表示:它规定前景像素绘制在背景之上时,前景颜色参与输出的程度。Alpha 独立于 RGB 颜色通道。不透明像素的 alpha 为 1(或 8 位 alpha 通道中的 255);完全透明像素的 alpha 为 0。
当背景完全不透明、前景 RGB 使用非预乘 alpha(straight alpha)表示,且 alpha 归一化到 0–1 时,source-over 合成的每个输出 RGB 通道可按下式计算。这一简化公式不用于计算透明目标的输出 alpha:
例如,alpha 为 50% 的图标像素会贡献一半自身颜色,同时保留一半背景。重复执行这一操作即可形成 UI 的视觉层级:背景、图像、文字、半透明控件、阴影和动画图层。合成后的最终位图随后经过上文所示的帧缓冲区和显示控制器阶段。
| Alpha 模式 | 含义 | 典型用途 | 集成注意事项 |
|---|---|---|---|
| 逐像素 alpha | 每个像素都携带自己的 alpha 值。 | 抗锯齿图标和文字、柔边、阴影、PNG 类资源。 | 可保留细节丰富的透明效果,但会增加源数据量和混合工作量。 |
| 全局 alpha | 一个 alpha 值应用于整个对象或图层。 | 屏幕、对话框或图像的淡入淡出。 | 适合统一淡化,不能表达对象内部的柔边。 |
| 二值 alpha | 像素要么完全可见,要么完全透明。 | 蒙版和简单字形。 | 复杂度较低,但未使用抗锯齿时边缘可能出现锯齿。 |
RGB565 不包含 alpha 通道,因此通常用于不透明的绘制目标和最终帧缓冲区。需要透明度的源资源或中间图层通常使用带 alpha 通道的格式(如 ARGB8888),或使用彩色图像加独立 alpha 蒙版。驱动必须采用 SDK、显示路径和所选加速器实际支持的格式。
常见的 alpha 表示方式有两种。使用**非预乘 alpha(straight alpha)时,RGB 表示原始颜色,混合时再乘以 alpha。使用预乘 alpha(premultiplied alpha)**时,RGB 已经乘以 alpha,source-over 方程变为 output = premultiplied_foreground + background × (1 − alpha)。不要混淆这两种表示方式:将非预乘数据当作预乘数据处理,或反过来处理,都会在边缘产生暗边或亮边。
Alpha 混合需要读取前景和目标像素,再写入结果。因此,相比简单的不透明复制或填充,它会增加内存流量。若驱动支持所选混合操作和像素格式,应使用 ePicasso;否则应保留 CPU 回退路径。PSRAM 带宽或功耗紧张时,应限制全屏半透明图层、仅重绘发生变化的区域,并避免不必要的中间绘图表面。
集成 LVGL¶
LVGL 是适用于 SF32 器件的实用 UI 框架,提供控件、样式、输入处理、动画、重绘区域管理和显示驱动接口。
典型 LVGL 集成需要:
- 显示驱动 flush 回调。
- 一个或多个绘制缓冲区。
- 用于 LVGL 计时的 tick 源。
- 触摸、按键、编码器或手势输入驱动。
- 图像和字体资源管理。
- 可选的 ePicasso 硬件加速钩子。
显示 flush 回调是渲染与输出之间的边界。其控制器与 DMA 行为请参阅显示控制器。
LVGL 移植决策¶
在打磨界面之前,应确定以下 LVGL 集成细节:
| 决策 | 建议方向 |
|---|---|
| Tick 源 | 使用能够在睡眠和唤醒后继续保持正确计时的稳定系统 tick。 |
| Flush 回调 | 支持区域传输,并由 DMA 或显示驱动发出完成信号。 |
| 绘制缓冲区数量 | 根据延迟(latency)和内存预算选择一个或两个。 |
| 待重绘区域策略 | 仅在能够降低总传输成本时合并小区域。 |
| 输入设备 | 通过 LVGL 输入驱动集成触摸、按键和编码器,而不是由应用轮询。 |
| 硬件加速 | 只启用 SDK/驱动支持的操作,并保留 CPU 回退路径。 |
| 缓存处理 | 在框架与驱动的边界,对共享缓冲区执行 clean/invalidate。 |
良好的 LVGL 移植应让页面代码保持声明式,同时由驱动负责传输、同步、加速和缓存行为。
使用 ePicasso 加速¶
当 UI 包含大量重复像素计算时,ePicasso 可以有效加速。常见适用操作包括:
- 矩形填充。
- 图像复制和 Blit。
- Alpha 混合。
- 图像缩放。
- 对受支持图像区域进行旋转或变换。
- 图层合成。
- 驱动支持的像素格式转换。
良好的移植方案应加速高频、大数据量操作,同时为不支持的场景保留 CPU 回退路径。不要假设每种 LVGL 样式效果或控件都能映射到硬件,应测量产品真正使用的页面。
加速效果最明显的场景¶
ePicasso 通常在以下场景中最有效:
- 填充、复制、混合、缩放或变换较大区域。
- UI 使用透明图标、文字蒙版、阴影、叠加层或动画过渡。
- CPU 原本需要在每帧执行大量像素循环。
- 缓冲区的存放位置和像素格式适合加速器高效访问。
加速收益可能有限的场景¶
以下情况中,硬件加速收益可能有限:
- 更新区域很小。
- 瓶颈是面板传输带宽,而不是渲染。
- 资源采用不支持的格式,或需要高开销转换。
- 缓冲区位于带宽不足的慢速内存。
- 缓存维护开销超过操作本身。
内存布局策略¶
图形性能往往受数据搬运限制,因此应根据用途安排缓冲区的存放位置:
- 尽可能将高频绘制缓冲区放入高速 SRAM。
- 只有 SRAM 不足时,才将大型帧缓冲区放入 PSRAM。
- 大型图像和字体可存放在 Flash 或 PSRAM,但要考虑访问延迟。
- 避免运行时反复转换资源格式。
- 按照 SDK 要求对 DMA 访问的缓冲区进行对齐。
- 当压缩或索引资源能够降低总带宽和解码开销时,应优先采用。
CPU 与图形或显示硬件共享缓冲区时,应遵循 SDK 的缓存维护和缓冲区所有权规则。硬件读取 CPU 写入的数据前,先 clean 相关缓存行并完成必要的同步。硬件写入缓冲区前,应先做好准备,防止 CPU 的脏缓存行随后回写并覆盖硬件结果。等待传输完成后,在 CPU 读取结果前 invalidate 过期缓存行。注意缓存行对齐及相邻数据;硬件持有缓冲区期间,不要修改其中的数据。使用 SDK 支持的接口,不能把 clean 和 invalidate 当作可互换的操作。
关于局部刷新、各类面板行为和分阶段启动调试顺序,请参阅显示控制器。
资源准备¶
良好的资源准备可以在修改代码之前提高 UI 性能。建议:
- 图像尺寸应与实际显示尺寸匹配。
- 避免每帧缩放大型图像。
- 尽可能预渲染复杂阴影、渐变或背景。
- 仅在需要透明度的区域使用 Alpha。
- 复用图标集并裁剪字体字符集。
- 从字体中移除未使用的字形。
- 高频资源应采用图形链路能够高效处理的格式。
对于多语言产品,字体可能成为 UI 内存的主要占用项,应尽早规划字体回退、字形子集和文本布局。
动画策略¶
流畅动画取决于每帧预算、面板带宽、渲染成本和功耗。实用策略包括:
- 只对用户能够感知的内容添加动画。
- 缩小动画区域。
- 优先使用容易映射到硬件加速的变换或透明度变化。
- 避免每帧执行高开销的全屏模糊、阴影或透明效果。
- 对非关键效果降低帧率。
- 屏幕变暗、被遮挡或处于非活动状态时停止动画。
可穿戴 UI 不需要处处采用桌面级动画。少量快速、清晰的过渡,通常比大量耗电或掉帧的效果体验更好。
图形验证矩阵¶
应使用可重复的测试页面,而不是主观判断“足够流畅”:
| 测试页面 | 重点压力项 |
|---|---|
| 纯色填充和色条 | 像素格式、字节顺序、flush 路径。 |
| 大量文字页面 | 字体内存、字形缓存、局部刷新。 |
| 带 Alpha 的图标网格 | 混合、资源带宽、ePicasso 路径。 |
| 滚动列表 | 重绘区域、传输带宽、输入延迟。 |
| 全屏过渡 | 每帧预算、双缓冲、面板带宽。 |
| 变暗或空闲页面 | 动画停止策略、背光、电源管理请求(PM vote)。 |
| 最坏共存场景 | UI 更新时同时运行蓝牙、音频或 AI。 |
每个页面都应记录渲染时间、flush 时间、CPU 负载和功耗。如果只测量总帧时间,就很难判断瓶颈来自 LVGL、ePicasso、内存还是面板接口。
图形性能问题排查¶
UI 运行缓慢时,应先定位瓶颈,再修改设计。
| 现象 | 重点检查方向 |
|---|---|
| 绘制时 CPU 占用率高 | 未启用硬件加速、软件像素操作过多、控件复杂。 |
| 渲染完成,但显示更新缓慢 | 面板接口带宽、flush 区域大小、显示驱动传输路径。 |
| 撕裂或闪烁 | 缓冲策略、同步、局部更新时间。 |
| 随机图形伪影 | 缓存一致性、缓冲区生命周期、stride 或像素格式不匹配。 |
| 简单页面正常,但动画性能差 | 全屏重绘、大面积 Alpha 混合、资源缩放、面板带宽。 |
| UI 空闲时功耗高 | 不必要的重绘、定时器、动画、显示或背光策略。 |
应分别测量:
- LVGL 渲染时间。
- ePicasso 操作时间。
- 显示 flush 时间。
- CPU 负载。
- 内存带宽压力。
- 活动、空闲和睡眠状态下的功耗。
常见错误¶
以下问题后期修复成本很高,应尽早避免:
- 尚未估算带宽就选择面板接口。
- 小范围 UI 变化仍进行全屏重绘。
- 未经分析就将全部 UI 资源放入慢速内存。
- RGB565 已经足够,却使用 RGB888。
- 每帧缩放大型图像。
- 忘记对硬件共享缓冲区做缓存维护。
- 假定 ePicasso 会自动加速所有 UI 操作。
- 使用过多定时器或动画,使 CPU 无法睡眠。
- 只优化帧率,而忽略触摸延迟。
- 等到 PCB 启动调试阶段才验证面板初始化。
启动调试检查清单¶
开始新的 SF32 图形项目时,应完成以下检查:
- 确认显示分辨率、色深、接口和面板驱动 IC。
- 确认所选 SF32 器件支持所需显示接口。
- 估算帧缓冲区和绘制缓冲区的内存需求。
- 确定全帧或局部、单缓冲或双缓冲策略。
- 完成面板复位、电源轨、背光及初始化序列的启动调试。
- 实现 LVGL tick、显示 flush 和输入驱动。
- 验证基本填充、图像、文字和触摸功能。
- 在 SDK 和驱动支持的场景中启用 ePicasso 加速。
- 验证共享缓冲区的缓存清理/失效(cache clean/invalidate)行为。
- 分析渲染时间、flush 时间、CPU 负载和功耗。
- 测试最坏页面、动画、蓝牙活动,以及睡眠和唤醒路径。
要点¶
- 图形设计应从显示接口、分辨率、色深和刷新要求出发。
- 使用 LVGL 或类似框架管理控件、重绘区域、绘制和输入。
- 使用 ePicasso 加速常见像素操作,同时保留 CPU 回退路径。
- 缓冲区的存放位置和缓冲策略与渲染代码同样需要仔细优化。
- 对带宽受限面板和静态可穿戴页面,优先采用局部刷新。
- UI 性能是系统级问题,涉及 CPU、ePicasso、内存、显示控制器、面板接口、触摸和功耗策略。
最后更新: