In this lesson, you will learn how to safely synchronize memory buffers shared between DMA controllers and the CPU by managing cache coherency.
When working with Direct Memory Access (DMA), the hardware controller operates independently of the CPU core. The primary challenge arises because modern processors use local caches (L1/L2) to store data. If the CPU modifies a memory buffer in its cache, the DMA controller—reading directly from physical RAM—will see stale data. Conversely, if the DMA controller writes new data into RAM, the CPU might continue reading outdated values from its cache, completely unaware that the underlying memory has changed.
To bridge this gap, you must implement cache maintenance operations before and after DMA transfers.
Managing the Cache Line
Before initiating a DMA transfer (where the DMA controller reads from RAM), you must clean (or write-back) the cache. This forces any pending CPU writes to be flushed out to physical RAM. After a DMA transfer completes (where the DMA controller writes to RAM), you must invalidate the cache range. This forces the CPU to discard its local cached copies, ensuring the next read fetches the fresh data provided by the DMA.
// Conceptual usage of a DMA-aware buffer
let mut buffer: [u8; 1024] = [0; 1024];
// 1. Clean cache before DMA reads from RAM
cache::clean_range(&buffer);
// 2. Trigger DMA engine (Non-blocking)
dma::start_transfer(buffer.as_mut_ptr(), 1024);
// 3. Wait for transfer completion...
dma::wait_until_finished();
// 4. Invalidate cache before CPU reads DMA-written data
cache::invalidate_range(&buffer);
// Now it is safe to access 'buffer'
process_data(&buffer);
Safety Considerations
Since unsafe blocks are often required to interface with memory-mapped registers, ensure your Buffer type is wrapped in an abstraction that prevents the CPU from accessing the memory while the DMA controller owns it. Using core::sync::atomic primitives is insufficient here; you must rely on hardware-specific intrinsic functions for cache management to guarantee that the CPU and DMA "see" the same reality.
Key Takeaway: Always clean the cache before a DMA read and invalidate the cache after a DMA write to prevent memory state corruption between the processor and hardware peripherals.