Skip to content
BoKSA

Input/Output and DMA

Input/Output and DMA

Introduction

Input/Output (I/O) connects the CPU to the outside world: GPIO, ADC, UART, SPI, I2C, Ethernet MAC, and more. On embedded systems, I/O is usually memory-mapped — reading/writing specific addresses controls hardware registers. DMA (Direct Memory Access) moves data between memory and peripherals without the CPU copying every byte — essential for audio, SD cards, and high-speed sensors.


Programmed I/O

The CPU explicitly reads/writes each data item:

1
2
3
// Conceptual: wait until UART transmit buffer empty, then send byte
while (!(UART->SR & TXE)) { }
UART->DR = byte;
Mode Description
Polling CPU loops checking status flags — simple, wastes cycles
Interrupt-driven Device signals ready; CPU handles batches
DMA Hardware transfers blocks; CPU notified on complete

Use polling only for bring-up or very slow I/O; prefer interrupts or DMA for throughput.


I/O configuration

Peripherals expose control/status registers:

Register type Examples
Data TX/RX buffer, ADC result
Status Busy, error, buffer full
Control Enable, mode, baud rate, interrupt enable
Configuration Pin mux, clock source

HAL (Hardware Abstraction Layer) wraps registers; bare-metal accesses volatile uint32_t * pointers — both map to the same silicon.

Pin multiplexing

One physical pin serves multiple functions (GPIO vs SPI vs UART). Pin mux must match PCB wiring — a common source of "it compiles but does nothing."


Synchronous vs asynchronous buses

Synchronous Asynchronous
Clock Shared clock line Handshake signals (ready/valid)
Examples SPI, I2C UART, some parallel buses
Timing Edge-aligned to clock Receiver samples with agreed baud or strobe
Distance/speed Short, fast on PCB UART tolerant of cable length at lower speed

SPI: master clocks MOSI/MISO; chip select per slave.
I2C: open-drain, pull-ups, addresses on 2 wires.
UART: start bit + data + optional parity + stop bits — see Serial communication protocols.


DMA

DMA controller performs memory ↔ peripheral transfers while CPU runs other code (or sleeps).

flowchart LR MEM[(Memory buffer)] DMA[DMA controller] PER[Peripheral FIFO] CPU[CPU] DMA <-->|Burst transfers| MEM DMA <-->|Hardware handshake| PER CPU -->|Configure channels| DMA DMA -->|Interrupt on complete| CPU

Benefits

  • Lower CPU load for large transfers
  • Steadier sampling (ADC + DMA ring buffer)
  • Required for SDMMC, Ethernet, display controllers at speed

Caveats

  • Buffer alignment and cache coherency (Cortex-A)
  • Circular (ring) mode for continuous ADC streams
  • Race conditions — do not read buffer while DMA writes same region

I/O addressing schemes

Scheme Used on
Memory-mapped ARM, RISC-V, most MCUs — *(uint32_t*)0x40021018
Port-mapped (isolated) x86 IN/OUT instructions — rare in embedded
Message-signalled PCIe on high-end SoCs

Embedded: assume memory-mapped unless datasheet says otherwise.


Storage attachment (embedded Linux)

Interface Typical device
SD/MMC Removable SD card
eMMC Soldered flash on module
NOR/NAND Raw flash with MTD driver
USB mass storage Thumb drive

SAN/NAS appear when the device is a network client to remote storage — see Memory systems.


Relevant topics


Starting points

  1. Trace one UART TX byte from write() to register level in debugger.
  2. Implement interrupt-driven RX ring buffer — compare CPU load to polling.
  3. Configure ADC + DMA circular mode — plot samples in serial plotter.
  4. Document pin mux table for your board (pin, function, pull-up/down).

Focus points

  • Volatile keyword for hardware registers — compiler must not optimize away reads.
  • Clear flags in ISR per reference manual (some need write-1-to-clear).
  • DMA half/full complete interrupts for double buffering.
  • Do not start DMA before peripheral and clocks are enabled.

Key points

  • Programmed I/O uses CPU loads/stores; DMA offloads bulk transfers.
  • Memory-mapped registers configure and use peripherals on typical MCUs.
  • Sync buses (SPI/I2C) use a clock; async (UART) rely on timing agreement.
  • Pin mux, alignment, and cache matter for correct and efficient I/O.