STM32H7 的 L1 Cache 与 DMA 一致性:Clean/Invalidate 的边界条件与实测陷阱

· 行业用户 · 6 浏览

回答(5)

Invalidate 前先 Clean 很重要,否则脏 line 被丢弃。另外注意 SCB 维护函数本身不是原子的,别在 DMA 传输中途乱调。
驱动阿凯 · 2026-10-29
别忘了 MPU:把 DMA 区配成 Non-cacheable 或 Write-through,比每次手动 Clean/Invalidate 更可靠,尤其多缓冲区场景。
Cortex_M7 · 2026-10-29
建议把 DMA 缓冲区放 DTCM RAM,DTCM 不经过 D-Cache,根本不用维护,省心且实时性好,代价是容量小。
嵌入式小刘 · 2026-10-29
实测最坑的是缓冲区跨 cache line:长度没向上取整,Clean 漏掉尾部,DMA 读到旧数据。统一按 32 字节对齐并 round up 长度即可。
硬件老张 · 2026-10-29
STM32H7 的 D-Cache 与 DMA 一致性核心在于:DMA 读内存前,CPU 若写过缓冲区,必须 Clean(写回)对应 cache line;DMA 写内存后,CPU 读之前必须 Invalidate(无效化),否则可能读到旧 cache 数据。边界条件:1) 操作地址必须按 32 字节 cache line 对齐,长度向上取整到 line 边界,否则会误清相邻数据;2) 缓冲区应放在非 cache 区或单独对齐的 cache line 上,避免与其它变量共享 line 导致伪共享;3) Invalidate 前若该 line 有脏数据会丢失,必须先 Clean 再 Invalidate;4) 使用 SCB_CleanDCache_by_Addr / SCB_InvalidateDCache_by_Addr,避免整 cache 操作影响实时性。实测陷阱:DMA 描述符/缓冲区未对齐导致偶发数据错;中断中调用 cache 维护函数耗时抖动;编译器优化把变量放寄存器导致看似 cache 问题;MPU 配置为 write-through 与 write-back 行为不同。建议 DMA 缓冲区用 __attribute__((aligned(32))) 并放在 DTCM 或配置 MPU 为非 cache 区,最稳妥。
mcuku 阿沐 · 2026-10-29