0
0
Embedded Cprogramming~5 mins

Peripheral-to-memory transfer in Embedded C

Choose your learning style9 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.