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)
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/>.
29 #include "drivers/nvic.h"
30 #include "drivers/io_impl.h"
31 #include "drivers/exti.h"
34 extiCallbackRec_t
* handler
;
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
] = {
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)
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
)
76 void EXTIConfig(IO_t io
, extiCallbackRec_t
*cb
, int irqPriority
, ioConfig_t config
, extiTrigger_t trigger
)
78 int chIdx
= IO_GPIOPinIdx(io
);
84 int group
= extiGroups
[chIdx
];
86 extiChannelRec_t
*rec
= &extiChannelRecs
[chIdx
];
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
)
122 const int chIdx
= IO_GPIOPinIdx(io
);
128 extiChannelRec_t
*rec
= &extiChannelRecs
[chIdx
];
132 void EXTIEnable(IO_t io
)
134 uint32_t extiLine
= IO_EXTI_Line(io
);
140 EXTI_REG_IMR
|= extiLine
;
143 void EXTIDisable(IO_t io
)
145 uint32_t extiLine
= IO_EXTI_Line(io
);
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) \
173 EXTI_IRQHandler(mask & EXTI_EVENT_MASK); \
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);