Faster ESP32

Introduction: Faster ESP32

About: Do you like technology? Follow my channel on Youtube and my Blog. In them I put videos every week of microcontrollers, arduinos, networks, among other subjects.

There are two ways to make the ESP32 GPIO stay at 0 or 1. You can call the #digitalwrite function, or you can go straight to the recorder. I’m showing the second option today: how to go straight to the register and write in the memory. This way, the command will instantly change state. Thus, we’ll first learn how to modify multiple GPIOs at once by using bitmasks. In our example today, we used five leds.

Step 1: Demonstration

Step 2: Registers /sdk/include/soc/soc/rtc_io_struct.h

union {
struct { uint32_t reserved0:14; uint32_t w1ts:18; /*GPIO0~17 output value write 1 to set*/ }; uint32_t val; } out_w1ts; union { struct { uint32_t reserved0:14; uint32_t w1tc:18; /*GPIO0~17 output value write 1 to clear*/ }; uint32_t val; } out_w1tc;

Step 3: DigitalWrite ESP32 Code Arduino /cores/esp32/esp32-hal-gpio.c

extern void IRAM_ATTR __digitalWrite(uint8_t pin, uint8_t val)

{ if(val) { if(pin < 32) { GPIO.out_w1ts = ((uint32_t)1 << pin); } else if(pin < 34) { GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); } } else { if(pin < 32) { GPIO.out_w1tc = ((uint32_t)1 << pin); } else if(pin < 34) { GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); } } }

Step 4: Multiple Pins at Once Ex.1

Setup

