-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
I'm trying to quickly react to a GPIO change on a RP2040.
The GPIO interrupt is setup as follow:
gpio_set_irq_enabled(FPL_I_FAULT_IN, GPIO_IRQ_EDGE_FALL, true);
gpio_add_raw_irq_handler(FPL_I_FAULT_IN, &gpio_isr);
irq_set_enabled(IO_IRQ_BANK0, true); // Enable the IO IRQ for GPIO
The content of the ISR:
void __not_in_flash_func(gpio_isr)(void) {
if (gpio_get_irq_event_mask(FPL_I_FAULT_IN) & GPIO_IRQ_EDGE_FALL) {
gpio_acknowledge_irq(FPL_I_FAULT_IN, GPIO_IRQ_EDGE_FALL);
gpio_put(CPU_D_DISABLE_OUT, 1);
}
}
Calling gpio_acknowledge_irq() before setting the pin to 1 causes a latency of 2.4us:
The obvious solution is to call it after.
Calling gpio_acknowledge_irq() after setting the pin to 1 causes a latency of only 525ns:
I was looking at the code to understand why clearing a bit was taking so long whe it struck me: the Flash!
I changed the definition of gpio_acknowledge_irq() to run from RAM as follows:
void __not_in_flash_func(gpio_acknowledge_irq)(uint gpio, uint32_t events) {
check_gpio_param(gpio);
io_bank0_hw->intr[gpio / 8] = events << (4 * (gpio % 8));
}
And this is the result I got: 637ns:
I know this will up for debate, but should this function that is almost-exclusively called from ISR, be run from RAM anyway?
Or what should the fix be in my case? (even calling gpio_acknowledge_irq() after setting the bit causes an unnecessary delay before the ISR returns).
RFC 😄