4141#define EXTI_MASK (0xFFFF)
4242
4343#if defined(EXTI_SWIER_SWI0 ) || defined(EXTI_SWIER_SWIER0 )
44- #define EXTI_REG_SWIER (EXTI->SWIER)
44+ # define EXTI_REG_SWIER (EXTI->SWIER)
4545#endif
4646
4747#if defined(EXTI_SWIER1_SWI0 ) || defined(EXTI_SWIER1_SWIER0 )
48- #define EXTI_REG_SWIER (EXTI->SWIER1)
48+ # define EXTI_REG_SWIER (EXTI->SWIER1)
4949#endif
5050
5151#if defined(EXTI_RTSR_RT0 ) || defined(EXTI_RTSR_TR0 )
52- #define EXTI_REG_RTSR (EXTI->RTSR)
52+ # define EXTI_REG_RTSR (EXTI->RTSR)
5353#endif
5454
5555#if defined(EXTI_RTSR1_RT0 ) || defined(EXTI_RTSR1_TR0 )
56- #define EXTI_REG_RTSR (EXTI->RTSR1)
56+ # define EXTI_REG_RTSR (EXTI->RTSR1)
5757#endif
5858
5959#if defined(EXTI_FTSR_FT0 ) || defined(EXTI_FTSR_TR0 )
60- #define EXTI_REG_FTSR (EXTI->FTSR)
60+ # define EXTI_REG_FTSR (EXTI->FTSR)
6161#endif
6262
6363#if defined(EXTI_FTSR1_FT0 ) || defined (EXTI_FTSR1_TR0 )
64- #define EXTI_REG_FTSR (EXTI->FTSR1)
64+ # define EXTI_REG_FTSR (EXTI->FTSR1)
6565#endif
6666
67- #ifdef EXTI_PR_PR0
68- #define EXTI_REG_PR (EXTI->PR)
69- #endif
70-
71- #ifdef EXTI_PR1_PIF0
72- #define EXTI_REG_PR (EXTI->PR1)
67+ #if defined(EXTI_PR_PR0 )
68+ # define EXTI_REG_PR (EXTI->PR)
69+ #elif defined(EXTI_PR1_PIF0 )
70+ # define EXTI_REG_PR (EXTI->PR1)
71+ #else
72+ # define EXTI_REG_FPR (EXTI->FPR1)
73+ # define EXTI_REG_RPR (EXTI->RPR1)
7374#endif
7475
7576#if defined(EXTI_C2_BASE )
76- # define EXTI_REG_IMR (EXTI_C2->IMR1)
77+ # define EXTI_REG_IMR (EXTI_C2->IMR1)
7778#elif defined(EXTI_IMR_IM0 )
78- # define EXTI_REG_IMR (EXTI->IMR)
79+ # define EXTI_REG_IMR (EXTI->IMR)
7980#elif defined(EXTI_IMR1_IM0 )
80- # define EXTI_REG_IMR (EXTI->IMR1)
81+ # define EXTI_REG_IMR (EXTI->IMR1)
82+ #endif
83+
84+ #ifdef RCC_APB2ENR_SYSCFGCOMPEN
85+ # define SYSFG_CLOCK APB2
86+ # define SYSFG_ENABLE_MASK RCC_APB2ENR_SYSCFGCOMPEN
87+ #endif
88+
89+ #ifdef RCC_APBENR2_SYSCFGEN
90+ # define SYSFG_ENABLE_MASK RCC_APBENR2_SYSCFGEN
91+ # ifdef APB12
92+ # define SYSFG_CLOCK APB12
93+ # else
94+ # define SYSFG_CLOCK APB2
95+ # endif
96+ #endif
97+
98+ #ifdef RCC_APB3ENR_SYSCFGEN
99+ # define SYSFG_CLOCK APB3
100+ # define SYSFG_ENABLE_MASK RCC_APB3ENR_SYSCFGEN
101+ #endif
102+
103+ #ifdef EXTI_EXTICR1_EXTI0
104+ # define EXTICR_REG (num ) (EXTI->EXTICR[(num) >> 2])
105+ #endif
106+
107+ #ifdef SYSCFG_EXTICR1_EXTI0
108+ # define EXTICR_REG (num ) (SYSCFG->EXTICR[(num) >> 2])
109+ #endif
110+
111+ #ifdef AFIO_EXTICR1_EXTI0
112+ # define EXTICR_REG (num ) (AFIO->EXTICR[(num) >> 2])
113+ #endif
114+
115+ #ifdef SYSCFG_EXTICR1_EXTI1_Pos
116+ # define EXTICR_FIELD_SIZE SYSCFG_EXTICR1_EXTI1_Pos
117+ #endif
118+
119+ #ifdef EXTI_EXTICR1_EXTI1_Pos
120+ # define EXTICR_FIELD_SIZE EXTI_EXTICR1_EXTI1_Pos
121+ #endif
122+
123+ #ifdef AFIO_EXTICR1_EXTI1_Pos
124+ # define EXTICR_FIELD_SIZE AFIO_EXTICR1_EXTI1_Pos
81125#endif
82126
83127void gpio_ll_irq_mask (gpio_port_t port , uint8_t pin )
@@ -102,6 +146,8 @@ static uint16_t level_triggered;
102146
103147static IRQn_Type get_irqn (uint8_t pin )
104148{
149+ /* TODO: Come up with a way that this doesn't need updates whenever a new
150+ * MCU family gets added */
105151#if defined(CPU_FAM_STM32L5 ) || defined(CPU_FAM_STM32U5 )
106152 return EXTI0_IRQn + pin ;
107153#elif defined(CPU_FAM_STM32F0 ) || defined(CPU_FAM_STM32L0 ) || \
@@ -155,48 +201,29 @@ static IRQn_Type get_irqn(uint8_t pin)
155201
156202static void clear_pending_irqs (uint8_t pin )
157203{
158- #if defined(CPU_FAM_STM32G0 ) || defined(CPU_FAM_STM32L5 ) || \
159- defined(CPU_FAM_STM32U5 ) || defined(CPU_FAM_STM32MP1 )
160- /* clear any pending requests */
161- EXTI -> RPR1 = (1 << pin );
162- EXTI -> FPR1 = (1 << pin );
204+ #ifdef EXTI_REG_PR
205+ /* same IRQ flag no matter if falling or rising edge detected */
206+ EXTI_REG_PR = (1U << pin );
163207#else
164- /* clear any pending requests */
165- EXTI_REG_PR = (1 << pin );
208+ /* distinct IRQ flags for falling and rising edge, clearing both */
209+ EXTI_REG_FPR = (1U << pin );
210+ EXTI_REG_RPR = (1U << pin );
166211#endif
167212}
168213
169214static void set_exti_port (uint8_t exti_num , uint8_t port_num )
170215{
171- #if defined(CPU_FAM_STM32G0 ) || defined(CPU_FAM_STM32L5 ) || \
172- defined(CPU_FAM_STM32U5 )
173- /* enable specific pin as exti sources */
174- EXTI -> EXTICR [exti_num >> 2 ] &= ~(0xf << ((exti_num & 0x03 ) * 8 ));
175- EXTI -> EXTICR [exti_num >> 2 ] |= (port_num << ((exti_num & 0x03 ) * 8 ));
176- #elif defined(CPU_FAM_STM32MP1 )
177- /* enable specific pin as exti sources */
178- EXTI -> EXTICR [exti_num >> 2 ] &= ~(0xf << ((exti_num & 0x03 ) * 4 ));
179- EXTI -> EXTICR [exti_num >> 2 ] |= (port_num << ((exti_num & 0x03 ) * 4 ));
180- #else
181- /* enable specific pin as exti sources */
182- SYSCFG -> EXTICR [exti_num >> 2 ] &= ~(0xf << ((exti_num & 0x03 ) * 4 ));
183- SYSCFG -> EXTICR [exti_num >> 2 ] |= (port_num << ((exti_num & 0x03 ) * 4 ));
184- #endif
216+ uint32_t tmp = EXTICR_REG (exti_num );
217+ tmp &= ~(0xf << ((exti_num & 0x03 ) * EXTICR_FIELD_SIZE ));
218+ tmp |= (port_num << ((exti_num & 0x03 ) * EXTICR_FIELD_SIZE ));
219+ EXTICR_REG (exti_num ) = tmp ;
185220}
186221
187222static uint8_t get_exti_port (uint8_t exti_num )
188223{
189- #if defined(CPU_FAM_STM32G0 ) || defined(CPU_FAM_STM32L5 ) || \
190- defined(CPU_FAM_STM32U5 )
191- /* enable specific pin as exti sources */
192- return 0xf & (EXTI -> EXTICR [exti_num >> 2 ] >> ((exti_num & 0x03 ) * 8 ));
193- #elif defined(CPU_FAM_STM32MP1 )
194- /* enable specific pin as exti sources */
195- return 0xf & (EXTI -> EXTICR [exti_num >> 2 ] >> ((exti_num & 0x03 ) * 4 ));
196- #else
197- /* enable specific pin as exti sources */
198- return 0xf & (SYSCFG -> EXTICR [exti_num >> 2 ] >> ((exti_num & 0x03 ) * 4 ));
199- #endif
224+ uint32_t reg = EXTICR_REG (exti_num );
225+ reg >>= (exti_num & 0x03 ) * EXTICR_FIELD_SIZE ;
226+ return reg & 0xf ;
200227}
201228
202229int gpio_ll_irq (gpio_port_t port , uint8_t pin , gpio_irq_trig_t trig , gpio_ll_cb_t cb , void * arg )
@@ -209,17 +236,8 @@ int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig, gpio_ll_cb_
209236 isr_ctx [pin ].arg = arg ;
210237
211238 /* enable clock of the SYSCFG module for EXTI configuration */
212- #if !defined(CPU_FAM_STM32WB ) && !defined(CPU_FAM_STM32MP1 ) && \
213- !defined(CPU_FAM_STM32WL )
214- #ifdef CPU_FAM_STM32F0
215- periph_clk_en (APB2 , RCC_APB2ENR_SYSCFGCOMPEN );
216- #elif defined(CPU_FAM_STM32G0 )
217- periph_clk_en (APB12 , RCC_APBENR2_SYSCFGEN );
218- #elif defined(CPU_FAM_STM32U5 )
219- periph_clk_en (APB3 , RCC_APB3ENR_SYSCFGEN );
220- #else
221- periph_clk_en (APB2 , RCC_APB2ENR_SYSCFGEN );
222- #endif
239+ #ifdef SYSFG_CLOCK
240+ periph_clk_en (SYSFG_CLOCK , SYSFG_ENABLE_MASK );
223241#endif
224242
225243 /* enable global pin interrupt */
@@ -262,30 +280,35 @@ int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig, gpio_ll_cb_
262280 return 0 ;
263281}
264282
265- void isr_exti (void )
283+ static uint32_t get_and_clear_pending_irqs (void )
266284{
267- #if defined(CPU_FAM_STM32G0 ) || defined(CPU_FAM_STM32L5 ) || \
268- defined(CPU_FAM_STM32U5 ) || defined(CPU_FAM_STM32MP1 )
269- /* get all interrupts handled by this ISR */
270- uint32_t pending_rising_isr = (EXTI -> RPR1 & EXTI_MASK );
271- uint32_t pending_falling_isr = (EXTI -> FPR1 & EXTI_MASK );
285+ #ifdef EXTI_REG_PR
286+ /* only one pending IRQ flag register for both falling and rising flanks */
287+ uint32_t pending_isr = (EXTI_REG_PR & EXTI_MASK );
288+
289+ /* clear by writing a 1 */
290+ EXTI_REG_PR = pending_isr ;
291+ return pending_isr ;
292+ #else
293+ /* distinct registers for pending IRQ flags depending on rising or falling
294+ * flank */
295+ uint32_t pending_rising_isr = (EXTI_REG_RPR & EXTI_MASK );
296+ uint32_t pending_falling_isr = (EXTI_REG_FPR & EXTI_MASK );
272297
273298 /* clear by writing a 1 */
274299 EXTI -> RPR1 = pending_rising_isr ;
275300 EXTI -> FPR1 = pending_falling_isr ;
276301
277- /* only generate interrupts against lines which have their IMR set */
278- uint32_t pending_isr = (pending_rising_isr | pending_falling_isr ) & EXTI_REG_IMR ;
279- #else
280- /* read all pending interrupts wired to isr_exti */
281- uint32_t pending_isr = (EXTI_REG_PR & EXTI_MASK );
302+ return pending_rising_isr | pending_falling_isr ;
303+ #endif
304+ }
282305
283- /* clear by writing a 1 */
284- EXTI_REG_PR = pending_isr ;
306+ void isr_exti (void )
307+ {
308+ uint32_t pending_isr = get_and_clear_pending_irqs ();
285309
286310 /* only generate soft interrupts against lines which have their IMR set */
287311 pending_isr &= EXTI_REG_IMR ;
288- #endif
289312
290313 /* iterate over all set bits */
291314 uint8_t pin = 0 ;
0 commit comments