How to Configure DMA in Embedded C: Simple Guide
To configure
DMA in embedded C, you need to set up the DMA controller registers to define source, destination, transfer size, and trigger conditions. Then enable the DMA channel and start the transfer. This setup allows data to move directly between memory and peripherals without CPU load.Syntax
DMA configuration typically involves setting these key registers:
- Source Address: Where data comes from.
- Destination Address: Where data goes.
- Transfer Size: Number of bytes or words to move.
- Control Register: Settings like transfer mode, priority, and enable bit.
These registers vary by microcontroller but the pattern is similar.
c
DMA_Channel->SRC_ADDR = (uint32_t)source_address; DMA_Channel->DST_ADDR = (uint32_t)destination_address; DMA_Channel->TRANSFER_SIZE = size_in_bytes; DMA_Channel->CONTROL = DMA_ENABLE | DMA_PRIORITY_HIGH | DMA_TRANSFER_MEMORY_TO_PERIPHERAL;
Example
This example shows how to configure DMA to transfer 10 bytes from a memory buffer to a peripheral data register on a generic microcontroller.
c
#include <stdint.h> #include <stdbool.h> #define DMA_ENABLE 0x01 #define DMA_PRIORITY_HIGH 0x02 #define DMA_TRANSFER_MEMORY_TO_PERIPHERAL 0x04 // Simulated DMA channel registers typedef struct { volatile uint32_t SRC_ADDR; volatile uint32_t DST_ADDR; volatile uint32_t TRANSFER_SIZE; volatile uint32_t CONTROL; } DMA_Channel_TypeDef; DMA_Channel_TypeDef DMA_Channel1; // Peripheral data register simulation volatile uint8_t PERIPHERAL_DATA_REG; int main() { uint8_t source_buffer[10] = {0,1,2,3,4,5,6,7,8,9}; // Configure DMA DMA_Channel1.SRC_ADDR = (uint32_t)source_buffer; DMA_Channel1.DST_ADDR = (uint32_t)&PERIPHERAL_DATA_REG; DMA_Channel1.TRANSFER_SIZE = 10; DMA_Channel1.CONTROL = DMA_ENABLE | DMA_PRIORITY_HIGH | DMA_TRANSFER_MEMORY_TO_PERIPHERAL; // Normally hardware handles transfer; here we simulate it for (uint32_t i = 0; i < DMA_Channel1.TRANSFER_SIZE; i++) { PERIPHERAL_DATA_REG = source_buffer[i]; // In real hardware, DMA moves data automatically } return 0; }
Common Pitfalls
Common mistakes when configuring DMA include:
- Not enabling the DMA channel after setup.
- Incorrect source or destination addresses causing data corruption.
- Setting wrong transfer size leading to buffer overruns.
- Forgetting to configure peripheral triggers or interrupts if required.
- Not checking DMA transfer completion before accessing data.
Always consult your microcontroller's reference manual for exact register details.
c
/* Wrong: Not enabling DMA channel */ DMA_Channel->CONTROL = DMA_PRIORITY_HIGH; /* Right: Enable DMA channel with proper flags */ DMA_Channel->CONTROL = DMA_ENABLE | DMA_PRIORITY_HIGH;
Quick Reference
Remember these quick tips for DMA configuration:
- Set source and destination addresses carefully.
- Specify correct transfer size matching your data.
- Enable the DMA channel after configuration.
- Configure peripheral triggers if needed.
- Use interrupts or polling to detect transfer completion.
Key Takeaways
Configure source, destination, transfer size, and control registers to set up DMA.
Always enable the DMA channel after configuring registers to start transfer.
Verify addresses and sizes to avoid data corruption or crashes.
Use peripheral triggers or interrupts to manage DMA transfers efficiently.
Consult your microcontroller manual for exact DMA register details.