Bird
Raised Fist0
Embedded Cprogramming~20 mins

Memory-to-peripheral transfer in Embedded C - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Memory-to-peripheral Transfer Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output of this DMA transfer status code?
Consider this embedded C code snippet that checks the status of a DMA transfer. What will be printed?
Embedded C
#include <stdio.h>
#include <stdint.h>

#define DMA_TRANSFER_COMPLETE 1

uint8_t DMA_Status = DMA_TRANSFER_COMPLETE;

int main() {
    if (DMA_Status & DMA_TRANSFER_COMPLETE) {
        printf("Transfer Complete\n");
    } else {
        printf("Transfer Incomplete\n");
    }
    return 0;
}
ACompilation error
BTransfer Incomplete
CTransfer Complete
DNo output
Attempts:
2 left
💡 Hint
Look at how the DMA_Status variable is checked using bitwise AND.
❓ Predict Output
intermediate
2:00remaining
What is the value of buffer after this memory-to-peripheral transfer simulation?
This code simulates copying data from memory to a peripheral buffer. What is the final content of buffer?
Embedded C
#include <stdio.h>
#include <string.h>

int main() {
    char memory[] = "DATA";
    char buffer[5] = {0};
    memcpy(buffer, memory, 4);
    buffer[4] = '\0';
    printf("%s", buffer);
    return 0;
}
ADATA
BCompilation error
CDAT
DDATA\0
Attempts:
2 left
💡 Hint
Check how memcpy copies bytes and how the null terminator is added.
🔧 Debug
advanced
3:00remaining
Why does this DMA transfer code cause a runtime error?
Examine this code snippet for a DMA transfer setup. Why does it cause a runtime error?
Embedded C
void start_dma_transfer(uint32_t *src, uint32_t *dst, size_t size) {
    for (size_t i = 0; i < size; i++) {
        dst[i] = src[i];
    }
}

int main() {
    uint32_t source[3] = {1, 2, 3};
    uint32_t destination[3] = {0};
    start_dma_transfer(source, destination, 3);
    return 0;
}
ACompilation error due to missing header
BNull pointer dereference
CNo error, runs fine
DArray index out of bounds causing undefined behavior
Attempts:
2 left
💡 Hint
Check the loop condition and array sizes carefully.
📝 Syntax
advanced
2:00remaining
Which option fixes the syntax error in this DMA transfer initialization?
This code snippet has a syntax error. Which option fixes it?
Embedded C
typedef struct {
    uint32_t *source;
    uint32_t *destination;
    size_t length;
} DMA_Transfer;

void init_dma(DMA_Transfer *transfer) {
    transfer->source = (uint32_t *)0x20000000;
    transfer->destination = (uint32_t *)0x40000000;
    transfer->length = 256;
}
AChange '->' to '.' operator
BAdd a semicolon after the first assignment line
CRemove the cast to (uint32_t *)
DAdd braces around the struct initialization
Attempts:
2 left
💡 Hint
Look carefully at the end of each statement line.
🚀 Application
expert
3:00remaining
How many bytes are transferred in this memory-to-peripheral DMA setup?
Given this DMA transfer configuration, how many bytes will be transferred?
Embedded C
typedef struct {
    uint8_t *src;
    volatile uint8_t *peripheral;
    size_t count;
} DMA_Config;

int main() {
    DMA_Config config = {
        .src = (uint8_t *)0x20001000,
        .peripheral = (volatile uint8_t *)0x40002000,
        .count = 128
    };
    // DMA transfer code here
    return 0;
}
A128 bytes
BCannot determine from code
C64 bytes
D256 bytes
Attempts:
2 left
💡 Hint
Look at the count field and data type size.

Practice

(1/5)
1. What is the main purpose of memory-to-peripheral transfer in embedded systems?
easy
A. To increase the CPU speed during data processing
B. To copy data from one memory location to another memory location
C. To transfer data from a peripheral device back to memory
D. To move data from memory to a device without using the CPU heavily

Solution

  1. Step 1: Understand the role of memory-to-peripheral transfer

    This transfer moves data from memory directly to a peripheral device, reducing CPU involvement.
  2. 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.
  3. Final Answer:

    To move data from memory to a device without using the CPU heavily -> Option D
  4. Quick Check:

    Memory-to-peripheral transfer reduces CPU load = A [OK]
