Memory-to-peripheral transfer in Embedded C - Time & Space Complexity
When transferring data from memory to a peripheral device, it is important to understand how the time taken grows as the amount of data increases.
We want to know how the number of operations changes when we send more data.
Analyze the time complexity of the following code snippet.
void transfer_data(uint8_t *memory, volatile uint8_t *peripheral, int size) {
for (int i = 0; i < size; i++) {
peripheral[i] = memory[i];
}
}
This code copies data byte-by-byte from a memory array to a peripheral device buffer.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop that copies each byte from memory to peripheral.
- How many times: The loop runs exactly
sizetimes, once for each byte.
As the amount of data to transfer grows, the number of copy operations grows in the same way.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 copy operations |
| 100 | 100 copy operations |
| 1000 | 1000 copy operations |
Pattern observation: The number of operations grows directly with the input size; doubling the data doubles the work.
Time Complexity: O(n)
This means the time to transfer data grows linearly with the amount of data.
[X] Wrong: "The transfer time stays the same no matter how much data we send."
[OK] Correct: Each byte must be copied individually, so more data means more time.
Understanding how data transfer time grows helps you explain performance in embedded systems clearly and confidently.
"What if we used DMA (Direct Memory Access) instead of a loop? How would the time complexity change?"
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
