In this lesson, you will learn how to identify and resolve data corruption issues that occur when the CPU cache and DMA controller battle over the same memory buffer.
When you use DMA to fill a buffer from a peripheral (like an ADC), the DMA controller writes directly into physical RAM. However, if your CPU has a data cache, it might have an old version of that buffer stored in its local cache lines. When your program reads the buffer, it gets the "stale" cached data instead of the fresh data the DMA just wrote. This is a coherency issue.
The Race Condition
A race condition occurs when the CPU begins processing data before the DMA has signaled completion. If your code checks a "ready" flag without ensuring the cache is synchronized, your logic might act on incomplete or "ghost" data.
Diagnostic Technique: The Buffer Integrity Check
To verify if your system is suffering from a coherency mismatch, use a "sentinel value" technique. Initialize your buffer with a known, distinct pattern (e.g., 0xDEADBEEF) before starting the DMA transfer.
// Example: Debugging buffer content
uint32_t adc_buffer[10];
void start_acquisition() {
// Fill with pattern before DMA
for(int i = 0; i < 10; i++) adc_buffer[i] = 0xDEADBEEF;
// Trigger DMA
start_dma_transfer(adc_buffer);
}
// In the DMA completion interrupt
void DMA_IRQHandler() {
// Check if the first and last elements are updated
if (adc_buffer[0] == 0xDEADBEEF || adc_buffer[9] == 0xDEADBEEF) {
// ERROR: DMA didn't finish or cache is masking the update
handle_corruption_error();
}
}
How to Fix
To solve these issues:
- Invalidate the Cache: Before reading a buffer that the DMA has just modified, you must "invalidate" the corresponding cache lines. This forces the CPU to ignore its internal cache and fetch the fresh data directly from RAM.
- Clean the Cache: If you are using DMA to send data out from memory to a peripheral, you must "clean" (flush) the cache to RAM first, ensuring the DMA sees the latest values stored by the CPU.
- Use Non-Cacheable Memory: For simple systems, declare your shared buffers in a memory region marked as "non-cacheable" in your MPU (Memory Protection Unit) configuration.
Key Takeaway: Data corruption in DMA systems is usually caused by the CPU reading stale values from its cache; always invalidate the cache before reading DMA-updated buffers or clean it before DMA-driven transmission.