Memory-to-peripheral transfer moves data from memory to a device like a screen or sensor. It helps send information without making the CPU do all the work.
Memory-to-peripheral transfer in Embedded C
DMA_Channel->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN; DMA_Channel->CPAR = (uint32_t)&PERIPHERAL_DATA_REGISTER; DMA_Channel->CMAR = (uint32_t)memory_address; DMA_Channel->CNDTR = data_length;
This example shows how to set up a DMA channel for memory-to-peripheral transfer.
DMA_CCR_DIR bit set means data moves from memory to peripheral.
DMA1_Channel3->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN; DMA1_Channel3->CPAR = (uint32_t)&USART1->DR; DMA1_Channel3->CMAR = (uint32_t)tx_buffer; DMA1_Channel3->CNDTR = sizeof(tx_buffer);
DMA2_Channel5->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN;
DMA2_Channel5->CPAR = (uint32_t)&SPI2->DR;
DMA2_Channel5->CMAR = (uint32_t)spi_tx_data;
DMA2_Channel5->CNDTR = 100;This program sets up a DMA channel to send the string "Hello DMA!" from memory to the USART1 peripheral automatically. The CPU does not need to send each character.
#include <stdint.h> #include "stm32f10x.h" // Example MCU header uint8_t message[] = "Hello DMA!"; void setup_dma_memory_to_peripheral(void) { // Enable clock for DMA1 RCC->AHBENR |= RCC_AHBENR_DMA1EN; // Disable DMA channel before configuration DMA1_Channel4->CCR &= ~DMA_CCR_EN; // Set peripheral address (e.g., USART1 data register) DMA1_Channel4->CPAR = (uint32_t)&USART1->DR; // Set memory address DMA1_Channel4->CMAR = (uint32_t)message; // Set number of data to transfer DMA1_Channel4->CNDTR = sizeof(message) - 1; // exclude null terminator // Configure DMA channel: // Memory increment mode enabled // Direction: memory to peripheral // Enable transfer complete interrupt (optional) DMA1_Channel4->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // Enable DMA channel DMA1_Channel4->CCR |= DMA_CCR_EN; } int main(void) { // Setup USART1 here (not shown for simplicity) setup_dma_memory_to_peripheral(); while (1) { // Main loop can do other tasks } }
Memory-to-peripheral transfer is often done using DMA (Direct Memory Access) controllers.
Make sure the peripheral is ready to receive data before starting the transfer.
Always disable the DMA channel before changing its settings.
Memory-to-peripheral transfer moves data from memory to a device without CPU intervention.
DMA controllers handle this transfer efficiently.
Setup involves configuring source, destination, data size, and enabling the DMA channel.
Practice
Solution
Step 1: Understand the role of memory-to-peripheral transfer
This transfer moves data from memory directly to a peripheral device, reducing CPU involvement.Step 2: Compare options with this understanding
Only To move data from memory to a device without using the CPU heavily correctly describes this purpose; others describe different operations or unrelated concepts.Final Answer:
To move data from memory to a device without using the CPU heavily -> Option DQuick Check:
Memory-to-peripheral transfer reduces CPU load = A [OK]
- Confusing memory-to-peripheral with peripheral-to-memory transfer
- Thinking it increases CPU speed
- Assuming it copies memory internally
Solution
Step 1: Understand enabling a bit in a register
To enable memory increment, set the MINC bit using bitwise OR (|=) to keep other bits unchanged.Step 2: Analyze each option
DMA->CCR |= DMA_CCR_MINC; uses |= which sets the bit correctly. DMA->CCR &= ~DMA_CCR_MINC; clears the bit, C overwrites all bits, D toggles the bit which is unsafe here.Final Answer:
DMA->CCR |= DMA_CCR_MINC; -> Option BQuick Check:
Enable bit with |= operator = A [OK]
- Using &= ~ to enable bits (actually disables)
- Assigning directly which clears other bits
- Using ^= which toggles bits unpredictably
uint16_t data[3] = {10, 20, 30};
DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR;
DMA->CNDTR = 3;
DMA->CPAR = (uint32_t)&PERIPH->DR;
DMA->CMAR = (uint32_t)data;
// DMA transfer starts and completes
Solution
Step 1: Understand memory increment and transfer count
Memory increment is enabled, so DMA reads data[0], data[1], data[2] sequentially, transferring 3 items.Step 2: Determine final peripheral register value
Each transfer writes to peripheral register. After last transfer, peripheral data register holds last value transferred: data[2] = 30.Final Answer:
30 -> Option AQuick Check:
Last transferred value = 30 [OK]
- Assuming peripheral holds first or middle value
- Ignoring memory increment effect
- Confusing transfer count with data index
DMA->CCR = DMA_CCR_DIR; DMA->CNDTR = 5; DMA->CPAR = (uint32_t)&PERIPH->DR; DMA->CMAR = (uint32_t)data_array; // Start DMA transfer
Solution
Step 1: Check memory increment setting
DMA_CCR_MINC bit is missing, so memory address does not increment during transfer.Step 2: Understand effect of missing memory increment
Without memory increment, DMA sends the same memory location repeatedly to peripheral, not the full array.Final Answer:
Memory increment mode is not enabled, so only first data is sent repeatedly -> Option AQuick Check:
Missing MINC bit causes repeated data = D [OK]
- Assuming peripheral address should point to memory
- Thinking transfer count causes overflow here
- Misreading direction bit status
Options: A) DMA->CMAR = 0x20001000; DMA->CPAR = 0x40013804; DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR; B) DMA->CPAR = 0x20001000; DMA->CMAR = 0x40013804; DMA->CCR = DMA_CCR_MINC; C) DMA->CPAR = 0x40013804; DMA->CMAR = 0x20001000; DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR; D) DMA->CMAR = 0x40013804; DMA->CPAR = 0x20001000; DMA->CCR = DMA_CCR_DIR;
Solution
Step 1: Identify source and destination addresses
Memory buffer is source (CMAR), peripheral register is destination (CPAR).Step 2: Check DMA direction and memory increment
DMA_CCR_DIR set means memory-to-peripheral transfer; DMA_CCR_MINC enables memory address increment.Step 3: Match correct option
DMA->CMAR = 0x20001000; DMA->CPAR = 0x40013804; DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR; correctly assigns CMAR to memory, CPAR to peripheral, and sets both DIR and MINC bits.Final Answer:
DMA->CMAR = 0x20001000; DMA->CPAR = 0x40013804; DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR; -> Option CQuick Check:
Memory in CMAR, peripheral in CPAR, DIR and MINC set = A [OK]
- Swapping source and destination addresses
- Forgetting to set memory increment bit
- Not setting direction bit for memory-to-peripheral
Ready to prove it?
Pass the test and this pattern moves unknown
