How do GPIO interrupts work on STM32, and what are the limitations of the EXTI system?
On STM32, external interrupts are managed by the EXTI (External Interrupt/Event Controller). Each of the 16 EXTI lines (EXTI0 through EXTI15) corresponds to a pin number — EXTI0 handles pin 0 from any port, EXTI1 handles pin 1, and so on. A SYSCFG multiplexer selects which GPIO port (A, B, C, etc.) is connected to each EXTI line. Each line can be configured to trigger on a rising edge, falling edge, or both. When the configured edge is detected, a pending flag is set and, if the corresponding interrupt mask bit is enabled, an interrupt request is generated.
The critical limitation is that only one port can be mapped to each EXTI line number at a time. PA0 and PB0 both map to EXTI0, so you cannot use both as interrupt sources simultaneously. This constraint applies across all ports — if you select PA0 for EXTI0, then PB0, PC0, PD0 are all excluded. This means a maximum of 16 external interrupts total, one per pin number. Hardware designers must account for this during schematic design by placing critical interrupt signals on pin numbers that do not conflict.
A second limitation is interrupt vector sharing. On most STM32 families, EXTI lines 5 through 9 share a single NVIC vector (EXTI9_5_IRQHandler), and lines 10 through 15 share another (EXTI15_10_IRQHandler). Inside these shared ISRs, firmware must check the EXTI pending register (PR) to determine which specific line triggered, then clear the correct pending bit. Lines 0 through 4 each have dedicated vectors. This sharing adds a small overhead but is rarely a practical problem — just remember to check and clear the flags correctly, or you will miss interrupts or create infinite ISR re-entry.
Source: GPIO Q&A
