DMA 和缓存

当使用 DMA 在内存之间或者内存和外设之间传输数据,如果此时 Cache 也正常启用,需要注意 Cache 和内存数据不一致的问题。

DMA TX

当 DMA 的源端是 Memory,需要发送数据时,一般流程如下:

  1. 申请发送缓冲区,需要确保起始地址和大小都与 Cache Line 对齐。

  2. CPU 将数据写入 Memory 缓冲区。

  3. 调用 DCache_Clean() 函数清理数据缓存

  4. 配置 DMA 发送参数

  5. DMA 启动传送

DMA RX

  1. CPU 分配接收缓冲区

  2. 执行 DCache_Clean() 确保接收缓冲区处于 clean 状态(如果接收缓冲区处于 clean 状态,可跳过此步骤)

    小心

    此步骤执行的原因是:

    • 对于 Cortex-A32,如果 Cache 中的接收缓冲区处于 dirty 状态,执行第 5 步 DCache_Invalidate() 将同时执行 cleaninvalidate 操作,可能会导致意外写入行为。

    • 如果 Cache 中的接收缓冲区处于 dirty 状态,当 CPU 的 D-Cache 满了,CPU 可能会将接收缓冲区中的脏数据写回内存,覆盖 DMA 已经写入的内容。

  3. 配置 DMA Rx 参数

  4. 配置并使能 DMA Rx 中断处理函数

  5. 执行 DCache_Invalidate() 作废 Cache 中对应的数据,确保 Cache 没有残留旧的接收缓冲区数据。

小心

此步骤必须执行,原因如下:

  • 对于具有自动数据预取功能的 CPU(如 Cortex-A32 和 DSP),当 CPU 读取接收缓冲区相邻地址的内容时,CPU 会在后台执行行填充操作,自动将接收缓冲区的旧值重新加载到 Cache 中。

  • 防止 CPU 在 DMA 处理期间将旧值读入 Cache。

  1. CPU 读取接收缓冲区(DMA Rx 返回的值)

备注

将缓冲区地址与 Cache Line 行对齐将减少 Cache 与内存数据不一致的问题。