Overcoming the 2 MSPS ADC Bottleneck

Van C. Ngo · September 15, 2026

Overcoming the 2 MSPS ADC Bottleneck

When sampling a 12-bit ADC at 2 MSPS on a 400 MHz MCU, relying on CPU interrupts is a recipe for system lockup. With only 500ns between samples, you have a strict budget of just 200 CPU cycles. Once you account for context saving and IRQ exit latency, your CPU is completely saturated.

To reclaim your processor, we must architect a system that operates entirely in the background.


The Autonomous Hardware Chain

The secret to zero-overhead data acquisition is daisy-chaining your MCU’s hardware peripherals. We decouple the hardware from the math using Double-Buffered (Ping-Pong) DMA.

  • The Trigger: A PWM timer running at exactly 2 MHz is configured to generate a Start of Conversion (SOC) on ADC Channel 0.
  • The ADC: Upon completing the 12-bit conversion, the ADC generates a hardware event mapped directly to a DMA request.
  • The Transfer: You must configure a DMA channel to pull the data from the device’s internal FIFO and stream it directly into your RAM.

The 512-Sample Ping-Pong Architecture

Instead of handling data sample by sample, the DMA controller fills massive blocks of memory while the CPU sleeps.

  • Define two 512-sample arrays to act as a Ping-Pong double buffer in memory.
  • The DMA continuously streams the incoming ADC results into the active buffer.
  • The EDMA fires an interrupt only when a 512-sample buffer is completely full.

  • Because we process blocks instead of single samples, the interrupt frequency plummets from 2,000,000 Hz to approximately 3.9kHz.

Welford RMS & CPU Cycle Budget

Inside the 3.9kHz interrupt handler, we need to calculate the Root Mean Square (RMS) of the 512-sample block. Using standard summation for squares can quickly cause numerical overflow, so we apply Welford’s method to compute variance in a single pass using a robust iterative formula:

\[M_k = M_{k-1} + \frac{x_k - M_{k-1}}{k}\] \[S_k = S_{k-1} + (x_k - M_{k-1})(x_k - M_k)\]

By shifting to a 3.9kHz interrupt rate, your available CPU time between interrupts expands from 200 cycles to an enormous 102,400 cycles (256us at 400 MHz). Running Welford’s method over 512 samples requires only a few thousand cycles.

  • Your CPU load drops from total saturation to a fraction of its capacity, while maintaining mathematically perfect continuous phase tracking.

  • You can verify this exact CPU utilization by toggling a dedicated GPIO pin high at the start of your ISR and low at the end, measuring the Worst Case Execution Time (WCET) on an oscilloscope.