ESP32-S3 SPI: dynamically remap SCLK pin between transactions
Posted: Fri Oct 17, 2025 6:05 pm
Hi everyone,
I’m working on an ESP32-S3 project where I need to communicate with multiple ADCs through isolation.
Each ADC uses a 3-wire SPI interface (no CS), and I’d like to select each ADC by switching which GPIO outputs the SPI clock (SCLK) signal.
The goal is to reassign the SCLK pin between polling each ADC instead of using separate SPI peripherals or additional isolator chips.
Why I want to do this
I have very limited PCB space, and there isn’t enough room between the ICs to route extra CS lines or add more vias and traces.
If I used a dedicated chip-select for each ADC, it would require additional SOIC-8 digital isolators, which I’m trying to avoid to keep the board compact.
This approach would allow me to:
Use just two SOIC-8 digital isolators plus one additional isolated GPIO that I already need.
Enable the clock only for the active ADC, keeping the others idle — which may also help reduce emitted noise from the shared SPI lines. (and current consumption)
Keep the overall design smaller and simpler, while still polling each ADC independently.
What I tried
I attempted to use gpio_matrix_out() to remap the SPI clock signal from one GPIO to another between transactions.
My sequence looks like this:
However, I noticed the following behavior:
If I disable the currently active SCLK pin first, ALL pins doesn’t output any clock after remapping.
If I don’t disable the current pin (the one configured during initialization), then both GPIOs toggle simultaneously with the clock signal.
It seems that once I disconnect the current SCLK output, the SPI peripheral stops driving the internal clock signal, or perhaps it requires some kind of restart — which I’d like to avoid since reinitializing the SPI driver every time would add latency.
My question
Is it possible to dynamically reassign the SPI SCLK pin (on ESP32-S3) between transactions without reinitializing the SPI driver each time?
If yes:
What’s the correct way to safely switch the clock pin using the GPIO matrix?
Do I need to re-enable the SPI peripheral or clear/restart something after remapping?
Any low-level insights, register-level details, or working code examples would be very helpful.
I’m working on an ESP32-S3 project where I need to communicate with multiple ADCs through isolation.
Each ADC uses a 3-wire SPI interface (no CS), and I’d like to select each ADC by switching which GPIO outputs the SPI clock (SCLK) signal.
The goal is to reassign the SCLK pin between polling each ADC instead of using separate SPI peripherals or additional isolator chips.
Why I want to do this
I have very limited PCB space, and there isn’t enough room between the ICs to route extra CS lines or add more vias and traces.
If I used a dedicated chip-select for each ADC, it would require additional SOIC-8 digital isolators, which I’m trying to avoid to keep the board compact.
This approach would allow me to:
Use just two SOIC-8 digital isolators plus one additional isolated GPIO that I already need.
Enable the clock only for the active ADC, keeping the others idle — which may also help reduce emitted noise from the shared SPI lines. (and current consumption)
Keep the overall design smaller and simpler, while still polling each ADC independently.
What I tried
I attempted to use gpio_matrix_out() to remap the SPI clock signal from one GPIO to another between transactions.
My sequence looks like this:
Code: Select all
// 1. Finish one SPI transaction
// 2. Disable the current SCLK pin
gpio_matrix_out(current_io, 0x100, false, false);
// 3. Enable the next GPIO for SCLK
gpio_matrix_out(new_io, spi_periph_signal[host_].spiclk_out, false, false);
buscfg_.sclk_io_num = sclk_io_num;
// 4. Start the next transaction
If I disable the currently active SCLK pin first, ALL pins doesn’t output any clock after remapping.
If I don’t disable the current pin (the one configured during initialization), then both GPIOs toggle simultaneously with the clock signal.
It seems that once I disconnect the current SCLK output, the SPI peripheral stops driving the internal clock signal, or perhaps it requires some kind of restart — which I’d like to avoid since reinitializing the SPI driver every time would add latency.
My question
If yes:
What’s the correct way to safely switch the clock pin using the GPIO matrix?
Do I need to re-enable the SPI peripheral or clear/restart something after remapping?
Any low-level insights, register-level details, or working code examples would be very helpful.