Page 1 of 1

Does gpio_set_level() before gpio_set_direction() work?

Posted: Mon Jul 04, 2022 7:40 pm
by brianpdx
I'd like to ensure that when I configure a GPIO as an output it has a known initial state.

Will gpio_set_level() configure a GPIO properly before it has been set as an output, for example:

Code: Select all

gpio_num_t gpio = /* some valid GPIO pin # */;

gpio_set_level(gpio, 0);
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
If not, how can a GPIO be configured to have a particular output state when the pin is switched to GPIO_MODE_OUTPUT?

Re: Does gpio_set_level() before gpio_set_direction() work?

Posted: Mon Jul 04, 2022 9:11 pm
by gtjoseph
The short answer is that "yes, calling gpio_set_leve() should work".

I believe that it will take effect although I can't test it right this second. gpio_set_level() checks that the gpio can be an output pin but not whether it's currently set as an output pin. It then updates the gpio driver structure. When you call gpio_set_direction(), it makes the same check then calls gpio_output_enable(). That does the check yet again and causes more structure bits to be set but then it calls esp_rom_gpio_connect_out_signal() which actually does the work to connect the gpio.

You can learn a lot by looking at the ESP_IDF source code. :D

Re: Does gpio_set_level() before gpio_set_direction() work?

Posted: Tue Jul 05, 2022 4:09 am
by brianpdx
Thank you for your reply.

I had a look through the source code and it's still not clear to me whether gpio_set_level() is guaranteed to set the output state prior to gpio_set_direction(). Mainly this could be due to my unfamiliarity with the ESP-IDF source code, but it looks like the actual configuration is done by writing to fields of a gpio_dev_s structure which is (presumably?) mapped to a magic address the hardware responds to when modifications are made. The low level calls look like:

Code: Select all

static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32_t level)
{
    if (level) {
        hw->out_w1ts.out_w1ts = (1 << gpio_num);
    } else {
        hw->out_w1tc.out_w1tc = (1 << gpio_num);
    }
}
and

Code: Select all

static inline __attribute__((always_inline)) void gpio_ll_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
{
    hw->enable_w1ts.enable_w1ts = (0x1 << gpio_num);
}
But what are the rules in the hardware? Is a write to hw->out_w1ts.out_w1ts before we've written to hw->enable_w1ts.enable_w1ts guaranteed to be honored?

Again, if I just haven't dug deep enough into the ESP-IDF source I apologize but I wonder if this is something that can only be definitively answered by an Espressif hardware engineer...

Re: Does gpio_set_level() before gpio_set_direction() work?

Posted: Tue Jul 05, 2022 6:21 am
by ESP_Sprite
The hardware is pretty simple: it'll process requests as they come in. The structs also have been declared as volatile (not that it matters much here) so the compiler will also send out those writes in the order you've written them.