7 #if !defined(SITL_BUILD)
9 #include "build/assert.h"
11 #include "drivers/exti.h"
12 #include "drivers/io_impl.h"
13 #include "drivers/nvic.h"
16 extiCallbackRec_t
* handler
;
19 extiChannelRec_t extiChannelRecs
[16];
21 // IRQ gouping, same on 103 and 303
22 #define EXTI_IRQ_GROUPS 7
23 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
24 static const uint8_t extiGroups
[16] = { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 };
25 static uint8_t extiGroupPriority
[EXTI_IRQ_GROUPS
];
27 #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
28 static const uint8_t extiGroupIRQn
[EXTI_IRQ_GROUPS
] = {
37 #elif defined(AT32F43x)
38 static const uint8_t extiGroupIRQn
[EXTI_IRQ_GROUPS
] = {
48 # warning "Unknown CPU"
51 // Absorb the difference in IMR and PR assignments to registers
53 #define EXTI_REG_IMR (EXTI_D1->IMR1)
54 #define EXTI_REG_PR (EXTI_D1->PR1)
55 #elif defined(AT32F43x)
56 // Interrupt enable register & interrupt status register
57 #define EXTI_REG_IMR (EXINT->inten)
58 #define EXTI_REG_PR (EXINT->intsts)
60 #define EXTI_REG_IMR (EXTI->IMR)
61 #define EXTI_REG_PR (EXTI->PR)
68 /* Enable SYSCFG clock otherwise the EXTI irq handlers are not called */
69 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG
, ENABLE
);
70 #elif defined(AT32F43x)
71 crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK
, TRUE
);
73 memset(extiChannelRecs
, 0, sizeof(extiChannelRecs
));
74 memset(extiGroupPriority
, 0xff, sizeof(extiGroupPriority
));
77 void EXTIHandlerInit(extiCallbackRec_t
*self
, extiHandlerCallback
*fn
)
82 #if defined(STM32F7) || defined(STM32H7)
83 void EXTIConfig(IO_t io
, extiCallbackRec_t
*cb
, int irqPriority
, ioConfig_t config
)
87 chIdx
= IO_GPIOPinIdx(io
);
90 extiChannelRec_t
*rec
= &extiChannelRecs
[chIdx
];
91 int group
= extiGroups
[chIdx
];
93 GPIO_InitTypeDef init
= {
95 .Mode
= GPIO_MODE_IT_RISING
,
96 .Speed
= GPIO_SPEED_FREQ_LOW
,
99 HAL_GPIO_Init(IO_GPIO(io
), &init
);
102 //uint32_t extiLine = IO_EXTI_Line(io);
104 //EXTI_ClearITPendingBit(extiLine);
106 if (extiGroupPriority
[group
] > irqPriority
) {
107 extiGroupPriority
[group
] = irqPriority
;
108 HAL_NVIC_SetPriority(extiGroupIRQn
[group
], irqPriority
, 0);
109 HAL_NVIC_EnableIRQ(extiGroupIRQn
[group
]);
112 #elif defined(AT32F43x)
113 void EXTIConfig(IO_t io
, extiCallbackRec_t
*cb
, int irqPriority
, exint_polarity_config_type trigger
)
116 chIdx
= IO_GPIOPinIdx(io
);
119 // we have only 16 extiChannelRecs
121 extiChannelRec_t
*rec
= &extiChannelRecs
[chIdx
];
122 int group
= extiGroups
[chIdx
];
125 scfg_exint_line_config(IO_EXTI_PortSourceGPIO(io
), IO_EXTI_PinSource(io
));
126 uint32_t extiLine
= IO_EXTI_Line(io
);
127 exint_flag_clear(extiLine
);
129 exint_init_type EXTIInit
;
130 exint_default_para_init(&EXTIInit
);
131 EXTIInit
.line_mode
= EXINT_LINE_INTERRUPUT
;
132 EXTIInit
.line_select
= extiLine
;
133 EXTIInit
.line_polarity
= trigger
;
134 EXTIInit
.line_enable
= TRUE
;
135 exint_init(&EXTIInit
);
137 if (extiGroupPriority
[group
] > irqPriority
) {
138 extiGroupPriority
[group
] = irqPriority
;
139 nvic_priority_group_config(NVIC_PRIORITY_GROUPING
);
140 nvic_irq_enable(extiGroupIRQn
[group
],irqPriority
,0);
144 void EXTIConfig(IO_t io
, extiCallbackRec_t
*cb
, int irqPriority
, EXTITrigger_TypeDef trigger
)
147 chIdx
= IO_GPIOPinIdx(io
);
151 // we have only 16 extiChannelRecs
154 extiChannelRec_t
*rec
= &extiChannelRecs
[chIdx
];
155 int group
= extiGroups
[chIdx
];
159 SYSCFG_EXTILineConfig(IO_EXTI_PortSourceGPIO(io
), IO_EXTI_PinSource(io
));
161 # warning "Unknown CPU"
163 uint32_t extiLine
= IO_EXTI_Line(io
);
165 EXTI_ClearITPendingBit(extiLine
);
167 EXTI_InitTypeDef EXTIInit
;
168 EXTIInit
.EXTI_Line
= extiLine
;
169 EXTIInit
.EXTI_Mode
= EXTI_Mode_Interrupt
;
170 EXTIInit
.EXTI_Trigger
= trigger
;
171 EXTIInit
.EXTI_LineCmd
= ENABLE
;
172 EXTI_Init(&EXTIInit
);
174 if (extiGroupPriority
[group
] > irqPriority
) {
175 extiGroupPriority
[group
] = irqPriority
;
177 NVIC_SetPriority(extiGroupIRQn
[group
], irqPriority
);
178 NVIC_EnableIRQ(extiGroupIRQn
[group
]);
183 void EXTIRelease(IO_t io
)
185 // don't forget to match cleanup with config
186 EXTIEnable(io
, false);
189 chIdx
= IO_GPIOPinIdx(io
);
193 // we have only 16 extiChannelRecs
196 extiChannelRec_t
*rec
= &extiChannelRecs
[chIdx
];
200 void EXTIEnable(IO_t io
, bool enable
)
202 #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)|| defined(AT32F43x)
203 uint32_t extiLine
= IO_EXTI_Line(io
);
207 EXTI_REG_IMR
|= extiLine
;
209 EXTI_REG_IMR
&= ~extiLine
;
211 # error "Unsupported target"
215 void EXTI_IRQHandler(void)
217 uint32_t exti_active
= EXTI_REG_IMR
& EXTI_REG_PR
;
219 while (exti_active
) {
220 unsigned idx
= 31 - __builtin_clz(exti_active
);
221 uint32_t mask
= 1 << idx
;
222 extiChannelRecs
[idx
].handler
->fn(extiChannelRecs
[idx
].handler
);
223 EXTI_REG_PR
= mask
; // clear pending mask (by writing 1)
224 exti_active
&= ~mask
;
228 #define _EXTI_IRQ_HANDLER(name) \
236 #if defined(AT32F43x)
237 _EXTI_IRQ_HANDLER(EXINT0_IRQHandler
);
238 _EXTI_IRQ_HANDLER(EXINT1_IRQHandler
);
239 _EXTI_IRQ_HANDLER(EXINT2_IRQHandler
);
240 _EXTI_IRQ_HANDLER(EXINT3_IRQHandler
);
241 _EXTI_IRQ_HANDLER(EXINT4_IRQHandler
);
242 _EXTI_IRQ_HANDLER(EXINT9_5_IRQHandler
);
243 _EXTI_IRQ_HANDLER(EXINT15_10_IRQHandler
);
245 _EXTI_IRQ_HANDLER(EXTI0_IRQHandler
);
246 _EXTI_IRQ_HANDLER(EXTI1_IRQHandler
);
247 #if defined(STM32F7) || defined(STM32H7)
248 _EXTI_IRQ_HANDLER(EXTI2_IRQHandler
);
249 #elif defined(STM32F4) || defined(AT32F43x)
250 _EXTI_IRQ_HANDLER(EXTI2_TS_IRQHandler
);
252 # warning "Unknown CPU"
254 _EXTI_IRQ_HANDLER(EXTI3_IRQHandler
);
255 _EXTI_IRQ_HANDLER(EXTI4_IRQHandler
);
256 _EXTI_IRQ_HANDLER(EXTI9_5_IRQHandler
);
257 _EXTI_IRQ_HANDLER(EXTI15_10_IRQHandler
);