Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / exti.c
blob60105de90f10a4fb30d0adc6820b723ad82cdd94
1 #include <stdbool.h>
2 #include <stdint.h>
3 #include <string.h>
5 #include "platform.h"
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"
15 typedef struct {
16 extiCallbackRec_t* handler;
17 } extiChannelRec_t;
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] = {
29 EXTI0_IRQn,
30 EXTI1_IRQn,
31 EXTI2_IRQn,
32 EXTI3_IRQn,
33 EXTI4_IRQn,
34 EXTI9_5_IRQn,
35 EXTI15_10_IRQn
37 #elif defined(AT32F43x)
38 static const uint8_t extiGroupIRQn[EXTI_IRQ_GROUPS] = {
39 EXINT0_IRQn,
40 EXINT1_IRQn,
41 EXINT2_IRQn,
42 EXINT3_IRQn,
43 EXINT4_IRQn,
44 EXINT9_5_IRQn,
45 EXINT15_10_IRQn
47 #else
48 # warning "Unknown CPU"
49 #endif
51 // Absorb the difference in IMR and PR assignments to registers
52 #if defined(STM32H7)
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)
59 #else
60 #define EXTI_REG_IMR (EXTI->IMR)
61 #define EXTI_REG_PR (EXTI->PR)
62 #endif
65 void EXTIInit(void)
67 #if defined(STM32F4)
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);
72 #endif
73 memset(extiChannelRecs, 0, sizeof(extiChannelRecs));
74 memset(extiGroupPriority, 0xff, sizeof(extiGroupPriority));
77 void EXTIHandlerInit(extiCallbackRec_t *self, extiHandlerCallback *fn)
79 self->fn = fn;
82 #if defined(STM32F7) || defined(STM32H7)
83 void EXTIConfig(IO_t io, extiCallbackRec_t *cb, int irqPriority, ioConfig_t config)
85 (void)config;
86 int chIdx;
87 chIdx = IO_GPIOPinIdx(io);
88 if (chIdx < 0)
89 return;
90 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
91 int group = extiGroups[chIdx];
93 GPIO_InitTypeDef init = {
94 .Pin = IO_Pin(io),
95 .Mode = GPIO_MODE_IT_RISING,
96 .Speed = GPIO_SPEED_FREQ_LOW,
97 .Pull = GPIO_NOPULL,
99 HAL_GPIO_Init(IO_GPIO(io), &init);
101 rec->handler = cb;
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)
115 int chIdx;
116 chIdx = IO_GPIOPinIdx(io);
117 if (chIdx < 0)
118 return;
119 // we have only 16 extiChannelRecs
120 ASSERT(chIdx < 16);
121 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
122 int group = extiGroups[chIdx];
123 rec->handler = cb;
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);
143 #else
144 void EXTIConfig(IO_t io, extiCallbackRec_t *cb, int irqPriority, EXTITrigger_TypeDef trigger)
146 int chIdx;
147 chIdx = IO_GPIOPinIdx(io);
148 if (chIdx < 0)
149 return;
151 // we have only 16 extiChannelRecs
152 ASSERT(chIdx < 16);
154 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
155 int group = extiGroups[chIdx];
157 rec->handler = cb;
158 #if defined(STM32F4)
159 SYSCFG_EXTILineConfig(IO_EXTI_PortSourceGPIO(io), IO_EXTI_PinSource(io));
160 #else
161 # warning "Unknown CPU"
162 #endif
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]);
181 #endif
183 void EXTIRelease(IO_t io)
185 // don't forget to match cleanup with config
186 EXTIEnable(io, false);
188 int chIdx;
189 chIdx = IO_GPIOPinIdx(io);
190 if (chIdx < 0)
191 return;
193 // we have only 16 extiChannelRecs
194 ASSERT(chIdx < 16);
196 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
197 rec->handler = NULL;
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);
204 if (!extiLine)
205 return;
206 if (enable)
207 EXTI_REG_IMR |= extiLine;
208 else
209 EXTI_REG_IMR &= ~extiLine;
210 #else
211 # error "Unsupported target"
212 #endif
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) \
229 void name(void) { \
230 EXTI_IRQHandler(); \
232 struct dummy \
233 /**/
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);
244 #else
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);
251 #else
252 # warning "Unknown CPU"
253 #endif
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);
258 #endif
260 #endif