I need to toggle a GPIO pin as fast as I can.
Using gpio_set_level() is just to slow. I ran across the following, and wanted to try it but the GPIO pin I want to use is 46.
How do yo do the following on the S3 higher than 31 ?
//This can only be used when the IO_PIN_Number is 0-31
//Use GPIO.out_w1ts = ((uint32_t)1 << IO_PIN_Number); to set the pin high
//Use GPIO.out_w1ts = ((uint32_t)1 << IO_PIN_Number); to set the pin low
ESP32-S3 Fast GPIO using GPIO.out_w1ts
Re: ESP32-S3 Fast GPIO using GPIO.out_w1ts
I think you need something like
GPIO.out1_w1ts = (1U << (pin - 32));
("out" contains the lower 32 pins, "out1" contains the pins starting from 32)
GPIO.out1_w1ts = (1U << (pin - 32));
("out" contains the lower 32 pins, "out1" contains the pins starting from 32)
Re: ESP32-S3 Fast GPIO using GPIO.out_w1ts
Close, its actually GPIO.out1_w1ts.val , there is no GPIO.out1_w1ts
Just wanted to add clarity for others that may need to twiddle pins faster.
The code below credit comes from this page here.
https://gitlab.cba.mit.edu/erik/strands ... ect_gpio.h
Just wanted to add clarity for others that may need to twiddle pins faster.
The code below credit comes from this page here.
https://gitlab.cba.mit.edu/erik/strands ... ect_gpio.h
Code: Select all
static inline __attribute__((always_inline))
void directWriteLow(IO_REG_TYPE pin)
{
if ( pin < 32 )
GPIO.out_w1tc = ((uint32_t)1 << pin);
else if ( pin < 34 )
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
}
static inline __attribute__((always_inline))
void directWriteHigh(IO_REG_TYPE pin)
{
if ( pin < 32 )
GPIO.out_w1ts = ((uint32_t)1 << pin);
else if ( pin < 34 )
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
}
Re: ESP32-S3 Fast GPIO using GPIO.out_w1ts
Hey I was running into the same issue recently with the S3 but found dedicated IO bundles and the following assembly inlines to be the fastest:
To use it, you first have to create a dedicated GPIO bundle as described here:
https://docs.espressif.com/projects/esp ... _gpio.html
The dedic_io_num param must be a mask of the pins in the bundle, IE, if your bundle has pins {15,12,14} and you want to write to pin 12 then dedic_io_num should be 0x2 or for pin 14 dedic_io_num should be 0x4 (1 << index_of_pin_in_bundle).
You can also decrease the nops if needed, but I haven't gotten it to work with any less than 2 so far.
Code: Select all
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) : );
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
}
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) : );
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
}
https://docs.espressif.com/projects/esp ... _gpio.html
The dedic_io_num param must be a mask of the pins in the bundle, IE, if your bundle has pins {15,12,14} and you want to write to pin 12 then dedic_io_num should be 0x2 or for pin 14 dedic_io_num should be 0x4 (1 << index_of_pin_in_bundle).
You can also decrease the nops if needed, but I haven't gotten it to work with any less than 2 so far.
Re: ESP32-S3 Fast GPIO using GPIO.out_w1ts
Thanks for the info!
Re: ESP32-S3 Fast GPIO using GPIO.out_w1ts
I have also gone down the Dedicated GPIO path using Bundles and was able to collect some data.
The API takes 420ns to change an IO pin, whereas using a Dedicated GPIO and assembly code it only takes 12ns. That's 35 times faster. 12ns corresponds to 80mhz and it is possible to create an 80mhz square wave.
I did not find the nops to be necessary but others may know something I don't. Each nop adds another 12ns.
I had previously been using IO Mux/GPIO Matrix without Bundle and writing directly to the wts/wtc registers in C and was getting 60ns.
If the nops are added to the Deticated/Bundle technich it will also be 60ns.
Thanks for the info posted above, it was very helpful.
The API takes 420ns to change an IO pin, whereas using a Dedicated GPIO and assembly code it only takes 12ns. That's 35 times faster. 12ns corresponds to 80mhz and it is possible to create an 80mhz square wave.
I did not find the nops to be necessary but others may know something I don't. Each nop adds another 12ns.
I had previously been using IO Mux/GPIO Matrix without Bundle and writing directly to the wts/wtc registers in C and was getting 60ns.
If the nops are added to the Deticated/Bundle technich it will also be 60ns.
Thanks for the info posted above, it was very helpful.
Who is online
Users browsing this forum: axellin, Google [Bot] and 118 guests