1、TouchGFX 内存模型全景:SRAM、SDRAM、Flash 与帧缓冲分配

做 TouchGFX 优化,第一件事就是搞清楚内存到底怎么分的。我见过不少开发者,UI 写得很漂亮,一跑起来就崩,最后发现是帧缓冲分配错了地方。说白了,内存模型就是 TouchGFX 的「地基」,地基没打好,上面盖什么楼都白搭。

1.1 MCU 三大存储区:谁该干什么

一个典型的 MCU 里,跟 TouchGFX 相关的存储区就三个:内部 SRAM、SDRAM(外部扩展)和 Flash。它们各有各的脾气,用错了地方,性能直接腰斩。

存储区 速度 容量 掉电保留 TouchGFX 典型用途
内部 SRAM 最快(~200MHz 总线) 通常 64KB~1MB 否 帧缓冲、动态对象、局部变量
SDRAM 较快(~100MHz 总线) 通常 4MB~64MB 否 大尺寸帧缓冲、缓存图片、字体缓存
内部 Flash 慢(读 ~25MHz) 通常 256KB~2MB 是 代码、只读资源(图片、字体、文本)

核心原则:SRAM 放「频繁读写」的数据(帧缓冲),Flash 放「只读不写」的数据(资源),SDRAM 放「大块但可以慢一点」的数据(大缓存)。

1.2 帧缓冲(Frame Buffer)的分配策略

帧缓冲是 TouchGFX 最吃内存的地方。你想想看,一个 480×272 的 16 位色屏幕,单缓冲就要 480×272×2 = 261KB。如果是 800×480 的 24 位色屏,单缓冲直接飙到 1.15MB。很多 MCU 内部 SRAM 总共才 512KB,一个缓冲就吃掉一半多。

TouchGFX 支持三种缓冲模式,我按实际项目经验给你排个序:

  1. 单缓冲(Single Buffer):最省内存,但屏幕刷新时会有撕裂感。适合低帧率或静态界面。
  2. 双缓冲(Double Buffer):一个前台显示,一个后台绘制。内存翻倍,但画面流畅。这是大多数项目的标配。
  3. 局部缓冲(Partial Buffer):只分配一小块内存,分块刷新屏幕。内存占用极低,但 CPU 开销大。适合 SRAM 极小的芯片。

我的习惯:只要 SDRAM 够用,我会把帧缓冲全部扔到 SDRAM 里,SRAM 留给动态对象和栈。如果芯片没有 SDRAM,那就用局部缓冲,把单缓冲大小压到 32KB 以内。

1.3 内存分区与 TouchGFX 的对应关系

TouchGFX 在代码里通过 touchgfx_config.h 和链接脚本(.ld / .scf)来定义内存布局。我画了一张图,帮你把物理分区和逻辑分区对应起来:

TouchGFX 内存分区对应关系图 TouchGFX 内存分区对应关系 物理存储区 内部 SRAM 64KB ~ 1MB 高速、易失 SDRAM 4MB ~ 64MB 中速、易失 内部 Flash 256KB ~ 2MB 低速、非易失 TouchGFX 逻辑分区 帧缓冲 单/双/局部 频繁读写 动态对象 Widget、容器 运行时分配 只读资源 图片、字体 编译时固定 箭头方向:物理存储区 → TouchGFX 逻辑分区(数据流向)

1.4 链接脚本中的内存布局

实际工程里,内存分区是在链接脚本里定义的。以 STM32H750 + 外部 SDRAM 为例,.ld 文件里大概长这样:

/* 内部 SRAM:128KB */
RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 128K

/* 外部 SDRAM:8MB,映射到 0xC0000000 */
SDRAM (xrw) : ORIGIN = 0xC0000000, LENGTH = 8M

/* 内部 Flash:1MB */
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1M

然后在 touchgfx_config.h 里指定帧缓冲位置:

#define FRAME_BUFFER_LOCATION  // 自定义宏
// 如果使用 SDRAM,在链接脚本里将帧缓冲段放到 SDRAM 区域
// 例如:__attribute__((section(".sdram_frame_buffer")))

我曾经踩过的坑:有一次我把帧缓冲放在 SDRAM,但忘了初始化 SDRAM 控制器。结果 UI 启动时直接 HardFault,查了两天才发现是内存还没准备好就开始写数据。记住:SDRAM 必须在 TouchGFX 初始化之前完成配置。

1.5 帧缓冲分配策略实战对比

我整理了一张对比表,帮你快速决策:

策略 内存占用 CPU 负载 画面质量 适用场景
单缓冲(SRAM) 低(1×帧大小) 低 有撕裂 静态界面、低分辨率屏
双缓冲(SDRAM) 高(2×帧大小) 中 无撕裂 动画、滑动、视频播放
局部缓冲(SRAM) 极低(16KB~64KB) 高 无撕裂 SRAM 极小、无 SDRAM

我的建议:如果芯片有 SDRAM,无脑上双缓冲。如果只有 SRAM,优先用局部缓冲,把单缓冲大小压到屏幕一行数据的大小(例如 800×2 = 1.6KB),这样内存占用几乎可以忽略。

1.6 小结:记住这三句话

  • SRAM 是黄金地段:放帧缓冲和动态对象,但地方小,要精打细算。
  • SDRAM 是郊区仓库:地方大,但访问慢一点,适合放大块数据。
  • Flash 是图书馆:只能读不能写,放代码和资源,别把变量放进去。