void setup()
{ //Configuração dos gpios gpio_config_t io_conf //Colocamos como OUTPUT io_conf.mode = GPIO_MODE_OUTPUT; //Definição dos gpios que fazem parte desta configuração //Da direita para a esquerda, os que tem 1 fazem parte da configuração //Neste exemplo, contando da direita para esquerda (começando do 0) temos o gpio 2 e o gpio 4 //Para facilitar quando temos pinos de valor alto podemos utilizar //deslocamento de bits, por exemplo: (1 << 2) | (1 << 4) io_conf.pin_bit_mask = 0b10100; //Ou poderia ser //io_conf.pin_bit_mask = (1 << 2) | (1 << 4); //Aplica a configuração gpio_config(&io_conf); }

Loop

void loop()
{ //Máscara de bits com os pinos que serão "setados" como ativos GPIO.out_w1ts = 0b10100; //Ou poderia ser //GPIO.out_w1ts = (1 << 2) | (1 << 4); //Delay de 1 segundo delay(1000); //Máscara de bits com os pinos serão desativados (clear) GPIO.out_w1tc = 0b10100; //Ou poderia ser //GPIO.out_w1tc = (1 << 2) | (1 << 4); //Delay de 1 segundo delay(1000); }

Step 5: Multiple Pins at Once Ex.2

Setup

//Máscara com os GPIOs 0, 2 e 4
//Se invertermos esta máscara com "~" teremos 0b01010 //e passamos a ter selecionados os GPIOs 1 e 3 int mask = 0b10101; void setup() { //Configuração dos gpios gpio_config_t io_conf; //Colocamos como OUTPUT io_conf.mode = GPIO_MODE_OUTPUT; //Definição dos gpios que fazem parte desta configuração //Da direita para a esquerda, os que tem 1 fazem parte da conifguração //No caso os GPIOs 0, 1, 2, 3 e 4 io_conf.pin_bit_mask = 0b11111; //Aplica a configuração gpio_config(&io_conf); }

Loop

void loop()
{ //Invertamos os bits da máscara //Os que estavam selecionados são desselecionados e vice-versa mask = ~mask; //Máscara de bits com os pinos que serão "setados" como ativos GPIO.out_w1ts = mask; //Máscara de bits com os pinos que serão desativados (clear) GPIO.out_w1tc = ~mask; //Delay de 1 segundo delay(1000); }

Step 6: Digital Speed TestWrite

void setup()
{ pinMode(4, OUTPUT); } void loop() { digitalWrite(4, HIGH); digitalWrite(4, LOW); }

Step 7: Speed ​​Test Bit Mask

void setup()

{ //Configuração dos gpios gpio_config_t io_conf; //Colocamos como OUTPUT io_conf.mode = GPIO_MODE_OUTPUT; //Definição dos gpios que fazem parte desta configuração io_conf.pin_bit_mask = 0b10000; //Aplica a configuração gpio_config(&io_conf); } void loop() { //Máscara de bits com os pinos que serão "setados" como ativos GPIO.out_w1ts = 0b10000; //Máscara de bits com os pinos serão desativados (clear) GPIO.out_w1tc = 0b10000; }

Step 8: Result Digital Speed TestWrite

Step 9: Result GPIO Mask Speed Test

Step 10: DOWNLOAD THE FILES

Be the First to Share

    Recommendations

    • Big and Small Contest

      Big and Small Contest
    • Make It Bridge

      Make It Bridge
    • For the Home Contest

      For the Home Contest

    3 Comments

    0
    brendlefly62
    brendlefly62

    3 months ago

    I know this is an old thread, but I'm new to the ESP32. The speed-test results are even more significant if you modify the test to write to multiple GPIOs (which you can do simultaneously with one instruction the "new" way). On ESP32, writing to 3 consecutive GPIOs (RED, GRN, BLU in the code below), the difference is an order of magnitude. Summary:

    "Old way": Period ~2.2us (freq. approx. = 455Khz), and there is a 300ns phase-lag between RED and GRN pulses; 600ns lag RED-BLU, due to sequential writes (see images)

    "New way": Period ~200ns (freq. approx. = 5Mhz), and there is no lag - pulses are simultaneous.

    These images are screenshots from my 10-yr-old 2-chan USB O'scope. RED is the red line in all images, but there are two images for each "way" - one shows GRN in blue, the other shows BLU in blue. The 5Mhz signal is really too fast for it, but it has captured the fundamental frequency and relative phase of the output signals.

    ------------------------------[ code ]----------------------------------------
    #include

    // define gpios-- use consecutive GPIOs (consecutive io register bits)
    // so "new way" can write all of them with one instruction
    #define RED 17
    #define GRN 18
    #define BLU 19

    // config gpios
    gpio_config_t io_conf;

    void setup()
    {

    // output mode - old way
    pinMode(RED, OUTPUT);
    pinMode(GRN, OUTPUT);
    pinMode(BLU, OUTPUT);

    // output mode - new way
    io_conf.intr_type = (gpio_int_type_t)GPIO_PIN_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    // io_conf.pin_bit_mask = (1 << RED) | (1 << GRN) | (1 << BLU); // or
    io_conf.pin_bit_mask = (0b111 << RED); // or
    // io_conf.pin_bit_mask = (0b11100000000000);
    gpio_config(&io_conf);
    }

    void old_way()
    {
    digitalWrite(RED, HIGH);
    digitalWrite(GRN, HIGH);
    digitalWrite(BLU, HIGH);
    digitalWrite(RED, LOW);
    digitalWrite(GRN, LOW);
    digitalWrite(BLU, LOW);
    }

    void new_way() {
    // GPIO.w1ts = (1 << RED) | (1 << GRN) | (1 << BLU); // or
    GPIO.out_w1ts = (0b111 << RED);
    // GPIO.out_w1tc = (1 << RED) | (1 << GRN) | (1 << BLU); //or
    GPIO.out_w1tc = (0b111 << RED);
    }

    void loop() { new_way(); }

    RED-BLU_NewWay_ 2022-11-22_151338.jpgRED-GRN_NewWay_ 2022-11-22_151338.jpgRED-BLU_OldWay_ 2022-11-22_151338.jpgRED-GRN_OldWay_ 2022-11-22_151338.jpg
    0
    jeanyves.filoche
    jeanyves.filoche

    2 years ago

    I found that ";" is missing at the end of "gpio_config_t io_conf"
    Thank you for this software.
    JY

    0
    jeanyves.filoche
    jeanyves.filoche

    Question 2 years ago on Step 10

    Hello Mr. Fernando Koyanagi
    I like the way you quickly change the state of ESP32's GPIOs. However, while uploading your examples to the Arduino IDE, I get the following message: "expected initializer before 'io_conf'".
    Where is my mistake?
    Thank you for your reply.
    jyfiloche@sfr.fr