TouchGFX 图形渲染出现花屏,核心原因是帧缓冲配置为 WBWA 模式(Normal write-back + 读写分配)时,未刷新 DCache(数据缓存) ——CPU 仅更新 Cache 未同步物理内存,LTDC(LCD 控制器)读取旧数据导致数据不一致。解决方案:在flushFrameBuffer函数中添加SCB_CleanInvalidateDCache(),一键同步 Cache 与物理内存,兼顾性能与显示稳定性。
资料获取:LAT1443 TouchGFX 图形渲染没有刷新DCache导致的花屏问题分析
1. 问题背景:性能与显示的矛盾场景
1.1 核心配置
- 硬件:Cortex-M7 内核 MCU(如 STM32F7/H7);
- 帧缓冲属性:为追求高性能,配置为 WBWA 模式(
TEX=1、C=1、B=1); - 图形框架:TouchGFX,执行部分渲染后出现局部花屏;
- 对比现象:切换为 Write-through(透写)模式后花屏消失,但系统性能下降(单次写入开销增大)。
1.2 关键矛盾
- WBWA 模式优势:写数据仅更新 DCache,不立即同步物理内存,速度快、总线开销小;
- 隐藏风险:TouchGFX 渲染完成后,Cache 中更新的数据未同步到物理内存,LTDC 读取物理内存时拿到旧数据,导致显示花屏。
2. 根源拆解:DCache 数据一致性问题
2.1 WBWA 模式的缓存机制
- 写操作:CPU 修改帧缓冲数据时,仅写入 DCache,标记为 “脏数据(Dirty)”,暂不写入物理内存;
- 读取逻辑:LTDC 作为独立主机,直接访问物理内存,而非 DCache;
- 冲突点:渲染完成后未执行 Cache 维护,DCache 中的新数据与物理内存的旧数据不一致,LTDC 显示异常。
2.2 TouchGFX 的渲染回调机制
TouchGFX 框架在每次局部渲染完成后,会自动调用flushFrameBuffer函数(定义在TouchGFXHAL.cpp),目的是通知框架 “渲染完成”,但默认实现未包含 DCache 刷新操作,无法解决 WBWA 模式下的数据一致性问题。
3. 解决方案:1 行代码修复,零性能损耗
在flushFrameBuffer函数中添加 DCache 清洁 + 无效化操作,确保 Cache 数据同步到物理内存,步骤如下:
3.1 代码修改(核心步骤)
打开工程中的TouchGFXHAL.cpp,找到flushFrameBuffer函数,添加SCB_CleanInvalidateDCache():
3.2 函数作用说明
SCB_CleanInvalidateDCache():CMSIS 标准函数,执行两步操作:- Clean(清洁):将 DCache 中标记为 “Dirty” 的脏数据写入物理内存;
- Invalidate(无效化):标记 DCache 对应区域为无效,后续读取直接从物理内存获取新数据;
- 优势:仅在渲染完成后执行一次,对系统性能影响极小,完全保留 WBWA 模式的性能优势。
3.3 补充:MPU 帧缓冲配置(确保 WBWA 模式正确)
若未正确配置 MPU,DCache 模式可能失效,需按以下参数配置帧缓冲区域:
| MPU 参数 | 配置值 | 说明 |
|---|---|---|
| TEX | 1 | Normal 内存类型标记 |
| C | 1 | 启用 Cache |
| B | 1 | 启用缓冲 |
| S | 0 | 非共享内存 |
| 内存类型 | Normal | 对应 WBWA 模式 |
4. 关键注意事项
- 模式适配:仅 WBWA 模式需要添加该代码,Write-through 模式无需(透写模式自动同步 Cache 与物理内存);
- 多主设备场景:除 LTDC 外,若 DMA、其他内核也访问帧缓冲,需同样执行 Cache 维护操作;
- 函数兼容性:
SCB_CleanInvalidateDCache()适用于所有 Cortex-M7 内核 MCU,无需修改适配; - 局部刷新优化:若仅局部渲染(如 rect 参数指定区域),可使用
SCB_CleanInvalidateDCache_by_Addr()精准刷新指定地址范围,进一步提升效率:
TouchGFX 花屏的核心是 “WBWA 模式下 DCache 数据未同步”,而非硬件或渲染逻辑问题。通过在flushFrameBuffer中添加 1 行 Cache 刷新代码,即可兼顾 WBWA 模式的高性能与显示稳定性,无需牺牲性能切换到 Write-through 模式。该方案适用于所有 Cortex-M7 内核 + TouchGFX 的嵌入式图形应用。
182