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.
Practice
What is the main advantage of using circular buffer mode in DMA?
Solution
Step 1: Understand circular buffer mode behavior
Circular buffer mode lets DMA wrap around to the start of the buffer after reaching the end, enabling continuous data transfer.Step 2: Identify the advantage
This means data can be streamed continuously without stopping or manual buffer reset.Final Answer:
It allows continuous data transfer without stopping when the buffer is full. -> Option DQuick Check:
Circular buffer = continuous transfer [OK]
- Thinking CPU speed changes with DMA mode
- Confusing interrupt behavior with buffer mode
- Assuming buffer size is reduced automatically
Which of the following is the correct way to enable circular mode in a DMA configuration struct in embedded C?
DMA_InitTypeDef DMA_InitStructure; // ... other initializations DMA_InitStructure.Mode = ?;
Solution
Step 1: Recall DMA mode options
DMA_Mode_Circular is the standard mode to enable circular buffer operation in DMA configurations.Step 2: Match the correct mode
DMA_Mode_Normal is single transfer, others like Interrupt or OneShot are not standard DMA modes for circular buffer.Final Answer:
DMA_Mode_Circular -> Option AQuick Check:
Enable circular mode = DMA_Mode_Circular [OK]
- Using DMA_Mode_Normal instead of circular
- Confusing interrupt mode with circular mode
- Using non-existent DMA modes
Given the following code snippet configuring DMA in circular mode, what will be the value of buffer[0] after 5 DMA transfers if the peripheral sends values 10, 20, 30, 40, 50 continuously?
#define BUFFER_SIZE 4
uint8_t buffer[BUFFER_SIZE] = {0};
// DMA configured in circular mode with buffer size 4
// Peripheral sends: 10, 20, 30, 40, 50
// DMA writes each value to buffer sequentially
// After 5 transfers:Solution
Step 1: Understand circular buffer write pattern
Buffer size is 4, so DMA writes values to buffer[0..3] in order, then wraps around to buffer[0].Step 2: Track each transfer
Transfers: 1->buffer[0]=10, 2->buffer[1]=20, 3->buffer[2]=30, 4->buffer[3]=40, 5->buffer[0]=50 (overwrite).Final Answer:
50 -> Option BQuick Check:
5th write wraps to buffer[0] = 50 [OK]
- Assuming buffer[0] keeps first value
- Ignoring wrap-around overwrite
- Confusing peripheral data order
Identify the error in this DMA circular buffer setup snippet:
DMA_InitTypeDef DMA_InitStructure; uint8_t buffer[8]; DMA_InitStructure.Mode = DMA_Mode_Circular; DMA_InitStructure.BufferSize = 10; DMA_InitStructure.MemBaseAddr = (uint32_t)buffer; // Start DMA
Solution
Step 1: Compare buffer size and BufferSize parameter
Buffer array has 8 elements, but BufferSize is set to 10, which is larger than buffer length.Step 2: Understand consequences
This mismatch can cause DMA to write beyond buffer bounds, leading to overflow and undefined behavior.Final Answer:
Buffer size is larger than actual buffer, causing overflow. -> Option CQuick Check:
BufferSize must not exceed buffer length [OK]
- Setting BufferSize larger than buffer array
- Ignoring buffer overflow risks
- Assuming casting memory address fixes size mismatch
You want to use DMA in circular mode to continuously read sensor data into a buffer of size 16. However, you notice data loss when the CPU reads the buffer slower than DMA writes. What is the best way to avoid data loss?
Solution
Step 1: Understand cause of data loss
If CPU reads slower than DMA writes, new data overwrites unread data in circular buffer causing loss.Step 2: Apply solution with double buffering
Increasing buffer size and using double buffering lets CPU read one buffer while DMA writes to another, preventing overwrite.Final Answer:
Increase buffer size and use double buffering technique. -> Option AQuick Check:
Double buffering prevents overwrite in circular DMA [OK]
- Disabling circular mode loses continuous transfer benefit
- Trying to slow DMA speed which may not be possible
- Stopping DMA interrupts causes data gaps
Ready to prove it?
Pass the test and this pattern moves unknown
