Does gpio_set_level() before gpio_set_direction() work?

brianpdx
Posts: 8
Joined: Fri Jan 29, 2021 6:07 am

Does gpio_set_level() before gpio_set_direction() work?

Postby brianpdx » Mon Jul 04, 2022 7:40 pm

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?

User avatar
gtjoseph
Posts: 81
Joined: Fri Oct 15, 2021 10:55 pm

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

Postby gtjoseph » Mon Jul 04, 2022 9:11 pm

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

brianpdx
Posts: 8
Joined: Fri Jan 29, 2021 6:07 am

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

Postby brianpdx » Tue Jul 05, 2022 4:09 am

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...

ESP_Sprite
Posts: 8921
Joined: Thu Nov 26, 2015 4:08 am

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

Postby ESP_Sprite » Tue Jul 05, 2022 6:21 am

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.

Who is online

Users browsing this forum: Google [Bot] and 115 guests