From b9ceac5ccc3515518f751a7c5b5c2c30188fef91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Tue, 6 Nov 2018 14:15:29 +0100 Subject: [PATCH 1/2] kinetis: Optimize GPIO IRQ handler Measurements show that the time from pin edge until return from interrupt is reduced from 22 us to 6.1 us for KW41Z running at 41.94 MHz. The measurements used a no-op GPIO callback for testing and were measured using an external logic analyzer. --- cpu/kinetis/periph/gpio.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cpu/kinetis/periph/gpio.c b/cpu/kinetis/periph/gpio.c index 03256dc553..67a01aeefc 100644 --- a/cpu/kinetis/periph/gpio.c +++ b/cpu/kinetis/periph/gpio.c @@ -28,6 +28,7 @@ #include #include #include "cpu.h" +#include "bitarithm.h" #include "bit.h" #include "periph/gpio.h" @@ -308,11 +309,18 @@ static inline void irq_handler(PORT_Type *port, int port_num) /* take interrupt flags only from pins which interrupt is enabled */ uint32_t status = port->ISFR; - for (int i = 0; i < 32; i++) { - if ((status & (1u << i)) && (port->PCR[i] & PORT_PCR_IRQC_MASK)) { - port->ISFR = (1u << i); - int ctx = get_ctx(port_num, i); - isr_ctx[ctx].cb(isr_ctx[ctx].arg); + while (status) { + /* get position of first bit set in status */ + unsigned pin = bitarithm_lsb(status); + /* clear it */ + status &= ~(1 << pin); + if (port->PCR[pin] & PORT_PCR_IRQC_MASK) { + port->ISFR = (1u << pin); + int ctx = get_ctx(port_num, pin); + gpio_cb_t cb = isr_ctx[ctx].cb; + if (cb) { + cb(isr_ctx[ctx].arg); + } } } cortexm_isr_end(); From 8bb73f237de78c61a7f992c06ffd64e9d02789fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 7 Nov 2018 13:05:50 +0100 Subject: [PATCH 2/2] kinetis: GPIO: avoid dup calls to cortexm_isr_end on KW41Z Devices with combined IRQs would call the cortexm_isr_end handler twice when it is part of the irq_handler routine. --- cpu/kinetis/periph/gpio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cpu/kinetis/periph/gpio.c b/cpu/kinetis/periph/gpio.c index 67a01aeefc..c1ae258a99 100644 --- a/cpu/kinetis/periph/gpio.c +++ b/cpu/kinetis/periph/gpio.c @@ -323,13 +323,13 @@ static inline void irq_handler(PORT_Type *port, int port_num) } } } - cortexm_isr_end(); } #ifdef PORTA_BASE void isr_porta(void) { irq_handler(PORTA, 0); + cortexm_isr_end(); } #endif /* PORTA_BASE */ @@ -337,6 +337,7 @@ void isr_porta(void) void isr_portb(void) { irq_handler(PORTB, 1); + cortexm_isr_end(); } #endif /* ISR_PORT_B */ @@ -344,6 +345,7 @@ void isr_portb(void) void isr_portc(void) { irq_handler(PORTC, 2); + cortexm_isr_end(); } #endif /* ISR_PORT_C */ @@ -351,6 +353,7 @@ void isr_portc(void) void isr_portd(void) { irq_handler(PORTD, 3); + cortexm_isr_end(); } #endif /* ISR_PORT_D */ @@ -358,6 +361,7 @@ void isr_portd(void) void isr_porte(void) { irq_handler(PORTE, 4); + cortexm_isr_end(); } #endif /* ISR_PORT_E */ @@ -365,6 +369,7 @@ void isr_porte(void) void isr_portf(void) { irq_handler(PORTF, 5); + cortexm_isr_end(); } #endif /* ISR_PORT_F */ @@ -372,6 +377,7 @@ void isr_portf(void) void isr_portg(void) { irq_handler(PORTG, 6); + cortexm_isr_end(); } #endif /* ISR_PORT_G */ @@ -381,6 +387,7 @@ void isr_portb_portc(void) { irq_handler(PORTB, 1); irq_handler(PORTC, 2); + cortexm_isr_end(); } #endif #endif /* MODULE_PERIPH_GPIO_IRQ */