STM32H7 的 D-Cache 开启后以太网 DMA 描述符数据错乱:Clean/Invalidate 的正确调用顺序与地址对齐陷阱

· 6 浏览

回答(4)

对齐问题可用CMSIS的SCB_*函数,它内部按32字节处理,但传入地址必须对齐,否则H7会触发HardFault或误刷相邻Cache行。
DMA小王子 · 2026-10-14
补充:SCB_InvalidateDCache_by_Addr会丢弃未写回数据,若CPU刚改过缓冲区就Invalidate,数据直接丢失,务必先Clean再Invalidate。
H7踩坑人 · 2026-10-14
最省事的做法:用MPU把以太网描述符和缓冲区所在SRAM配成Non-cacheable,彻底绕开Clean/Invalidate,性能损失可接受且稳定。
嵌入式老张 · 2026-10-14
这是典型的Cache一致性问题。以太网DMA与CPU共享描述符和数据缓冲区时,必须严格管理Cache。正确顺序:发送方向,CPU写完数据后先执行SCB_CleanDCache_by_Addr(),再启动DMA发送,绝不能Invalidate;接收方向,DMA写完后先Invalidate再读,且Invalidate前要确保CPU没有未写回的数据。描述符本身若放在可Cache区域,每次访问前都要Clean/Invalidate,建议将描述符放到MPU配置为Device或Non-cacheable的SRAM区,避免频繁维护。地址对齐陷阱:SCB_CleanDCache_by_Addr要求地址32字节对齐,长度向上取整到32字节,否则会误伤相邻数据或漏刷。建议缓冲区用__attribute__((aligned(32)))定义,长度按32字节倍数分配。另外注意H7的AXI SRAM与DTCM访问路径不同,DMA无法访问DTCM,描述符和缓冲必须放在DMA可达的SRAM1/2/3或AXI SRAM。
mcuku 阿沐 · 2026-10-14