Send motor data and then immediately decode prior telemetry data for bitbanged DSHOT...
[betaflight.git] / src / main / drivers / at32 / exti_at32.c
blob78f40edea5c1623d378822934bcebeccf3f43fd1
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
25 #include "platform.h"
27 #ifdef USE_EXTI
29 #include "drivers/nvic.h"
30 #include "drivers/io_impl.h"
31 #include "drivers/exti.h"
33 typedef struct {
34 extiCallbackRec_t* handler;
35 } extiChannelRec_t;
37 extiChannelRec_t extiChannelRecs[16];
39 #define EXTI_IRQ_GROUPS 7
40 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
41 static const uint8_t extiGroups[16] = { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 };
42 static uint8_t extiGroupPriority[EXTI_IRQ_GROUPS];
44 static const uint8_t extiGroupIRQn[EXTI_IRQ_GROUPS] = {
45 EXINT0_IRQn,
46 EXINT1_IRQn,
47 EXINT2_IRQn,
48 EXINT3_IRQn,
49 EXINT4_IRQn,
50 EXINT9_5_IRQn,
51 EXINT15_10_IRQn
54 static uint32_t triggerLookupTable[] = {
55 [BETAFLIGHT_EXTI_TRIGGER_RISING] = EXINT_TRIGGER_RISING_EDGE,
56 [BETAFLIGHT_EXTI_TRIGGER_FALLING] = EXINT_TRIGGER_FALLING_EDGE,
57 [BETAFLIGHT_EXTI_TRIGGER_BOTH] = EXINT_TRIGGER_BOTH_EDGE
60 #define EXTI_REG_IMR (EXINT->inten)
61 #define EXTI_REG_PR (EXINT->intsts)
63 void EXTIInit(void)
65 crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
67 memset(extiChannelRecs, 0, sizeof(extiChannelRecs));
68 memset(extiGroupPriority, 0xff, sizeof(extiGroupPriority));
71 void EXTIHandlerInit(extiCallbackRec_t *self, extiHandlerCallback *fn)
73 self->fn = fn;
76 void EXTIConfig(IO_t io, extiCallbackRec_t *cb, int irqPriority, ioConfig_t config, extiTrigger_t trigger)
78 int chIdx = IO_GPIOPinIdx(io);
80 if (chIdx < 0) {
81 return;
84 int group = extiGroups[chIdx];
86 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
87 rec->handler = cb;
89 EXTIDisable(io);
91 IOConfigGPIO(io, config);
93 scfg_exint_line_config(IO_GPIO_PortSource(io), IO_GPIO_PinSource(io));
95 uint32_t extiLine = IO_EXTI_Line(io);
97 exint_flag_clear(extiLine);
99 exint_init_type exint_init_struct;
100 exint_default_para_init(&exint_init_struct);
101 exint_init_struct.line_enable = TRUE;
102 exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
103 exint_init_struct.line_select = extiLine;
104 exint_init_struct.line_polarity = triggerLookupTable[trigger];
105 exint_init(&exint_init_struct);
107 if (extiGroupPriority[group] > irqPriority) {
108 extiGroupPriority[group] = irqPriority;
110 nvic_priority_group_config(NVIC_PRIORITY_GROUPING);
111 nvic_irq_enable(extiGroupIRQn[group],
112 NVIC_PRIORITY_BASE(irqPriority),
113 NVIC_PRIORITY_SUB(irqPriority));
118 void EXTIRelease(IO_t io)
120 EXTIDisable(io);
122 const int chIdx = IO_GPIOPinIdx(io);
124 if (chIdx < 0) {
125 return;
128 extiChannelRec_t *rec = &extiChannelRecs[chIdx];
129 rec->handler = NULL;
132 void EXTIEnable(IO_t io)
134 uint32_t extiLine = IO_EXTI_Line(io);
136 if (!extiLine) {
137 return;
140 EXTI_REG_IMR |= extiLine;
143 void EXTIDisable(IO_t io)
145 uint32_t extiLine = IO_EXTI_Line(io);
147 if (!extiLine) {
148 return;
151 EXTI_REG_IMR &= ~extiLine;
152 EXTI_REG_PR = extiLine;
155 #define EXTI_EVENT_MASK 0xFFFF
157 void EXTI_IRQHandler(uint32_t mask)
159 uint32_t exti_active = (EXTI_REG_IMR & EXTI_REG_PR) & mask;
161 EXTI_REG_PR = exti_active;
163 while (exti_active) {
164 unsigned idx = 31 - __builtin_clz(exti_active);
165 uint32_t mask = 1 << idx;
166 extiChannelRecs[idx].handler->fn(extiChannelRecs[idx].handler);
167 exti_active &= ~mask;
171 #define _EXTI_IRQ_HANDLER(name, mask) \
172 void name(void) { \
173 EXTI_IRQHandler(mask & EXTI_EVENT_MASK); \
175 struct dummy \
176 /**/
178 _EXTI_IRQ_HANDLER(EXINT0_IRQHandler, 0x0001);
179 _EXTI_IRQ_HANDLER(EXINT1_IRQHandler, 0x0002);
180 _EXTI_IRQ_HANDLER(EXINT2_IRQHandler, 0x0004);
181 _EXTI_IRQ_HANDLER(EXINT3_IRQHandler, 0x0008);
182 _EXTI_IRQ_HANDLER(EXINT4_IRQHandler, 0x0010);
183 _EXTI_IRQ_HANDLER(EXINT9_5_IRQHandler, 0x03e0);
184 _EXTI_IRQ_HANDLER(EXINT15_10_IRQHandler, 0xfc00);
186 #endif