Bird
Raised Fist0
Embedded Cprogramming~5 mins

Peripheral-to-memory transfer in Embedded C

Choose your learning style10 modes available
Introduction

Peripheral-to-memory transfer moves data from a device like a sensor or communication port directly into memory. This helps programs get data without waiting or using extra steps.

Reading sensor data continuously into memory for processing.
Receiving data from a communication port like UART or SPI.
Storing audio or video data from a camera or microphone.
Logging data from a peripheral device without CPU delay.
Syntax
Embedded C
DMA_Channel->CCR = DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_EN;
DMA_Channel->CPAR = (uint32_t)&PERIPHERAL_DATA_REGISTER;
DMA_Channel->CMAR = (uint32_t)memory_buffer;
DMA_Channel->CNDTR = data_length;

This example shows setting up a DMA channel for peripheral-to-memory transfer.

DMA_CCR_MINC enables memory address increment, so data fills the buffer.

Examples
Setup DMA channel 1 to transfer 100 ADC readings from ADC data register to adc_buffer in memory.
Embedded C
DMA1_Channel1->CCR = DMA_CCR_MINC | DMA_CCR_EN;
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
DMA1_Channel1->CMAR = (uint32_t)adc_buffer;
DMA1_Channel1->CNDTR = 100;
Configure DMA channel 3 to receive 50 bytes from SPI1 data register into spi_rx_buffer with transfer complete interrupt enabled.
Embedded C
DMA2_Channel3->CCR = DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_EN;
DMA2_Channel3->CPAR = (uint32_t)&SPI1->DR;
DMA2_Channel3->CMAR = (uint32_t)spi_rx_buffer;
DMA2_Channel3->CNDTR = 50;
Sample Program

This program simulates a peripheral-to-memory transfer using a DMA channel. It copies 10 bytes from a simulated peripheral data array into a memory buffer and prints the result.

Embedded C
#include <stdint.h>
#include <stdio.h>

// Simulated peripheral data register
volatile uint8_t PERIPHERAL_DATA_REGISTER = 0;

// Buffer in memory to store data
uint8_t memory_buffer[10];

// Simulated DMA channel structure
typedef struct {
    uint32_t CCR;
    uint32_t CPAR;
    uint32_t CMAR;
    uint32_t CNDTR;
} DMA_Channel_TypeDef;

DMA_Channel_TypeDef DMA_Channel1;

// Constants for DMA control register bits
#define DMA_CCR_MINC  (1 << 7)  // Memory increment mode
#define DMA_CCR_EN    (1 << 0)  // Channel enable

// Function to simulate peripheral-to-memory transfer
void start_dma_transfer(DMA_Channel_TypeDef *dma, volatile uint8_t *peripheral, uint8_t *memory, uint32_t length) {
    dma->CPAR = (uint32_t)peripheral;
    dma->CMAR = (uint32_t)memory;
    dma->CNDTR = length;
    dma->CCR = DMA_CCR_MINC | DMA_CCR_EN;

    // Simulate transfer: copy data from peripheral to memory
    for (uint32_t i = 0; i < length; i++) {
        memory[i] = peripheral[i];
    }

    // Disable DMA after transfer
    dma->CCR &= ~DMA_CCR_EN;
}

int main() {
    // Simulate peripheral data as an array
    volatile uint8_t peripheral_data[10] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};

    // Start DMA transfer from peripheral_data to memory_buffer
    start_dma_transfer(&DMA_Channel1, peripheral_data, memory_buffer, 10);

    // Print memory buffer contents
    for (int i = 0; i < 10; i++) {
        printf("%d ", memory_buffer[i]);
    }
    printf("\n");

    return 0;
}
OutputSuccess
Important Notes

Peripheral-to-memory transfer often uses DMA to avoid CPU load.

Memory increment mode (MINC) is important to fill buffers correctly.

Always disable DMA channel after transfer to avoid unintended behavior.

Summary

Peripheral-to-memory transfer moves data directly from device to memory.

DMA hardware helps do this efficiently without CPU waiting.

Setup involves configuring source, destination, length, and enabling DMA.

Practice

(1/5)
1. What is the main purpose of peripheral-to-memory transfer in embedded systems?
easy
A. To execute arithmetic operations on peripheral data
B. To send data from memory back to the peripheral device
C. To move data directly from a peripheral device to memory without CPU intervention
D. To reset the peripheral device after data transfer

Solution

  1. Step 1: Understand peripheral-to-memory transfer

    This transfer moves data directly from a peripheral device to memory, bypassing the CPU to improve efficiency.
  2. Step 2: Identify the main purpose

    The main goal is to reduce CPU load by letting hardware handle data movement.
  3. Final Answer:

    To move data directly from a peripheral device to memory without CPU intervention -> Option C
  4. Quick Check:

    Peripheral-to-memory transfer = direct data move without CPU [OK]
Hint: Peripheral-to-memory means data moves without CPU help [OK]
Common Mistakes:
  • Confusing peripheral-to-memory with memory-to-peripheral transfer
  • Thinking CPU processes data during transfer
  • Assuming transfer resets the device
