Ground Embedded KO Subscribe

Notes / MCU Firmware

Using DMA: ADC and UART without the CPU

Two practical DMA setups: keep filling a circular buffer with ADC values, and receive UART packets of unknown length.

GROUND EMBEDDED · NOTEMCU Firmware 09Using DMAAvg 30%D1 period

ADC + circular DMA

First halfhandled in the Half callbackSecond halfhandled in the Complete callback
Circular DMA buffer. A callback arrives each time half is full, so you process the half just filled while DMA fills the other.

DMA keeps writing the ADC scan results into an array. The CPU only has to read the array, and the latest values are there.

uint16_t adc_buf[4];
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buf, 4);   // keeps updating when set to circular mode

When collecting a long waveform, split the buffer in two and process the opposite half on each half-complete / complete interrupt (double buffering).

UART receive + IDLE line

RX lineIDLE interrupt
When the line goes quiet for one byte time after data, the IDLE interrupt fires. You know where the packet ends without knowing its length.

This is the standard approach when the packet length is unknown.

  1. Keep receiving UART RX into a large buffer (for example 256 bytes) with circular DMA
  2. When the line is quiet for more than one byte time, an IDLE interrupt fires
  3. Work out the current write position from the DMA remaining count (NDTR) and process only the newly arrived section

HAL provides HAL_UARTEx_ReceiveToIdle_DMA().

Things to check

  • DMA stream and channel numbers are fixed for each peripheral (see the table in the reference manual).
  • Some chips have memory regions DMA cannot access (CCM RAM and DTCM on some STM32 parts).
  • On chips with a cache (H7, F7), put DMA buffers in a non-cached region, or clean and invalidate the cache.
FREE PDFGet the 3 free ebooksIf you want to keep reading this topic as one book: BLDC motor control, serial communication and sensors at book length. PDFs are in Korean.Get them free →