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 支持三种缓冲模式,我按实际项目经验给你排个序:
- 单缓冲(Single Buffer):最省内存,但屏幕刷新时会有撕裂感。适合低帧率或静态界面。
- 双缓冲(Double Buffer):一个前台显示,一个后台绘制。内存翻倍,但画面流畅。这是大多数项目的标配。
- 局部缓冲(Partial Buffer):只分配一小块内存,分块刷新屏幕。内存占用极低,但 CPU 开销大。适合 SRAM 极小的芯片。
我的习惯:只要 SDRAM 够用,我会把帧缓冲全部扔到 SDRAM 里,SRAM 留给动态对象和栈。如果芯片没有 SDRAM,那就用局部缓冲,把单缓冲大小压到 32KB 以内。
1.3 内存分区与 TouchGFX 的对应关系
TouchGFX 在代码里通过 touchgfx_config.h 和链接脚本(.ld / .scf)来定义内存布局。我画了一张图,帮你把物理分区和逻辑分区对应起来:
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 是图书馆:只能读不能写,放代码和资源,别把变量放进去。