Hint: Memory-to-peripheral means memory to device, not memory to memory [OK]
Common Mistakes:
  • Confusing memory-to-peripheral with peripheral-to-memory transfer
  • Thinking it increases CPU speed
  • Assuming it copies memory internally
2. Which of the following is the correct way to enable memory increment mode in a DMA configuration in embedded C?
easy
A. DMA->CCR &= ~DMA_CCR_MINC;
B. DMA->CCR |= DMA_CCR_MINC;
C. DMA->CCR = DMA_CCR_MINC;
D. DMA->CCR ^= DMA_CCR_MINC;

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    DMA->CCR |= DMA_CCR_MINC; -> Option B
  4. Quick Check:

    Enable bit with |= operator = A [OK]
Hint: Use |= to set bits without changing others [OK]
Common Mistakes:
  • Using &= ~ to enable bits (actually disables)
  • Assigning directly which clears other bits
  • Using ^= which toggles bits unpredictably
3. Given the following code snippet configuring a DMA transfer, what will be the value of the peripheral data register after the transfer completes?
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
medium
A. 30
B. 10
C. 20
D. 0

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    30 -> Option A
  4. Quick Check:

    Last transferred value = 30 [OK]
Hint: Peripheral register ends with last memory value sent [OK]
Common Mistakes:
  • Assuming peripheral holds first or middle value
  • Ignoring memory increment effect
  • Confusing transfer count with data index
4. Identify the error in this DMA memory-to-peripheral transfer setup:
DMA->CCR = DMA_CCR_DIR;
DMA->CNDTR = 5;
DMA->CPAR = (uint32_t)&PERIPH->DR;
DMA->CMAR = (uint32_t)data_array;
// Start DMA transfer
medium
A. Memory increment mode is not enabled, so only first data is sent repeatedly
B. Peripheral address is incorrect, should point to memory
C. Transfer count is set too high causing overflow
D. DMA direction bit is cleared, so transfer is peripheral to memory

Solution

  1. Step 1: Check memory increment setting

    DMA_CCR_MINC bit is missing, so memory address does not increment during transfer.
  2. Step 2: Understand effect of missing memory increment

    Without memory increment, DMA sends the same memory location repeatedly to peripheral, not the full array.
  3. Final Answer:

    Memory increment mode is not enabled, so only first data is sent repeatedly -> Option A
  4. Quick Check:

    Missing MINC bit causes repeated data = D [OK]
Hint: Always enable memory increment for multiple data items [OK]
Common Mistakes:
  • Assuming peripheral address should point to memory
  • Thinking transfer count causes overflow here
  • Misreading direction bit status
5. You want to transfer a block of 4 bytes from memory to a UART peripheral using DMA. The memory buffer is at address 0x20001000 and the UART data register is at 0x40013804. Which DMA configuration correctly sets the source, destination, and enables memory increment for this transfer?
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;
hard
A. DMA->CPAR = 0x40013804; DMA->CMAR = 0x20001000; DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR;
B. DMA->CPAR = 0x20001000; DMA->CMAR = 0x40013804; DMA->CCR = DMA_CCR_MINC;
C. DMA->CMAR = 0x20001000; DMA->CPAR = 0x40013804; DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR;
D. DMA->CMAR = 0x40013804; DMA->CPAR = 0x20001000; DMA->CCR = DMA_CCR_DIR;

Solution

  1. Step 1: Identify source and destination addresses

    Memory buffer is source (CMAR), peripheral register is destination (CPAR).
  2. Step 2: Check DMA direction and memory increment

    DMA_CCR_DIR set means memory-to-peripheral transfer; DMA_CCR_MINC enables memory address increment.
  3. 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.
  4. Final Answer:

    DMA->CMAR = 0x20001000; DMA->CPAR = 0x40013804; DMA->CCR = DMA_CCR_MINC | DMA_CCR_DIR; -> Option C
  5. Quick Check:

    Memory in CMAR, peripheral in CPAR, DIR and MINC set = A [OK]
Hint: Peripheral address in CPAR, memory in CMAR, set DIR and MINC bits [OK]
Common Mistakes:
  • Swapping source and destination addresses
  • Forgetting to set memory increment bit
  • Not setting direction bit for memory-to-peripheral
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard