From 6540609c35bd58fa80d64ba782f31d1ad44eb042 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Mon, 9 Mar 2020 18:34:06 +0100 Subject: [PATCH 1/2] cpu/sam0_common: gpio: save a few cycles in isr_eic() Don't iterate over all bits in the GPIO status register, instead just loop as many times as there are set bits. --- cpu/sam0_common/periph/gpio.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cpu/sam0_common/periph/gpio.c b/cpu/sam0_common/periph/gpio.c index e721d75a72..f8c7c5e49b 100644 --- a/cpu/sam0_common/periph/gpio.c +++ b/cpu/sam0_common/periph/gpio.c @@ -322,12 +322,18 @@ void gpio_irq_disable(gpio_t pin) void isr_eic(void) { - for (unsigned i = 0; i < NUMOF_IRQS; i++) { - if (_EIC->INTFLAG.reg & (1 << i)) { - _EIC->INTFLAG.reg = (1 << i); - gpio_config[i].cb(gpio_config[i].arg); - } + /* read & clear interrupt flags */ + uint32_t state = _EIC->INTFLAG.reg; + state &= (1 << NUMOF_IRQS) - 1; + _EIC->INTFLAG.reg = state; + + /* execute interrupt callbacks */ + while (state) { + unsigned pin = 8 * sizeof(state) - __builtin_clz(state) - 1; + state &= ~(1 << pin); + gpio_config[pin].cb(gpio_config[pin].arg); } + cortexm_isr_end(); } From eb3f515f5505c9ee7b9e789aec2e9784d7554e94 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Mon, 9 Mar 2020 18:35:29 +0100 Subject: [PATCH 2/2] cpu/sam0_common: gpio: Make use of dedicated GPIO interrupts saml1x and samd5x have dedicated interrupts per GPIO line. Use those instead of iterating over the GPIO status bits to serve IRQs even faster. --- cpu/sam0_common/periph/gpio.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/cpu/sam0_common/periph/gpio.c b/cpu/sam0_common/periph/gpio.c index f8c7c5e49b..42af450f2c 100644 --- a/cpu/sam0_common/periph/gpio.c +++ b/cpu/sam0_common/periph/gpio.c @@ -320,7 +320,11 @@ void gpio_irq_disable(gpio_t pin) _EIC->INTENCLR.reg = (1 << exti); } +#if defined(CPU_SAML1X) +void isr_eic_other(void) +#else void isr_eic(void) +#endif { /* read & clear interrupt flags */ uint32_t state = _EIC->INTFLAG.reg; @@ -342,7 +346,9 @@ void isr_eic(void) #define ISR_EICn(n) \ void isr_eic ## n (void) \ { \ - isr_eic(); \ + _EIC->INTFLAG.reg = 1 << n; \ + gpio_config[n].cb(gpio_config[n].arg); \ + cortexm_isr_end(); \ } ISR_EICn(0) @@ -354,6 +360,7 @@ ISR_EICn(4) ISR_EICn(5) ISR_EICn(6) ISR_EICn(7) +#if (NUMOF_IRQS > 8) ISR_EICn(8) ISR_EICn(9) ISR_EICn(10) @@ -362,9 +369,8 @@ ISR_EICn(12) ISR_EICn(13) ISR_EICn(14) ISR_EICn(15) -#else -ISR_EICn(_other) -#endif /* CPU_SAML1X */ +#endif /* NUMOF_IRQS > 8 */ +#endif /* CPU_SAMD5X */ #endif /* CPU_SAML1X || CPU_SAMD5X */ #else /* MODULE_PERIPH_GPIO_IRQ */