Page 1 of 1

Why is SPI transaction latency (~15 µs for 2-byte transfers) so high on ESP32-S3?

Posted: Fri Oct 31, 2025 7:29 pm
by wvernaschii
Hi everyone,
I’m trying to understand the SPI transaction latency on the ESP32-S3 when communicating with a fast external ADC (ADS7040, 12-bit SPI ADC).
According to my measurements, each SPI transaction (2 bytes per sample) takes about 15 µs, which gives a sampling rate of roughly 65 kSamples/s.
This seems very close to the numbers shown in the official ESP-IDF documentation:
Typical transaction duration for one byte of data:
Interrupt transaction via DMA: 26 µs
Interrupt transaction via CPU: 24 µs
Polling transaction via DMA: 11 µs
Polling transaction via CPU: 9 µs
Note: These values are from the official ESP-IDF SPI Master Driver documentation.
(https://docs.espressif.com/projects/esp ... aster.html)
However, even though the ESP32-S3 SPI peripheral can run at up to 80 MHz, the effective throughput I’m getting is far lower than expected.
I’d like to understand what contributes to this ~9–15 µs per transaction overhead:
Is the bottleneck mainly from DMA descriptor setup, task/ISR switching, chip-select toggling, or FreeRTOS queue handling?
Would using continuous DMA streaming (keeping CS low and sending longer buffers) reduce this significantly?
Would a bare-metal or register-level SPI implementation (bypassing the IDF driver) achieve a much higher sample rate?
Setup details:
MCU: ESP32-S3
ADC: TI ADS7040 (12-bit, SPI, 2 bytes per sample)
SPI clock: up to 20 MHz
ESP-IDF version: v6.0.0
Mode: SPI master, polling transactions via CPU
Any insight or confirmation from Espressif engineers or anyone who has profiled the SPI transaction path would be greatly appreciated.
Thanks in advance!

Re: Why is SPI transaction latency (~15 µs for 2-byte transfers) so high on ESP32-S3?

Posted: Sat Nov 01, 2025 2:45 am
by Sprite
Yep, you're right, each transaction by default needs the CPU to take an interrupt, set up DMA etc before it starts. Newer ESP32s (like the -S3) have a mode called 'segmented transfer' for this (where the DMA stream contains instructions on how to set up the next transfer). Looks like the ESP-IDF driver doesn't support this yet, but there's some example projects out there.