In this lesson, you will learn how to configure DMA addressing modes to automate continuous data movement between peripherals and memory without CPU intervention.
When we offload data transfers to the Direct Memory Access (DMA) controller, we must tell it how to handle source and destination addresses as each byte or word is moved. If we don’t define these rules, the DMA might overwrite the same memory location repeatedly or point to the wrong peripheral register.
Addressing Modes
There are two primary ways the DMA manages addresses:
- Fixed Addressing: The address remains constant. This is essential when transferring data to or from a peripheral register (like the
ADC_DRdata register). Since the peripheral register is a single memory-mapped location, the DMA should not increment the pointer. - Incremental Addressing: The address increases (e.g., by 1, 2, or 4 bytes) after every transfer. This is used when filling or reading from a data buffer in RAM, allowing the DMA to populate an array sequentially.
Transfer Modes
- Normal Mode: The DMA performs a predefined number of transfers and then stops. This is useful for single-shot captures.
- Circular Mode: Once the DMA finishes the transfer count, it automatically resets the destination address to the buffer's starting point and begins again. This is perfect for continuous audio streaming or sensor logging, where you want to overwrite old data with new data indefinitely.
Configuration Illustration
Imagine an ADC capturing data into a buffer. You would configure the source (ADC) as Fixed and the destination (RAM buffer) as Incremental.
// Conceptual configuration logic
DMA_Channel_Config {
.SourceAddress = &ADC1->DR; // The hardware register address
.SourceIncrement = DISABLE; // Stay on the register
.DestAddress = &Buffer[0]; // The array in RAM
.DestIncrement = ENABLE; // Move to next array index
.Mode = DMA_CIRCULAR; // Loop back to start automatically
}
By combining these settings, the DMA acts as a tireless background worker, filling your buffers while your CPU remains free to process the data or enter low-power modes.
Key Takeaway: Use Fixed addressing for peripheral registers, Incremental addressing for memory buffers, and Circular mode to maintain a continuous, autonomous data stream.