0
0
Power-electronicsHow-ToBeginner · 4 min read

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.