这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » STM32H7S78-DK图形加速实战:LTDC/DMA2D/NeoChrom三

共1条 1/1 1 跳转至页

STM32H7S78-DK图形加速实战:LTDC/DMA2D/NeoChrom三渲染路径对比

高工
2026-11-11 10:26:24     打赏
STM32H7S78-DK 图形加速实战:LTDC / DMA2D / NeoChrom 三渲染路径对比

本文记录在 STM32H7S78-DK(STM32H7S7L8,Cortex-M7 @600MHz,800×480 RGB 屏)上,用 Zephyr 4.5 + LVGL 9.6 把板载三种图形硬件全部用起来,并设计了一个可运行时按键切换渲染路径的对比实验,用日志定量给出三者的差异。环境基于《STM32H7S78-DK 上跑通 Zephyr:从 Blinky 到外部 Flash 启动》。

1. 三种硬件在 Zephyr 中的使用方式

硬件Zephyr/LVGL 支持方式关键配置
LTDCZephyr 原生显示驱动,帧缓冲放 PSRAM,直渲染双缓冲板级 defconfig 自动配置
DMA2D(Chrom-ART)LVGL 9.6 内置 draw unit,自带 STM32H7RS 时钟使能CONFIG_LV_USE_DRAW_DMA2D=y
NeoChrom GPU2DLVGL NemaGFX renderer + Zephyr 官方 glue(含 Cortex-M7 预编译库)CONFIG_LV_USE_NEMA_GFX=y

LVGL 9 把每个渲染器注册为全局 draw unit,按链表优先级分发绘制任务(NEMA > DMA2D > SW),处理不了的原语自动回落,因此三者可以共存。

2. 运行时切换渲染器(本实验的核心技巧)

LVGL 没有公开的 draw unit 开关 API,但开启 CONFIG_LV_USE_PRIVATE_API=y 后可以拿到内部链表,按键时重建它——把对应硬件单元摘掉或挂回:

/* 重建全局 draw unit 链表:优先级 NEMA_GFX -> DMA2D -> SW */
static void apply_render_mode(enum render_mode m)
{
    lv_draw_global_info_t *info = &LV_GLOBAL_DEFAULT()->draw_info;
    lv_draw_unit_t *head = sw_unit;

    if (m == MODE_NEMA && nema_unit != NULL && dma2d_unit != NULL) {
        nema_unit->next = dma2d_unit;
        dma2d_unit->next = sw_unit;
        head = nema_unit;
    } else if (m >= MODE_DMA2D && dma2d_unit != NULL) {
        dma2d_unit->next = sw_unit;
        head = dma2d_unit;
    }

    sw_unit->next = NULL;
    info->unit_head = head;
}

3. 实验设计

PSRAM 全部用起来(256Mbit Hexadeca-SPI,映射在 0x90000000):

# LVGL 堆内存池搬到 PSRAM 并加大到 2MB
CONFIG_LV_Z_MEMORY_POOL_ZEPHYR_REGION=y
CONFIG_LV_Z_MEMORY_POOL_ZEPHYR_REGION_NAME="PSRAM"
CONFIG_LV_Z_MEM_POOL_SIZE=2097152

加上板级默认的双全屏帧缓冲(2×800×480×3 ≈ 2.3MB),PSRAM 共占用约 3.5MB。2MB 的堆让大图像缓冲成为可能:实验中从 PSRAM 分配一块 200×150 旋转画布(SW 渲染时放不下也转不动的场景)。

测量方法:LVGL sysmon 日志模式,每 300ms 输出一行官方统计,render(纯绘制)与 flush(刷屏)分开:

CONFIG_LV_USE_SYSMON=y
CONFIG_LV_USE_PERF_MONITOR=y
CONFIG_LV_USE_PERF_MONITOR_LOG_MODE=y
CONFIG_LV_USE_LOG=y            # sysmon 日志依赖 LVGL 日志总开关
CONFIG_LV_DEF_REFR_PERIOD=5    # 默认 33ms 会把 FPS 顶死在 30
CONFIG_CPU_LOAD=y              # Zephyr CPU 负载统计,不开 CPU% 恒为 100

输出示例:

sysmon: 21 FPS (refr_cnt: 7 | redraw_cnt: 7), refr 46ms (render 33ms | flush 11ms), CPU 52%

4. 实测数据与曲线

压力场景:阴影渐变弹跳小球 + 旋转圆弧 + 进度条 + 缩放文字 + 半透明移动面板 + 200×150 PSRAM 画布持续旋转。

gpu_compare_curves.png

模式render 时间(均值)flushCPUFPS
CPU (SW)~48ms~7ms84~94%14~21
DMA2D~39ms~6ms78~100%16~21
NeoChrom GPU~38ms~5ms50~65%19~21

5. 结论

  1. NeoChrom 是最优路径:绘制快约 20%,关键优势在 CPU 占用——从 ~90% 降到 ~55%,同样帧率下省出三分之一 CPU 给应用逻辑,这就是独显的意义。

  2. DMA2D 绘制同样快约 20%,但 CPU 没降:Zephyr 的 LVGL 以 LV_OS_NONE 运行(应用手动调 lv_timer_handler),DMA2D 的中断异步模式在 OS_NONE 下无效(源码里有对应 #warning),传输完成靠轮询死等,硬件干活 CPU 干等。

  3. flush 仅 ~7ms,不是瓶颈:垂直同步等待远小于想象,时间主要花在真实绘制。

  4. GPU 差距没有拉得更开的原因:文字、圆弧、渐变等原语 NemaGFX 不接管(回落 SW),且帧缓冲在 PSRAM,带宽是共享天花板。属 LVGL 混合渲染的常态。

  5. PSRAM 的正确用法:帧缓冲(2.3MB)+ LVGL 堆(2MB)都放 PSRAM 后,片内 SRAM 留给 NemaGFX 池(330KB)和系统,大图像/双缓冲/GPU 同时工作的基础。

6. 踩坑记录

  • FPS 全卡 30:LV_DEF_REFR_PERIOD 默认 33ms,任何模式都撞天花板,改成 5ms 才解开。

  • CPU 恒 100%:Zephyr 版 LVGL 的 CPU% 取自 cpu_load_get(),必须开 CONFIG_CPU_LOAD=y,否则 idle 恒为 0。

  • sysmon 日志不出:LV_USE_PERF_MONITOR_LOG_MODE 依赖 CONFIG_LV_USE_LOG=y(默认关,LV_LOG 是空操作);之前看到的 lvgl 警告来自 Zephyr glue 自己的日志,容易误导。

  • 主循环空转:固定 5ms 调 lv_timer_handler 会推高 CPU 占用读数,应用其返回值睡眠。

  • *LVZ 符号不可直接赋值**:LV_Z_USE_NEMA_GFX 等无 prompt 符号由 LV_USE_NEMA_GFX 自动带出,在 prj.conf 里直接赋值会报 Kconfig 错误。

  • NemaGFX 内存池放不下:默认 800×600(~490KB)超过 456KB SRAM,需调小(实验用 800×400)。





关键词: STM32H7S78-DK     图形     DMA2D     Ne    

共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]