APM:Libraries
exti.c
Go to the documentation of this file.
1 /*
2 (c) 2017 night_ghost@ykoctpa.ru
3 
4 based on: LeafLabs
5 
6 */
7 
8 #pragma GCC optimize ("O2")
9 
10 #include "exti.h"
11 #include "hal.h"
12 #include "util.h"
13 #include "nvic.h"
14 
15 
16 typedef struct exti_channel {
17  uint32_t irq_line;
18  IRQn_Type irq_type;
19 } exti_channel;
20 
21 
22 static const exti_channel exti_channels[] = {
23  { .irq_line = EXTI_Line0, .irq_type = EXTI0_IRQn }, // EXTI0
24  { .irq_line = EXTI_Line1, .irq_type = EXTI1_IRQn }, // EXTI1
25  { .irq_line = EXTI_Line2, .irq_type = EXTI2_IRQn }, // EXTI2
26  { .irq_line = EXTI_Line3, .irq_type = EXTI3_IRQn }, // EXTI3
27  { .irq_line = EXTI_Line4, .irq_type = EXTI4_IRQn }, // EXTI4
28  { .irq_line = EXTI_Line5, .irq_type = EXTI9_5_IRQn }, // EXTI5
29  { .irq_line = EXTI_Line6, .irq_type = EXTI9_5_IRQn }, // EXTI6
30  { .irq_line = EXTI_Line7, .irq_type = EXTI9_5_IRQn }, // EXTI7
31  { .irq_line = EXTI_Line8, .irq_type = EXTI9_5_IRQn }, // EXTI8
32  { .irq_line = EXTI_Line9, .irq_type = EXTI9_5_IRQn }, // EXTI9
33  { .irq_line = EXTI_Line10, .irq_type = EXTI15_10_IRQn }, // EXTI10
34  { .irq_line = EXTI_Line11, .irq_type = EXTI15_10_IRQn }, // EXTI11
35  { .irq_line = EXTI_Line12, .irq_type = EXTI15_10_IRQn }, // EXTI12
36  { .irq_line = EXTI_Line13, .irq_type = EXTI15_10_IRQn }, // EXTI13
37  { .irq_line = EXTI_Line14, .irq_type = EXTI15_10_IRQn }, // EXTI14
38  { .irq_line = EXTI_Line15, .irq_type = EXTI15_10_IRQn }, // EXTI15
39 };
40 
41 #define NUM_IRQ (sizeof(exti_channels)/sizeof(exti_channel))
42 
43 static Handler handlers[NUM_IRQ] IN_CCM;
44 
45 
46 void exti_init(){
47  memset(handlers, 0, sizeof(handlers));
48 }
49 
50 
51 static inline EXTITrigger_TypeDef get_exti_mode(exti_trigger_mode mode) {
52  switch (mode) {
53  case EXTI_RISING:
54  return EXTI_Trigger_Rising;
55  case EXTI_FALLING:
56  return EXTI_Trigger_Falling;
58  return EXTI_Trigger_Rising_Falling;
59  }
60  // Can't happen
61  assert_param(0);
62  return (EXTITrigger_TypeDef)0;
63 }
64 
66  afio_exti_port port,
67  Handler handler,
68  exti_trigger_mode mode)
69 {
70  /* Check the parameters */
71  assert_param(handler);
72  assert_param(IS_EXTI_PIN_SOURCE(num));
73  assert_param(IS_EXTI_PORT_SOURCE(num));
74  assert_param(port >= 0 && num <= 4);
75 
76  EXTI_InitTypeDef EXTI_InitStructure;
77 
78  // Register the handler
79  handlers[num] = handler;
80 
81  // Enable SYSCFG clock
82  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
83 
84  afio_exti_select(port, num);
85 
86  uint32_t line = exti_channels[num].irq_line;
87 
88  // clear active request
90 
91  /* Configure EXTI Line */
92  EXTI_InitStructure.EXTI_Line = line;
93  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
94  EXTI_InitStructure.EXTI_Trigger = get_exti_mode(mode);
95  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
96  EXTI_Init(&EXTI_InitStructure);
97 
98  /* Enable and set EXTI Line Interrupt priority */
99  enable_nvic_irq(exti_channels[num].irq_type, GPIO_INT_PRIORITY); // we init NVIC for 4 bit preemption, 0 bit subpriority
100 
101 }
102 
104  afio_exti_port port,
105  Handler handler,
106  exti_trigger_mode mode,
107  uint8_t priority)
108 {
109  /* Check the parameters */
110  assert_param(handler);
111  assert_param(IS_EXTI_PIN_SOURCE(num));
112  assert_param(IS_EXTI_PORT_SOURCE(num));
113  assert_param(port >= 0 && num <= 4);
114 
115  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // we must wait some time before access to SYSCFG
116 
117  /* Register the handler */
118  handlers[num] = handler;
119 
120  // Enable SYSCFG clock
121 
122  afio_exti_select(port, num); // select port as EXTI interrupt source. SYSCFG not documented in STM docs
123 
124  uint32_t line = exti_channels[num].irq_line;
125 
126  // clear active request
128 
129  /* Configure EXTI Line */
130  EXTI_InitTypeDef EXTI_InitStructure;
131  EXTI_InitStructure.EXTI_Line = line;
132  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
133  EXTI_InitStructure.EXTI_Trigger = get_exti_mode(mode);
134  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
135  EXTI_Init(&EXTI_InitStructure);
136 
137  /* Enable and set EXTI Line Interrupt to the given priority */
138  enable_nvic_irq(exti_channels[num].irq_type, priority); // we init NVIC for 4 bit preemption, 0 bit subpriority
139 
140 }
141 
142 
144 {
145  /* Check the parameters */
146  assert_param(IS_EXTI_PORT_SOURCE(num));
147 
148 
149  EXTI_InitTypeDef EXTI_InitStructure;
150  EXTI_StructInit(&EXTI_InitStructure);
151  EXTI_InitStructure.EXTI_Line = exti_channels[num].irq_line;
152  EXTI_InitStructure.EXTI_LineCmd = DISABLE;
153  EXTI_Init(&EXTI_InitStructure);
154 
155 /* do not disable interrupt in NVIC because it can be shared
156  NVIC_DisableIRQ(exti_channels[num].irq_type);
157 */
158 
159  /* Finally, unregister the user's handler */
160  handlers[num] = (Handler)0;
161 }
162 
163 
165  if(e){
166  EXTI->IMR |= exti_channels[num].irq_line;
167  }else {
168  EXTI->IMR &= ~exti_channels[num].irq_line;
169 
170  }
171 }
172 
173 /*
174  * Interrupt handlers
175  */
176 
177 
178 static void exti_serv(uint32_t extline, uint8_t num)
179 {
180 #ifdef ISR_PERF
181  t = stopwatch_getticks();
182 #endif
183  if(EXTI_GetITStatus(extline) != RESET) {
184  Handler handler = handlers[num];
185 
186  if (handler) {
187  revo_call_handler(handler, num); // handler();
188  }
189 
190  /* Clear the EXTI line pending bit */
191  exti_clear_pending_bit(extline);
192  }
193 
194 #ifdef ISR_PERF
195  t = stopwatch_getticks() - t;
196  isr_time += t;
197  if(t>max_isr_time) max_isr_time=t;
198 #endif
199 }
200 
202 {
203  exti_serv(EXTI_Line0, 0);
204 }
205 
206 void EXTI1_IRQHandler(void)
207 {
208  exti_serv(EXTI_Line1, 1);
209 }
210 
211 void EXTI2_IRQHandler(void)
212 {
213  exti_serv(EXTI_Line2, 2);
214 }
215 
216 void EXTI3_IRQHandler(void)
217 {
218  exti_serv(EXTI_Line3, 3);
219 }
220 
221 void EXTI4_IRQHandler(void)
222 {
223  exti_serv(EXTI_Line4, 4);
224 }
225 
227 {
228  exti_serv(EXTI_Line5, 5);
229  exti_serv(EXTI_Line6, 6);
230  exti_serv(EXTI_Line7, 7);
231  exti_serv(EXTI_Line8, 8);
232  exti_serv(EXTI_Line9, 9);
233 }
234 
236 {
237  exti_serv(EXTI_Line10, 10);
238  exti_serv(EXTI_Line11, 11);
239  exti_serv(EXTI_Line12, 12);
240  exti_serv(EXTI_Line13, 13);
241  exti_serv(EXTI_Line14, 14);
242  exti_serv(EXTI_Line15, 15);
243 }
244 
static uint32_t stopwatch_getticks()
Definition: stopwatch.h:33
void exti_attach_interrupt(afio_exti_num num, afio_exti_port port, Handler handler, exti_trigger_mode mode)
Register a handler to run upon external interrupt.
Definition: exti.c:65
static void exti_clear_pending_bit(uint32_t EXTI_Line)
Definition: exti.h:126
#define NUM_IRQ
Definition: exti.c:41
static const exti_channel exti_channels[]
Definition: exti.c:22
uint32_t irq_line
Definition: exti.c:17
#define assert_param(expr)
void exti_init()
Definition: exti.c:46
void EXTI4_IRQHandler(void)
Definition: exti.c:221
IRQn_Type irq_type
Definition: exti.c:18
struct exti_channel exti_channel
void exti_attach_interrupt_pri(afio_exti_num num, afio_exti_port port, Handler handler, exti_trigger_mode mode, uint8_t priority)
Definition: exti.c:103
void EXTI15_10_IRQHandler(void)
Definition: exti.c:235
void EXTI0_IRQHandler(void)
Definition: exti.c:201
exti_trigger_mode
Definition: exti.h:51
void enable_nvic_irq(uint8_t irq, uint8_t prio)
Definition: nvic.c:8
Miscellaneous utility macros and procedures.
afio_exti_num
Definition: exti.h:15
static EXTITrigger_TypeDef get_exti_mode(exti_trigger_mode mode)
Definition: exti.c:51
static Handler handlers [NUM_IRQ] IN_CCM
Definition: exti.c:43
void EXTI2_IRQHandler(void)
Definition: exti.c:211
#define GPIO_INT_PRIORITY
Definition: Config.h:47
void exti_enable_interrupt(afio_exti_num num, bool e)
Definition: exti.c:164
uint64_t Handler
Definition: hal_types.h:19
void exti_detach_interrupt(afio_exti_num num)
Unregister an external interrupt handler.
Definition: exti.c:143
void uint32_t num
Definition: systick.h:80
void EXTI1_IRQHandler(void)
Definition: exti.c:206
void revo_call_handler(Handler h, uint32_t arg)
Definition: Scheduler.cpp:1420
static void afio_exti_select(afio_exti_port gpio_port, afio_exti_num pin)
Definition: gpio_hal.h:168
void EXTI9_5_IRQHandler(void)
Definition: exti.c:226
void EXTI3_IRQHandler(void)
Definition: exti.c:216
static void exti_serv(uint32_t extline, uint8_t num)
Definition: exti.c:178
afio_exti_port
External interrupt line port selector.
Definition: exti.h:40