Firmware SDK
twr_exti.c
1 #include <twr_exti.h>
2 #include <twr_irq.h>
3 #include <stm32l0xx.h>
4 
5 static bool _twr_exti_initialized = false;
6 
7 static struct
8 {
9  twr_exti_line_t line;
10  void (*callback)(twr_exti_line_t, void *);
11  void *param;
12 
13 } _twr_exti[16];
14 
15 static inline void _twr_exti_irq_handler(void);
16 
17 void twr_exti_register(twr_exti_line_t line, twr_exti_edge_t edge, void (*callback)(twr_exti_line_t, void *), void *param)
18 {
19  // Extract port number
20  uint8_t port = ((uint8_t) line >> 4) & 7;
21 
22  // Extract pin number
23  uint8_t pin = (uint8_t) line & 15;
24 
25  // Extract mask
26  uint16_t mask = 1 << pin;
27 
28  // Disable interrupts
30 
31  // Store line identifier
32  _twr_exti[pin].line = line;
33 
34  // Store callback function
35  _twr_exti[pin].callback = callback;
36 
37  // Store callback parameter
38  _twr_exti[pin].param = param;
39 
40  // If this is the first call...
41  if (!_twr_exti_initialized)
42  {
43  // Remember it has been already initialized
44  _twr_exti_initialized = true;
45 
46  // Enable SYSCFG clock
47  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
48 
49  // Enable EXTI interrupt requests
50  NVIC_EnableIRQ(EXTI0_1_IRQn);
51  NVIC_EnableIRQ(EXTI2_3_IRQn);
52  NVIC_EnableIRQ(EXTI4_15_IRQn);
53  }
54 
55  // Configure port selection for given line
56  SYSCFG->EXTICR[pin >> 2] |= port << ((pin & 3) << 2);
57 
58  if (edge == TWR_EXTI_EDGE_RISING)
59  {
60  // Enable rising edge trigger
61  EXTI->RTSR |= mask;
62 
63  // Disable falling edge trigger
64  EXTI->FTSR &= ~mask;
65  }
66  else if (edge == TWR_EXTI_EDGE_FALLING)
67  {
68  // Disable rising edge trigger
69  EXTI->RTSR &= ~mask;
70 
71  // Enable falling edge trigger
72  EXTI->FTSR |= mask;
73  }
74  else if (edge == TWR_EXTI_EDGE_RISING_AND_FALLING)
75  {
76  // Enable rising edge trigger
77  EXTI->RTSR |= mask;
78 
79  // Enable falling edge trigger
80  EXTI->FTSR |= mask;
81  }
82 
83  // Unmask interrupt request
84  EXTI->IMR |= mask;
85 
86  // Enable interrupts
88 }
89 
91 {
92  // Extract pin number
93  uint8_t pin = (uint8_t) line & 15;
94 
95  // Extract mask
96  uint16_t mask = 1 << pin;
97 
98  // Disable interrupts
100 
101  // If line identifier matches record...
102  if (line == _twr_exti[pin].line)
103  {
104  // Mask interrupt request
105  EXTI->IMR &= ~mask;
106 
107  // Clear pending interrupt
108  EXTI->PR = mask;
109  }
110 
111  // Enable interrupts
112  twr_irq_enable();
113 }
114 
115 static inline void _twr_exti_irq_handler(void)
116 {
117  // Determine source of interrupt and call appropriate callback
118  if ((EXTI->PR & 0x0001) != 0) { EXTI->PR = 0x0001; _twr_exti[0].callback(_twr_exti[0].line, _twr_exti[0].param); return; }
119  if ((EXTI->PR & 0x0002) != 0) { EXTI->PR = 0x0002; _twr_exti[1].callback(_twr_exti[1].line, _twr_exti[1].param); return; }
120  if ((EXTI->PR & 0x0004) != 0) { EXTI->PR = 0x0004; _twr_exti[2].callback(_twr_exti[2].line, _twr_exti[2].param); return; }
121  if ((EXTI->PR & 0x0008) != 0) { EXTI->PR = 0x0008; _twr_exti[3].callback(_twr_exti[3].line, _twr_exti[3].param); return; }
122  if ((EXTI->PR & 0x0010) != 0) { EXTI->PR = 0x0010; _twr_exti[4].callback(_twr_exti[4].line, _twr_exti[4].param); return; }
123  if ((EXTI->PR & 0x0020) != 0) { EXTI->PR = 0x0020; _twr_exti[5].callback(_twr_exti[5].line, _twr_exti[5].param); return; }
124  if ((EXTI->PR & 0x0040) != 0) { EXTI->PR = 0x0040; _twr_exti[6].callback(_twr_exti[6].line, _twr_exti[6].param); return; }
125  if ((EXTI->PR & 0x0080) != 0) { EXTI->PR = 0x0080; _twr_exti[7].callback(_twr_exti[7].line, _twr_exti[7].param); return; }
126  if ((EXTI->PR & 0x0100) != 0) { EXTI->PR = 0x0100; _twr_exti[8].callback(_twr_exti[8].line, _twr_exti[8].param); return; }
127  if ((EXTI->PR & 0x0200) != 0) { EXTI->PR = 0x0200; _twr_exti[9].callback(_twr_exti[9].line, _twr_exti[9].param); return; }
128  if ((EXTI->PR & 0x0400) != 0) { EXTI->PR = 0x0400; _twr_exti[10].callback(_twr_exti[10].line, _twr_exti[10].param); return; }
129  if ((EXTI->PR & 0x0800) != 0) { EXTI->PR = 0x0800; _twr_exti[11].callback(_twr_exti[11].line, _twr_exti[11].param); return; }
130  if ((EXTI->PR & 0x1000) != 0) { EXTI->PR = 0x1000; _twr_exti[12].callback(_twr_exti[12].line, _twr_exti[12].param); return; }
131  if ((EXTI->PR & 0x2000) != 0) { EXTI->PR = 0x2000; _twr_exti[13].callback(_twr_exti[13].line, _twr_exti[13].param); return; }
132  if ((EXTI->PR & 0x4000) != 0) { EXTI->PR = 0x4000; _twr_exti[14].callback(_twr_exti[14].line, _twr_exti[14].param); return; }
133  if ((EXTI->PR & 0x8000) != 0) { EXTI->PR = 0x8000; _twr_exti[15].callback(_twr_exti[15].line, _twr_exti[15].param); return; }
134 }
135 
136 void EXTI0_1_IRQHandler(void)
137 {
138  _twr_exti_irq_handler();
139 }
140 
141 void EXTI2_3_IRQHandler(void)
142 {
143  _twr_exti_irq_handler();
144 }
145 
146 void EXTI4_15_IRQHandler(void)
147 {
148  _twr_exti_irq_handler();
149 }
void twr_exti_register(twr_exti_line_t line, twr_exti_edge_t edge, void(*callback)(twr_exti_line_t, void *), void *param)
Enable EXTI line interrupt and register callback function.
Definition: twr_exti.c:17
void twr_exti_unregister(twr_exti_line_t line)
Disable EXTI line interrupt.
Definition: twr_exti.c:90
twr_exti_line_t
EXTI lines.
Definition: twr_exti.h:22
twr_exti_edge_t
Interrupt edge sensitivity.
Definition: twr_exti.h:196
@ TWR_EXTI_EDGE_FALLING
EXTI line is configured to falling edge sensitivity.
Definition: twr_exti.h:201
@ TWR_EXTI_EDGE_RISING_AND_FALLING
EXTI line is configured to both rising and falling edge sensitivity.
Definition: twr_exti.h:204
@ TWR_EXTI_EDGE_RISING
EXTI line is configured to rising edge sensitivity.
Definition: twr_exti.h:198
void twr_irq_disable(void)
Disable interrupt requests globally (call can be nested)
Definition: twr_irq.c:7
void twr_irq_enable(void)
Enable interrupt requests globally (call can be nested)
Definition: twr_irq.c:21