Skip to content

Commit 03dfa49

Browse files
committed
cpu/stm32: Implement GPIO LL IRQ support for STM32F1
1 parent 9719bbf commit 03dfa49

File tree

3 files changed

+101
-78
lines changed

3 files changed

+101
-78
lines changed

cpu/stm32/Makefile.features

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@ FEATURES_PROVIDED += periph_rtt_overflow
1212
FEATURES_PROVIDED += periph_uart_modecfg
1313
FEATURES_PROVIDED += periph_uart_nonblocking
1414
FEATURES_PROVIDED += periph_gpio_ll
15-
16-
ifneq ($(CPU_FAM),f1)
17-
FEATURES_PROVIDED += periph_gpio_ll_irq
18-
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high
19-
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low
20-
endif
15+
FEATURES_PROVIDED += periph_gpio_ll_irq
16+
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high
17+
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low
2118

2219
ifneq (,$(filter $(CPU_FAM),f0 f1 f3 g0 g4 l0 l1 l4 l5 u5 wb wl))
2320
FEATURES_PROVIDED += periph_flashpage

cpu/stm32/kconfigs/f1/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ config CPU_FAM_F1
1717
select HAS_PERIPH_FLASHPAGE_PAGEWISE
1818
select HAS_PERIPH_FLASHPAGE_RAW
1919
select HAS_PERIPH_GPIO_LL
20+
select HAS_PERIPH_GPIO_LL_IRQ
21+
select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_HIGH
22+
select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_LOW
2023
select HAS_PERIPH_RTT_SET_COUNTER
2124
select HAS_PERIPH_WDT
2225
select HAVE_SHARED_PERIPH_RTT_PERIPH_RTC

cpu/stm32/periph/gpio_ll_irq.c

Lines changed: 95 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -41,43 +41,87 @@
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

83127
void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin)
@@ -102,6 +146,8 @@ static uint16_t level_triggered;
102146

103147
static 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

156202
static 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

169214
static 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

187222
static 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

202229
int 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

Comments
 (0)