2. Which of the following is the correct way to enable DMA for peripheral-to-memory transfer in embedded C?
easy
A. DMA_Channel->CCR = DMA_CCR_EN << 1;
B. DMA_Channel->CCR |= DMA_CCR_EN;
C. DMA_Channel->CCR &= ~DMA_CCR_EN;
D. DMA_Channel->CCR = 0;

Solution

  1. Step 1: Understand DMA enable bit setting

    To enable DMA channel, the enable bit (DMA_CCR_EN) must be set using bitwise OR to preserve other bits.
  2. Step 2: Analyze options

    DMA_Channel->CCR |= DMA_CCR_EN; sets the enable bit correctly with |=. DMA_Channel->CCR = 0; clears all bits, disabling DMA. DMA_Channel->CCR &= ~DMA_CCR_EN; clears the enable bit. DMA_Channel->CCR = DMA_CCR_EN << 1; shifts enable bit incorrectly.
  3. Final Answer:

    DMA_Channel->CCR |= DMA_CCR_EN; -> Option B
  4. Quick Check:

    Enable DMA by setting bit with |= [OK]
Hint: Use |= to set enable bit without clearing others [OK]
Common Mistakes:
  • Using = instead of |= clears other bits
  • Clearing enable bit instead of setting it
  • Shifting bits incorrectly
3. Given the following code snippet, what will be the value of memory_buffer[0] after DMA transfer completes?
uint8_t peripheral_data = 0x55;
uint8_t memory_buffer[1] = {0x00};
// DMA configured to transfer 1 byte from &peripheral_data to memory_buffer
// DMA transfer completes here
medium
A. 0x55
B. 0x00
C. 0xFF
D. Undefined (random value)

Solution

  1. Step 1: Understand DMA transfer setup

    DMA is set to transfer 1 byte from peripheral_data (0x55) to memory_buffer.
  2. Step 2: Determine memory_buffer[0] after transfer

    After transfer, memory_buffer[0] will hold the value 0x55 copied from peripheral_data.
  3. Final Answer:

    0x55 -> Option A
  4. Quick Check:

    DMA copies 0x55 to memory_buffer[0] [OK]
Hint: DMA copies source byte to destination buffer [OK]
Common Mistakes:
  • Assuming memory_buffer stays unchanged
  • Confusing peripheral_data value
  • Thinking DMA sets memory to 0xFF
4. Identify the error in this DMA peripheral-to-memory transfer setup code snippet:
DMA_Channel->CPAR = (uint32_t)&memory_buffer;
DMA_Channel->CMAR = (uint32_t)&peripheral_data;
DMA_Channel->CNDTR = 4;
DMA_Channel->CCR &= ~DMA_CCR_EN;
DMA_Channel->CCR |= DMA_CCR_EN;
medium
A. The DMA channel is enabled before setting transfer length
B. The DMA channel is enabled without disabling first
C. The transfer length (CNDTR) is set after enabling DMA
D. The peripheral address and memory address are swapped

Solution

  1. Step 1: Recall DMA register roles

    CPAR holds peripheral (source) address, CMAR holds memory (destination) address for peripheral-to-memory transfer.
  2. Step 2: Check the code assignments

    The code sets CPAR = &memory_buffer (should be peripheral), CMAR = &peripheral_data (should be memory). Addresses are swapped.
  3. Final Answer:

    The peripheral address and memory address are swapped -> Option D
  4. Quick Check:

    CPAR=peripheral, CMAR=memory [OK]
Hint: Peripheral address = CPAR, Memory address = CMAR [OK]
Common Mistakes:
  • Swapping peripheral and memory addresses
  • Enabling DMA before setting parameters
  • Not disabling DMA before re-enabling
5. You want to transfer 8 bytes from a UART peripheral data register to a memory buffer using DMA. Which sequence correctly sets up the DMA for peripheral-to-memory transfer?
hard
A. Set DMA peripheral address to UART data register; set memory address to buffer; set transfer length to 8; enable DMA channel
B. Set DMA memory address to UART data register; set peripheral address to buffer; set transfer length to 8; enable DMA channel
C. Set DMA peripheral address to buffer; set memory address to UART data register; set transfer length to 8; enable DMA channel
D. Set DMA transfer length to 8; enable DMA channel; set peripheral and memory addresses afterwards

Solution

  1. Step 1: Identify source and destination

    Source is UART data register (peripheral), destination is memory buffer.
  2. Step 2: Set DMA registers correctly

    Peripheral address register (CPAR) must point to UART data register, memory address register (CMAR) to buffer, transfer length to 8 bytes, then enable DMA channel.
  3. Final Answer:

    Set DMA peripheral address to UART data register; set memory address to buffer; set transfer length to 8; enable DMA channel -> Option A
  4. Quick Check:

    Peripheral = source, Memory = destination, length set before enable [OK]
Hint: Peripheral address = source, memory address = destination [OK]
Common Mistakes:
  • Swapping peripheral and memory addresses
  • Enabling DMA before setting addresses and length
  • Setting transfer length after enabling DMA
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