0
0
Embedded Cprogramming~7 mins

Circular buffer DMA mode in Embedded C

Choose your learning style9 modes available
Introduction

Circular buffer DMA mode helps to continuously store data in a fixed-size buffer without stopping. It automatically wraps around when it reaches the end, so you don't lose data.

When reading data from sensors continuously without missing any values.
When receiving serial data streams like UART or SPI without manual buffer management.
When audio or video data streams need to be processed in real-time.
When you want to reduce CPU load by letting DMA handle data transfers automatically.
Syntax
Embedded C
DMA_InitTypeDef dma_init;
dma_init.DMA_Mode = DMA_Mode_Circular;
// Other DMA settings like direction, buffer size, peripheral address, memory address
DMA_Init(DMAx_Streamy, &dma_init);
DMA_Cmd(DMAx_Streamy, ENABLE);

The key setting is dma_init.DMA_Mode = DMA_Mode_Circular to enable circular buffer mode.

You must configure buffer size and addresses correctly to avoid overwriting important data.

Examples
This example sets up DMA to read 128 bytes from a peripheral to memory in circular mode.
Embedded C
DMA_InitTypeDef dma_init;
dma_init.DMA_Channel = DMA_Channel_4;
dma_init.DMA_DIR = DMA_DIR_PeripheralToMemory;
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma_init.DMA_Mode = DMA_Mode_Circular;
dma_init.DMA_Priority = DMA_Priority_High;
dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma_init.DMA_BufferSize = 128;
DMA_Init(DMA2_Stream0, &dma_init);
DMA_Cmd(DMA2_Stream0, ENABLE);
Used for continuous UART reception without stopping DMA.
Embedded C
// Start DMA in circular mode for UART RX buffer
DMA_InitTypeDef dma_uart_rx;
dma_uart_rx.DMA_Channel = DMA_Channel_4;
dma_uart_rx.DMA_DIR = DMA_DIR_PeripheralToMemory;
dma_uart_rx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_uart_rx.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_uart_rx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma_uart_rx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma_uart_rx.DMA_Mode = DMA_Mode_Circular;
dma_uart_rx.DMA_BufferSize = UART_RX_BUFFER_SIZE;
// Other UART DMA settings
DMA_Init(DMA1_Stream5, &dma_uart_rx);
DMA_Cmd(DMA1_Stream5, ENABLE);
Sample Program

This program configures DMA in circular mode to fill a buffer continuously from a peripheral (simulated here). It then prints the buffer content.

Embedded C
#include "stm32f4xx.h"
#include <stdio.h>

#define BUFFER_SIZE 16
uint8_t dma_buffer[BUFFER_SIZE];

void DMA_Config(void) {
    DMA_InitTypeDef dma_init;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

    DMA_DeInit(DMA2_Stream0);
    while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE) {}

    dma_init.DMA_Channel = DMA_Channel_0;
    dma_init.DMA_DIR = DMA_DIR_PeripheralToMemory;
    dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
    dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    dma_init.DMA_Mode = DMA_Mode_Circular;
    dma_init.DMA_Priority = DMA_Priority_High;
    dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable;
    dma_init.DMA_BufferSize = BUFFER_SIZE;
    dma_init.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
    dma_init.DMA_Memory0BaseAddr = (uint32_t)dma_buffer;

    DMA_Init(DMA2_Stream0, &dma_init);

    DMA_Cmd(DMA2_Stream0, ENABLE);
}

int main(void) {
    DMA_Config();

    // Simulate main loop
    for (int i = 0; i < BUFFER_SIZE; i++) {
        dma_buffer[i] = i + 1; // Simulate data received by DMA
    }

    // Print buffer content
    for (int i = 0; i < BUFFER_SIZE; i++) {
        printf("%d ", dma_buffer[i]);
    }
    printf("\n");

    while (1) {}
}
OutputSuccess
Important Notes

Make sure the buffer size matches the DMA configuration to avoid data corruption.

In circular mode, DMA never stops; you must handle data reading carefully to avoid overwriting unread data.

Check your microcontroller's reference manual for exact DMA register and function names.

Summary

Circular buffer DMA mode lets DMA write data continuously in a loop.

It is useful for streaming data like sensors or communication peripherals.

Proper buffer and DMA setup is important to avoid data loss.