Skip to content

Commit 70d31a9

Browse files
jplexergmarull
authored andcommitted
fw/drivers/sf32lb52/exti: optimize interrupt handling and remove GPIO2 support
Optimize GPIO1_IRQHandler to prevent interrupt storms that were blocking other tasks (e.g. I2C). The handler now only checks pending interrupts across GPIO1's 3 banks (78 pins) using ISR & IER masking and __builtin_ctz for efficient bit scanning, instead of iterating through all pins. Move NVIC configuration from exti_enable() to exti_configure_pin() so the interrupt controller is configured once during setup rather than on every enable call. Fix register write operations for IESR/IECR (interrupt enable set/clear registers) by using direct assignment instead of read-modify-write, as these are write-only registers. Add ISR clearing in exti_disable() to prevent stale interrupts from firing after a line is disabled. Remove all GPIO2 support as it is unused - this simplifies the driver and removes conditional logic from prv_gpio_get_instance(), prv_insert_handler(), prv_delete_handler(), exti_enable(), exti_disable(), and removes the GPIO2_IRQHandler entirely. Signed-off-by: Joshua Jun <[email protected]>
1 parent c19eed0 commit 70d31a9

File tree

1 file changed

+37
-36
lines changed

1 file changed

+37
-36
lines changed

src/fw/drivers/sf32lb52/exti.c

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,22 @@
1212
#include "system/passert.h"
1313

1414
#define EXTI_MAX_GPIO1_PIN_NUM 16
15-
#define EXTI_MAX_GPIO2_PIN_NUM 1
1615

1716
typedef struct {
1817
uint32_t gpio_pin;
1918
ExtiHandlerCallback callback;
2019
} ExtiHandlerConfig_t;
2120

2221
static ExtiHandlerConfig_t s_exti_gpio1_handler_configs[EXTI_MAX_GPIO1_PIN_NUM];
23-
static ExtiHandlerConfig_t s_exti_gpio2_handler_configs[EXTI_MAX_GPIO2_PIN_NUM];
2422

