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.
Circular buffer DMA mode in 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.
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);// 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);
This program configures DMA in circular mode to fill a buffer continuously from a peripheral (simulated here). It then prints the buffer content.
#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) {} }
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.
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.