Why is SPI transaction latency (~15 µs for 2-byte transfers) so high on ESP32-S3?
Posted: Fri Oct 31, 2025 7:29 pm
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:
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!
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:
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.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)
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!