2523
static GPIO_TypeDef *prv_gpio_get_instance(GPIO_TypeDef *hgpio, uint16_t gpio_pin,
2624
uint16_t *offset) {
27-
uint16_t max_num;
2825
uint16_t inst_idx;
2926
GPIO_TypeDef *gpiox;
3027

31-
if ((GPIO_TypeDef *)hwp_gpio1 == hgpio) {
32-
max_num = GPIO1_PIN_NUM;
33-
} else {
34-
max_num = GPIO2_PIN_NUM;
35-
}
36-
37-
HAL_ASSERT(gpio_pin < max_num);
28+
HAL_ASSERT(gpio_pin < GPIO1_PIN_NUM);
3829

39-
if (gpio_pin >= max_num) {
30+
if (gpio_pin >= GPIO1_PIN_NUM) {
4031
return (GPIO_TypeDef *)NULL;
4132
}
4233

@@ -52,11 +43,11 @@ static GPIO_TypeDef *prv_gpio_get_instance(GPIO_TypeDef *hgpio, uint16_t gpio_pi
5243
static void prv_insert_handler(GPIO_TypeDef *hgpio, uint8_t gpio_pin, ExtiHandlerCallback cb) {
5344
// Find the handler index for this pin
5445
uint8_t index = 0;
55-
while (index < (hgpio == hwp_gpio1 ? EXTI_MAX_GPIO1_PIN_NUM : EXTI_MAX_GPIO2_PIN_NUM) &&
46+
while (index < EXTI_MAX_GPIO1_PIN_NUM &&
5647
s_exti_gpio1_handler_configs[index].callback != NULL) {
5748
index++;
5849
}
59-
if (index >= (hgpio == hwp_gpio1 ? EXTI_MAX_GPIO1_PIN_NUM : EXTI_MAX_GPIO2_PIN_NUM)) {
50+
if (index >= EXTI_MAX_GPIO1_PIN_NUM) {
6051
// No available slot
6152
return;
6253
}
@@ -68,12 +59,12 @@ static void prv_insert_handler(GPIO_TypeDef *hgpio, uint8_t gpio_pin, ExtiHandle
6859
static void prv_delete_handler(GPIO_TypeDef *hgpio, uint8_t gpio_pin) {
6960
// Find the handler index for this pin
7061
uint8_t index = 0;
71-
while (index < (hgpio == hwp_gpio1 ? EXTI_MAX_GPIO1_PIN_NUM : EXTI_MAX_GPIO2_PIN_NUM) &&
62+
while (index < EXTI_MAX_GPIO1_PIN_NUM &&
7263
s_exti_gpio1_handler_configs[index].callback != NULL &&
7364
s_exti_gpio1_handler_configs[index].gpio_pin != gpio_pin) {
7465
index++;
7566
}
76-
if (index >= (hgpio == hwp_gpio1 ? EXTI_MAX_GPIO1_PIN_NUM : EXTI_MAX_GPIO2_PIN_NUM)) {
67+
if (index >= EXTI_MAX_GPIO1_PIN_NUM) {
7768
// Handler not found
7869
return;
7970
}
@@ -105,31 +96,26 @@ void exti_configure_pin(ExtiConfig cfg, ExtiTrigger trigger, ExtiHandlerCallback
10596
gpiox->IPLSR = (1UL << offset);
10697
break;
10798
}
99+
100+
// Configure NVIC once during pin setup
101+
HAL_NVIC_SetPriority(GPIO1_IRQn, 6, 0);
102+
HAL_NVIC_EnableIRQ(GPIO1_IRQn);
108103
}
109104

110105
void exti_enable(ExtiConfig cfg) {
111106
uint16_t offset;
112107
GPIO_TypeDef *gpiox = prv_gpio_get_instance(cfg.peripheral, cfg.gpio_pin, &offset);
113-
if (cfg.peripheral == hwp_gpio1) {
114-
// Enable the EXTI line for GPIO1
115-
gpiox->IESR |= (1 << offset);
116-
} else {
117-
gpiox->IESR_EXT |= (1 << offset);
118-
}
119-
120-
HAL_NVIC_SetPriority(GPIO1_IRQn, 6, 0);
121-
HAL_NVIC_EnableIRQ(GPIO1_IRQn);
108+
// Enable the EXTI line for GPIO1
109+
gpiox->IESR = (1 << offset);
110+
// Note: NVIC is configured once in exti_configure_pin, no need to set it here
122111
}
123112

124113
void exti_disable(ExtiConfig cfg) {
125114
uint16_t offset;
126115
GPIO_TypeDef *gpiox = prv_gpio_get_instance(cfg.peripheral, cfg.gpio_pin, &offset);
127-
if (cfg.peripheral == hwp_gpio1) {
128-
// Disable the EXTI line for GPIO1
129-
gpiox->IECR |= (1 << offset);
130-
} else {
131-
gpiox->IECR_EXT |= (1 << offset);
132-
}
116+
// Disable the EXTI line for GPIO1
117+
gpiox->IECR = (1 << offset);
118+
gpiox->ISR = (1 << offset);
133119
}
134120

135121
void HAL_GPIO_EXTI_Callback(GPIO_TypeDef *hgpio, uint16_t GPIO_Pin) {
@@ -154,12 +140,27 @@ void HAL_GPIO_EXTI_Callback(GPIO_TypeDef *hgpio, uint16_t GPIO_Pin) {
154140
}
155141
}
156142

157-
void GPIO1_IRQHandler(void) { HAL_GPIO_IRQHandler(hwp_gpio1); }
158-
159-
void GPIO2_IRQHandler(
160-
void) // Define the interrupt siervice routine (ISR) according to the interrupt vector table
161-
{
162-
HAL_GPIO_IRQHandler(hwp_gpio2);
143+
void GPIO1_IRQHandler(void) {
144+
// Optimized interrupt handler to avoid looping through all 78 pins
145+
// which causes an interrupt storm and blocks other tasks (e.g. I2C).
146+
GPIO_TypeDef *base = hwp_gpio1;
147+
// GPIO1 has pins 0-78, spanning 3 banks (32 pins each)
148+
for (int i = 0; i < 3; i++) {
149+
GPIO_TypeDef *gpiox = base + i;
150+
uint32_t isr = gpiox->ISR;
151+
uint32_t ier = gpiox->IER;
152+
uint32_t pending = isr & ier;
153+
154+
while (pending) {
155+
uint32_t bit = __builtin_ctz(pending);
156+
uint32_t pin = (i * 32) + bit;
157+
158+
// Always call the HAL handler which will clear ISR and invoke callback
159+
HAL_GPIO_EXTI_IRQHandler(hwp_gpio1, pin);
160+
161+
pending &= ~(1UL << bit);
162+
}
163+
}
163164
}
164165

165166
void exti_configure_other(ExtiLineOther exti_line, ExtiTrigger trigger) {}

0 commit comments

Comments
 (0)