Refactor missing prototypes 2 (#14170)
[betaflight.git] / src / platform / AT32 / exti_at32.c
blobc0e2d3dafcce66ff042a957e9b7dbd1585225a15
1 /*
2 * This file is part of Betaflight.
4 * Betaflight is free software. You can redistribute this software
5 * and/or modify this software under the terms of the GNU General
6 * Public License as published by the Free Software Foundation,
7 * either version 3 of the License, or (at your option) any later
8 * version.
10 * Betaflight is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this software.
19 * If not, see <http://www.gnu.org/licenses/>.
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <string.h>
26 #include "platform.h"
28 #ifdef USE_EXTI
30 #include "drivers/nvic.h"
31 #include "drivers/io_impl.h"
32 #include "drivers/exti.h"
34 typedef struct {
35 extiCallbackRec_t* handler;
36 } extiChannelRec_t;
38 extiChannelRec_t extiChannelRecs[16];
40 #define EXTI_IRQ_GROUPS 7
41 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
42 static const uint8_t extiGroups[16] = { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 };
43 static uint8_t extiGroupPriority[EXTI_IRQ_GROUPS];
45 static const uint8_t extiGroupIRQn[EXTI_IRQ_GROUPS] = {
46 EXINT0_IRQn,
47 EXINT1_IRQn,
48 EXINT2_IRQn,
49 EXINT3_IRQn,
50 EXINT4_IRQn,
51 EXINT9_5_IRQn,
52 EXINT15_10_IRQn
55 static uint32_t triggerLookupTable[] = {
56 [BETAFLIGHT_EXTI_TRIGGER_RISING] = EXINT_TRIGGER_RISING_EDGE,
57 [BETAFLIGHT_EXTI_TRIGGER_FALLING] = EXINT_TRIGGER_FALLING_EDGE,
58 [BETAFLIGHT_EXTI_TRIGGER_BOTH] = EXINT_TRIGGER_BOTH_EDGE
61 #define EXTI_REG_IMR (EXINT->inten)
62 #define EXTI_REG_PR (EXINT->intsts)
64 void EXTIInit(void)
66 crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
68 memset(extiChannelRecs, 0, sizeof(extiChannelRecs));
69 memset(extiGroupPriority, 0xff, sizeof(extiGroupPriority));
72 void EXTIHandlerInit(extiCallbackRec_t *self, extiHandlerCallback *fn)
74 self->fn = fn;
77 void EXTIConfig(IO_t io, extiCallbackRec_t *cb, int irqPriority, ioConfig_t config, extiTrigger_t trigger)
79 int chIdx = IO_GPIOPinIdx(io);
81 if (chIdx < 0) {
82 return;
85 int group = extiGroups[chIdx];
87 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
88 rec->handler = cb;
90 EXTIDisable(io);
92 IOConfigGPIO(io, config);
94 scfg_exint_line_config(IO_GPIO_PortSource(io), IO_GPIO_PinSource(io));
96 uint32_t extiLine = IO_EXTI_Line(io);
98 exint_flag_clear(extiLine);
100 exint_init_type exint_init_struct;
101 exint_default_para_init(&exint_init_struct);
102 exint_init_struct.line_enable = TRUE;
103 exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
104 exint_init_struct.line_select = extiLine;
105 exint_init_struct.line_polarity = triggerLookupTable[trigger];
106 exint_init(&exint_init_struct);
108 if (extiGroupPriority[group] > irqPriority) {
109 extiGroupPriority[group] = irqPriority;
111 nvic_priority_group_config(NVIC_PRIORITY_GROUPING);
112 nvic_irq_enable(extiGroupIRQn[group],
113 NVIC_PRIORITY_BASE(irqPriority),
114 NVIC_PRIORITY_SUB(irqPriority));
119 void EXTIRelease(IO_t io)
121 EXTIDisable(io);
123 const int chIdx = IO_GPIOPinIdx(io);
125 if (chIdx < 0) {
126 return;
129 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
130 rec->handler = NULL;
133 void EXTIEnable(IO_t io)
135 uint32_t extiLine = IO_EXTI_Line(io);
137 if (!extiLine) {
138 return;
141 EXTI_REG_IMR |= extiLine;
144 void EXTIDisable(IO_t io)
146 uint32_t extiLine = IO_EXTI_Line(io);
148 if (!extiLine) {
149 return;
152 EXTI_REG_IMR &= ~extiLine;
153 EXTI_REG_PR = extiLine;
156 #define EXTI_EVENT_MASK 0xFFFF
158 static void EXTI_IRQHandler(uint32_t mask)
160 uint32_t exti_active = (EXTI_REG_IMR & EXTI_REG_PR) & mask;
162 EXTI_REG_PR = exti_active;
164 while (exti_active) {
165 unsigned idx = 31 - __builtin_clz(exti_active);
166 uint32_t mask = 1 << idx;
167 extiChannelRecs[idx].handler->fn(extiChannelRecs[idx].handler);
168 exti_active &= ~mask;
172 #define _EXTI_IRQ_HANDLER(name, mask) \
173 void name(void) { \
174 EXTI_IRQHandler(mask & EXTI_EVENT_MASK); \
176 struct dummy \
177 /**/
179 _EXTI_IRQ_HANDLER(EXINT0_IRQHandler, 0x0001);
180 _EXTI_IRQ_HANDLER(EXINT1_IRQHandler, 0x0002);
181 _EXTI_IRQ_HANDLER(EXINT2_IRQHandler, 0x0004);
182 _EXTI_IRQ_HANDLER(EXINT3_IRQHandler, 0x0008);
183 _EXTI_IRQ_HANDLER(EXINT4_IRQHandler, 0x0010);
184 _EXTI_IRQ_HANDLER(EXINT9_5_IRQHandler, 0x03e0);
185 _EXTI_IRQ_HANDLER(EXINT15_10_IRQHandler, 0xfc00);
187 #endif