Very fast GPIO on ESP32 [EN]
Posted: 29 October 2025, 17:26 - Wed
Hi,
The ESP32 is a readily available SoC microcomputer with a generous amount of RAM and Flash memory and many useful interfaces. You can use it to build truly complex devices... but sometimes you need to reduce this "monster" to a microcontroller! Of course, its excess resources won't bother you
Today, I'll show you a relatively simple example of how to access fast GPIOs...
To illustrate the example, I used the DevKit-C module with the ESP32-S3 (16R8N) chip, but it can be any ESP32
Prerequisites:
- Espressif SDK environment: https://docs.espressif.com/projects/esp ... setup.html
- any editor (I use Geany under Linux)
Code:
At this point, I would like to thank my colleague Jaromir Kopp: https://www.facebook.com/groups/1100373 ... 1057020183
Jaromir suggested some very practical things to me and showed me a fragment of the code on which I based my example. You may find comments related to this topic here: https://www.facebook.com/groups/1100373 ... 347866662/
By using a dedicated GPIO and assembler, the maximum frequency achieved when toggling a single GPIO bit on the port was 48MHz at a 240MHz clock speed. Of course, this is just a proof of concept, and the actual speed will decrease significantly when we add logic to the program. However, I'd like to point out that the same task performed in Arduino code yields a maximum of 1.3MHz, while in the PlatformiO/VCS/Espressif environment, I achieved a full 8MHz. The difference is: 1.3 --> 8 -> 48MHz
What do you think?
It's also worth mentioning that the ESPidf environment utilizes the FreeRTOS RTOS, which has many advantages, but also some disadvantages. The system overhead can introduce interference into your main program, for example, by sending watchdog logs to the console. You may then disable some of the FreeRTOS add-ons in 'menuconfig' e.g.:
Have fun!
The ESP32 is a readily available SoC microcomputer with a generous amount of RAM and Flash memory and many useful interfaces. You can use it to build truly complex devices... but sometimes you need to reduce this "monster" to a microcontroller! Of course, its excess resources won't bother you
Today, I'll show you a relatively simple example of how to access fast GPIOs...
To illustrate the example, I used the DevKit-C module with the ESP32-S3 (16R8N) chip, but it can be any ESP32
Prerequisites:
- Espressif SDK environment: https://docs.espressif.com/projects/esp ... setup.html
- any editor (I use Geany under Linux)
Code:
Code: Select all
#include "driver/gpio.h"
#include "driver/dedic_gpio.h"
// Define the GPIO pin for test (GPIO 2 is common for onboard LEDs)
#define BLINK_GPIO 2
static inline __attribute__((__always_inline__)) void IRAM_ATTR directWriteHigh(const uint8_t dedic_io_num)
{
__asm__ __volatile__ ("ee.set_bit_gpio_out %0" : : "I"(dedic_io_num) : );
}
static inline __attribute__((__always_inline__)) void IRAM_ATTR directWriteLow(const uint8_t dedic_io_num)
{
__asm__ __volatile__ ("ee.clr_bit_gpio_out %0" : : "I"(dedic_io_num) : );
}
static inline __attribute__((__always_inline__)) void IRAM_ATTR LeExp(void)
{
gpio_reset_pin(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
dedic_gpio_bundle_handle_t dedic_gpio = NULL;
dedic_gpio_bundle_config_t dedic_gpio_conf = {
.flags.out_en = true,
.gpio_array = (int[])
{
BLINK_GPIO
},
.array_size = 1,
};
ESP_ERROR_CHECK(dedic_gpio_new_bundle(&dedic_gpio_conf, &dedic_gpio));
while(1)
{
directWriteHigh(1);
directWriteLow(1);
}
}
void app_main(void)
{
LeExp();
}
Jaromir suggested some very practical things to me and showed me a fragment of the code on which I based my example. You may find comments related to this topic here: https://www.facebook.com/groups/1100373 ... 347866662/
By using a dedicated GPIO and assembler, the maximum frequency achieved when toggling a single GPIO bit on the port was 48MHz at a 240MHz clock speed. Of course, this is just a proof of concept, and the actual speed will decrease significantly when we add logic to the program. However, I'd like to point out that the same task performed in Arduino code yields a maximum of 1.3MHz, while in the PlatformiO/VCS/Espressif environment, I achieved a full 8MHz. The difference is: 1.3 --> 8 -> 48MHz
It's also worth mentioning that the ESPidf environment utilizes the FreeRTOS RTOS, which has many advantages, but also some disadvantages. The system overhead can introduce interference into your main program, for example, by sending watchdog logs to the console. You may then disable some of the FreeRTOS add-ons in 'menuconfig' e.g.:
Have fun!