Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_gpio.c
1 #include <bc_gpio.h>
2 #include <bc_irq.h>
3 #include <stm32l0xx.h>
4 
5 #define BC_GPIO_CHANNEL_COUNT 21
6 
7 #define BC_GPIO_PORT_P0 GPIOA
8 #define BC_GPIO_PORT_P1 GPIOA
9 #define BC_GPIO_PORT_P2 GPIOA
10 #define BC_GPIO_PORT_P3 GPIOA
11 #define BC_GPIO_PORT_P4 GPIOA
12 #define BC_GPIO_PORT_P5 GPIOA
13 #define BC_GPIO_PORT_P6 GPIOB
14 #define BC_GPIO_PORT_P7 GPIOA
15 #define BC_GPIO_PORT_P8 GPIOB
16 #define BC_GPIO_PORT_P9 GPIOB
17 #define BC_GPIO_PORT_P10 GPIOA
18 #define BC_GPIO_PORT_P11 GPIOA
19 #define BC_GPIO_PORT_P12 GPIOB
20 #define BC_GPIO_PORT_P13 GPIOB
21 #define BC_GPIO_PORT_P14 GPIOB
22 #define BC_GPIO_PORT_P15 GPIOB
23 #define BC_GPIO_PORT_P16 GPIOB
24 #define BC_GPIO_PORT_P17 GPIOB
25 #define BC_GPIO_PORT_LED GPIOH
26 #define BC_GPIO_PORT_BUTTON GPIOA
27 #define BC_GPIO_PORT_INT GPIOC
28 
29 #define BC_GPIO_POS_P0 0
30 #define BC_GPIO_POS_P1 1
31 #define BC_GPIO_POS_P2 2
32 #define BC_GPIO_POS_P3 3
33 #define BC_GPIO_POS_P4 4
34 #define BC_GPIO_POS_P5 5
35 #define BC_GPIO_POS_P6 1
36 #define BC_GPIO_POS_P7 6
37 #define BC_GPIO_POS_P8 0
38 #define BC_GPIO_POS_P9 2
39 #define BC_GPIO_POS_P10 10
40 #define BC_GPIO_POS_P11 9
41 #define BC_GPIO_POS_P12 14
42 #define BC_GPIO_POS_P13 15
43 #define BC_GPIO_POS_P14 13
44 #define BC_GPIO_POS_P15 12
45 #define BC_GPIO_POS_P16 8
46 #define BC_GPIO_POS_P17 9
47 #define BC_GPIO_POS_LED 1
48 #define BC_GPIO_POS_BUTTON 8
49 #define BC_GPIO_POS_INT 13
50 
51 #define _BC_GPIO_MODE_MASK 0xf
52 #define _BC_GPIO_MODE_AF_POS 4
53 #define _bc_gpio_64_bit_pos(__CHANNEL__) (_bc_gpio_32_bit_pos[(__CHANNEL__)] << 1)
54 
55 GPIO_TypeDef * const bc_gpio_port[BC_GPIO_CHANNEL_COUNT] =
56 {
57  BC_GPIO_PORT_P0,
58  BC_GPIO_PORT_P1,
59  BC_GPIO_PORT_P2,
60  BC_GPIO_PORT_P3,
61  BC_GPIO_PORT_P4,
62  BC_GPIO_PORT_P5,
63  BC_GPIO_PORT_P6,
64  BC_GPIO_PORT_P7,
65  BC_GPIO_PORT_P8,
66  BC_GPIO_PORT_P9,
67  BC_GPIO_PORT_P10,
68  BC_GPIO_PORT_P11,
69  BC_GPIO_PORT_P12,
70  BC_GPIO_PORT_P13,
71  BC_GPIO_PORT_P14,
72  BC_GPIO_PORT_P15,
73  BC_GPIO_PORT_P16,
74  BC_GPIO_PORT_P17,
75  BC_GPIO_PORT_LED,
76  BC_GPIO_PORT_BUTTON,
77  BC_GPIO_PORT_INT
78 };
79 
80 static const uint8_t _bc_gpio_iopenr_mask[BC_GPIO_CHANNEL_COUNT] =
81 {
82  RCC_IOPENR_GPIOAEN, // P0
83  RCC_IOPENR_GPIOAEN, // P1
84  RCC_IOPENR_GPIOAEN, // P2
85  RCC_IOPENR_GPIOAEN, // P3
86  RCC_IOPENR_GPIOAEN, // P4
87  RCC_IOPENR_GPIOAEN, // P5
88  RCC_IOPENR_GPIOBEN, // P6
89  RCC_IOPENR_GPIOAEN, // P7
90  RCC_IOPENR_GPIOBEN, // P8
91  RCC_IOPENR_GPIOBEN, // P9
92  RCC_IOPENR_GPIOAEN, // P10
93  RCC_IOPENR_GPIOAEN, // P11
94  RCC_IOPENR_GPIOBEN, // P12
95  RCC_IOPENR_GPIOBEN, // P13
96  RCC_IOPENR_GPIOBEN, // P14
97  RCC_IOPENR_GPIOBEN, // P15
98  RCC_IOPENR_GPIOBEN, // P16
99  RCC_IOPENR_GPIOBEN, // P17
100  RCC_IOPENR_GPIOHEN, // LED
101  RCC_IOPENR_GPIOAEN, // BUTTON
102  RCC_IOPENR_GPIOCEN // INT
103 };
104 
105 static const uint16_t _bc_gpio_16_bit_pos[BC_GPIO_CHANNEL_COUNT] =
106 {
107  BC_GPIO_POS_P0,
108  BC_GPIO_POS_P1,
109  BC_GPIO_POS_P2,
110  BC_GPIO_POS_P3,
111  BC_GPIO_POS_P4,
112  BC_GPIO_POS_P5,
113  BC_GPIO_POS_P6,
114  BC_GPIO_POS_P7,
115  BC_GPIO_POS_P8,
116  BC_GPIO_POS_P9,
117  BC_GPIO_POS_P10,
118  BC_GPIO_POS_P11,
119  BC_GPIO_POS_P12,
120  BC_GPIO_POS_P13,
121  BC_GPIO_POS_P14,
122  BC_GPIO_POS_P15,
123  BC_GPIO_POS_P16,
124  BC_GPIO_POS_P17,
125  BC_GPIO_POS_LED,
126  BC_GPIO_POS_BUTTON,
127  BC_GPIO_POS_INT
128 };
129 
130 static const uint16_t _bc_gpio_32_bit_pos[BC_GPIO_CHANNEL_COUNT] =
131 {
132  2 * BC_GPIO_POS_P0,
133  2 * BC_GPIO_POS_P1,
134  2 * BC_GPIO_POS_P2,
135  2 * BC_GPIO_POS_P3,
136  2 * BC_GPIO_POS_P4,
137  2 * BC_GPIO_POS_P5,
138  2 * BC_GPIO_POS_P6,
139  2 * BC_GPIO_POS_P7,
140  2 * BC_GPIO_POS_P8,
141  2 * BC_GPIO_POS_P9,
142  2 * BC_GPIO_POS_P10,
143  2 * BC_GPIO_POS_P11,
144  2 * BC_GPIO_POS_P12,
145  2 * BC_GPIO_POS_P13,
146  2 * BC_GPIO_POS_P14,
147  2 * BC_GPIO_POS_P15,
148  2 * BC_GPIO_POS_P16,
149  2 * BC_GPIO_POS_P17,
150  2 * BC_GPIO_POS_LED,
151  2 * BC_GPIO_POS_BUTTON,
152  2 * BC_GPIO_POS_INT
153 };
154 
155 const uint16_t bc_gpio_16_bit_mask[BC_GPIO_CHANNEL_COUNT] =
156 {
157  1 << BC_GPIO_POS_P0,
158  1 << BC_GPIO_POS_P1,
159  1 << BC_GPIO_POS_P2,
160  1 << BC_GPIO_POS_P3,
161  1 << BC_GPIO_POS_P4,
162  1 << BC_GPIO_POS_P5,
163  1 << BC_GPIO_POS_P6,
164  1 << BC_GPIO_POS_P7,
165  1 << BC_GPIO_POS_P8,
166  1 << BC_GPIO_POS_P9,
167  1 << BC_GPIO_POS_P10,
168  1 << BC_GPIO_POS_P11,
169  1 << BC_GPIO_POS_P12,
170  1 << BC_GPIO_POS_P13,
171  1 << BC_GPIO_POS_P14,
172  1 << BC_GPIO_POS_P15,
173  1 << BC_GPIO_POS_P16,
174  1 << BC_GPIO_POS_P17,
175  1 << BC_GPIO_POS_LED,
176  1 << BC_GPIO_POS_BUTTON,
177  1 << BC_GPIO_POS_INT
178 };
179 
180 static const uint32_t _bc_gpio_32_bit_mask[4][BC_GPIO_CHANNEL_COUNT] =
181 {
182  {
183  0UL,
184  0UL,
185  0UL,
186  0UL,
187  0UL,
188  0UL,
189  0UL,
190  0UL,
191  0UL,
192  0UL,
193  0UL,
194  0UL,
195  0UL,
196  0UL,
197  0UL,
198  0UL,
199  0UL,
200  0UL,
201  0UL,
202  0UL,
203  0UL
204  },
205  {
206  1UL << (2 * BC_GPIO_POS_P0),
207  1UL << (2 * BC_GPIO_POS_P1),
208  1UL << (2 * BC_GPIO_POS_P2),
209  1UL << (2 * BC_GPIO_POS_P3),
210  1UL << (2 * BC_GPIO_POS_P4),
211  1UL << (2 * BC_GPIO_POS_P5),
212  1UL << (2 * BC_GPIO_POS_P6),
213  1UL << (2 * BC_GPIO_POS_P7),
214  1UL << (2 * BC_GPIO_POS_P8),
215  1UL << (2 * BC_GPIO_POS_P9),
216  1UL << (2 * BC_GPIO_POS_P10),
217  1UL << (2 * BC_GPIO_POS_P11),
218  1UL << (2 * BC_GPIO_POS_P12),
219  1UL << (2 * BC_GPIO_POS_P13),
220  1UL << (2 * BC_GPIO_POS_P14),
221  1UL << (2 * BC_GPIO_POS_P15),
222  1UL << (2 * BC_GPIO_POS_P16),
223  1UL << (2 * BC_GPIO_POS_P17),
224  1UL << (2 * BC_GPIO_POS_LED),
225  1UL << (2 * BC_GPIO_POS_BUTTON),
226  1UL << (2 * BC_GPIO_POS_INT)
227  },
228  {
229  2UL << (2 * BC_GPIO_POS_P0),
230  2UL << (2 * BC_GPIO_POS_P1),
231  2UL << (2 * BC_GPIO_POS_P2),
232  2UL << (2 * BC_GPIO_POS_P3),
233  2UL << (2 * BC_GPIO_POS_P4),
234  2UL << (2 * BC_GPIO_POS_P5),
235  2UL << (2 * BC_GPIO_POS_P6),
236  2UL << (2 * BC_GPIO_POS_P7),
237  2UL << (2 * BC_GPIO_POS_P8),
238  2UL << (2 * BC_GPIO_POS_P9),
239  2UL << (2 * BC_GPIO_POS_P10),
240  2UL << (2 * BC_GPIO_POS_P11),
241  2UL << (2 * BC_GPIO_POS_P12),
242  2UL << (2 * BC_GPIO_POS_P13),
243  2UL << (2 * BC_GPIO_POS_P14),
244  2UL << (2 * BC_GPIO_POS_P15),
245  2UL << (2 * BC_GPIO_POS_P16),
246  2UL << (2 * BC_GPIO_POS_P17),
247  2UL << (2 * BC_GPIO_POS_LED),
248  2UL << (2 * BC_GPIO_POS_BUTTON),
249  2UL << (2 * BC_GPIO_POS_INT)
250  },
251  {
252  3UL << (2 * BC_GPIO_POS_P0),
253  3UL << (2 * BC_GPIO_POS_P1),
254  3UL << (2 * BC_GPIO_POS_P2),
255  3UL << (2 * BC_GPIO_POS_P3),
256  3UL << (2 * BC_GPIO_POS_P4),
257  3UL << (2 * BC_GPIO_POS_P5),
258  3UL << (2 * BC_GPIO_POS_P6),
259  3UL << (2 * BC_GPIO_POS_P7),
260  3UL << (2 * BC_GPIO_POS_P8),
261  3UL << (2 * BC_GPIO_POS_P9),
262  3UL << (2 * BC_GPIO_POS_P10),
263  3UL << (2 * BC_GPIO_POS_P11),
264  3UL << (2 * BC_GPIO_POS_P12),
265  3UL << (2 * BC_GPIO_POS_P13),
266  3UL << (2 * BC_GPIO_POS_P14),
267  3UL << (2 * BC_GPIO_POS_P15),
268  3UL << (2 * BC_GPIO_POS_P16),
269  3UL << (2 * BC_GPIO_POS_P17),
270  3UL << (2 * BC_GPIO_POS_LED),
271  3UL << (2 * BC_GPIO_POS_BUTTON),
272  3UL << (2 * BC_GPIO_POS_INT)
273  }
274 };
275 
276 const uint32_t bc_gpio_32_bit_upper_mask[BC_GPIO_CHANNEL_COUNT] =
277 {
278  (1UL << 16) << BC_GPIO_POS_P0,
279  (1UL << 16) << BC_GPIO_POS_P1,
280  (1UL << 16) << BC_GPIO_POS_P2,
281  (1UL << 16) << BC_GPIO_POS_P3,
282  (1UL << 16) << BC_GPIO_POS_P4,
283  (1UL << 16) << BC_GPIO_POS_P5,
284  (1UL << 16) << BC_GPIO_POS_P6,
285  (1UL << 16) << BC_GPIO_POS_P7,
286  (1UL << 16) << BC_GPIO_POS_P8,
287  (1UL << 16) << BC_GPIO_POS_P9,
288  (1UL << 16) << BC_GPIO_POS_P10,
289  (1UL << 16) << BC_GPIO_POS_P11,
290  (1UL << 16) << BC_GPIO_POS_P12,
291  (1UL << 16) << BC_GPIO_POS_P13,
292  (1UL << 16) << BC_GPIO_POS_P14,
293  (1UL << 16) << BC_GPIO_POS_P15,
294  (1UL << 16) << BC_GPIO_POS_P16,
295  (1UL << 16) << BC_GPIO_POS_P17,
296  (1UL << 16) << BC_GPIO_POS_LED,
297  (1UL << 16) << BC_GPIO_POS_BUTTON,
298  (1UL << 16) << BC_GPIO_POS_INT
299 };
300 
302 {
303  // Disable interrupts
304  bc_irq_disable();
305 
306  // Enable GPIO clock
307  RCC->IOPENR |= _bc_gpio_iopenr_mask[channel];
308 
309  // Enable interrupts
310  bc_irq_enable();
311 }
312 
314 {
315  // Disable interrupts
316  bc_irq_disable();
317 
318  // Read PUPDR register
319  uint32_t pupdr = bc_gpio_port[channel]->PUPDR;
320 
321  // Reset corresponding PUPDR bits
322  pupdr &= ~_bc_gpio_32_bit_mask[3][channel];
323 
324  // Set corresponding PUPDR bits
325  pupdr |= _bc_gpio_32_bit_mask[pull][channel];
326 
327  // Write PUPDR register
328  bc_gpio_port[channel]->PUPDR = pupdr;
329 
330  // Enable interrupts
331  bc_irq_enable();
332 }
333 
335 {
336  // Return pull setting from PUPDR register
337  return (bc_gpio_pull_t) ((bc_gpio_port[channel]->PUPDR >> _bc_gpio_32_bit_pos[channel]) & 3);
338 }
339 
341 {
342  // Disable interrupts
343  bc_irq_disable();
344 
345  // Read OTYPER register
346  uint32_t otyper = bc_gpio_port[channel]->OTYPER;
347 
348  // Read MODER register
349  uint32_t moder = bc_gpio_port[channel]->MODER;
350 
351  // If mode setting is open-drain output...
352  if (mode == BC_GPIO_MODE_OUTPUT_OD)
353  {
354  // Set corresponding OTYPER bit
355  otyper |= bc_gpio_16_bit_mask[channel];
356 
357  // Override desired mode setting to output
358  mode = BC_GPIO_MODE_OUTPUT;
359  }
360  else
361  {
362  // Reset corresponding OTYPER bit
363  otyper &= ~bc_gpio_16_bit_mask[channel];
364  }
365 
366  // If mode setting is alternative function ...
367  if((mode & _BC_GPIO_MODE_MASK) == BC_GPIO_MODE_ALTERNATE)
368  {
369  // ... write AF number to appropriate pin of appropriate AFR register
370  if(_bc_gpio_16_bit_pos[channel] >= 8)
371  {
372  bc_gpio_port[channel]->AFR[1] |= ((uint8_t)mode >> _BC_GPIO_MODE_AF_POS) << (_bc_gpio_64_bit_pos(channel) - 32);
373  }
374  else
375  {
376  bc_gpio_port[channel]->AFR[0] |= ((uint8_t)mode >> _BC_GPIO_MODE_AF_POS) << _bc_gpio_64_bit_pos(channel);
377  }
378 
379  // Mask AF number (mode is used as a coordinates in the array below ...)
380  mode &= _BC_GPIO_MODE_MASK;
381  }
382 
383  // Reset corresponding MODER bits
384  moder &= ~_bc_gpio_32_bit_mask[3][channel];
385 
386  // Set corresponding MODER bits
387  moder |= _bc_gpio_32_bit_mask[mode][channel];
388 
389  // Write OTYPER register
390  bc_gpio_port[channel]->OTYPER = otyper;
391 
392  // Write MODER register
393  bc_gpio_port[channel]->MODER = moder;
394 
395  // Enable interrupts
396  bc_irq_enable();
397 }
398 
400 {
401  // Read mode setting from MODER register
402  bc_gpio_mode_t mode = (bc_gpio_mode_t) ((bc_gpio_port[channel]->MODER >> _bc_gpio_32_bit_pos[channel]) & 3);
403 
404  // If mode setting is output...
405  if (mode == BC_GPIO_MODE_OUTPUT)
406  {
407  // If TYPER register bit indicates open-drain output...
408  if (((bc_gpio_port[channel]->OTYPER >> _bc_gpio_16_bit_pos[channel]) & 1) != 0)
409  {
410  // Override mode setting to open-drain
411  mode = BC_GPIO_MODE_OUTPUT_OD;
412  }
413  }
414 
415  // If mode setting is alternative function ...
416  else if (mode == BC_GPIO_MODE_ALTERNATE)
417  {
418  // Readout AF number from appropriate AFR
419  if(_bc_gpio_16_bit_pos[channel] >= 8)
420  {
421  mode = (bc_gpio_port[channel]->AFR[1] >> (_bc_gpio_64_bit_pos(channel) - 32)) & 0x0f;
422  }
423  else
424  {
425  mode = (bc_gpio_port[channel]->AFR[0] >> _bc_gpio_64_bit_pos(channel)) & 0x0f;
426  }
427 
428  // Insert number to enumeration
429  mode = (mode << _BC_GPIO_MODE_AF_POS) | BC_GPIO_MODE_ALTERNATE;
430  }
431 
432  // Return mode setting
433  return mode;
434 }
435 
437 {
438  // Return GPIO state from IDR register
439  return (bc_gpio_port[channel]->IDR & bc_gpio_16_bit_mask[channel]) != 0 ? 1 : 0;
440 }
441 
442 void bc_gpio_set_output(bc_gpio_channel_t channel, int state)
443 {
444  // Write GPIO state to BSRR register
445  bc_gpio_port[channel]->BSRR = state ? bc_gpio_16_bit_mask[channel] : bc_gpio_32_bit_upper_mask[channel];
446 }
447 
449 {
450  // Return GPIO state from ODR register
451  return (bc_gpio_port[channel]->ODR & bc_gpio_16_bit_mask[channel]) != 0 ? 1 : 0;
452 }
453 
455 {
456  // Disable interrupts
457  bc_irq_disable();
458 
459  // Write ODR register with inverted bit
460  bc_gpio_port[channel]->ODR ^= bc_gpio_16_bit_mask[channel];
461 
462  // Enable interrupts
463  bc_irq_enable();
464 }
void bc_irq_enable(void)
Enable interrupt requests globally (call can be nested)
Definition: bc_irq.c:21
int bc_gpio_get_output(bc_gpio_channel_t channel)
Get output state for GPIO channel.
Definition: bc_gpio.c:448
void bc_gpio_set_output(bc_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: bc_gpio.c:442
bc_gpio_mode_t bc_gpio_get_mode(bc_gpio_channel_t channel)
Get mode of operation for GPIO channel.
Definition: bc_gpio.c:399
bc_gpio_pull_t bc_gpio_get_pull(bc_gpio_channel_t channel)
Get pull-up/pull-down configuration for GPIO channel.
Definition: bc_gpio.c:334
void bc_gpio_set_mode(bc_gpio_channel_t channel, bc_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: bc_gpio.c:340
void bc_gpio_set_pull(bc_gpio_channel_t channel, bc_gpio_pull_t pull)
Set pull-up/pull-down configuration for GPIO channel.
Definition: bc_gpio.c:313
bc_gpio_pull_t
GPIO pull-up/pull-down setting.
Definition: bc_gpio.h:81
int bc_gpio_get_input(bc_gpio_channel_t channel)
Get input state for GPIO channel.
Definition: bc_gpio.c:436
void bc_gpio_toggle_output(bc_gpio_channel_t channel)
Toggle output state for GPIO channel.
Definition: bc_gpio.c:454
bc_gpio_channel_t
GPIO channels.
Definition: bc_gpio.h:12
GPIO channel operates in alternate mode.
Definition: bc_gpio.h:105
void bc_irq_disable(void)
Disable interrupt requests globally (call can be nested)
Definition: bc_irq.c:7
GPIO channel operates as open-drain output.
Definition: bc_gpio.h:111
void bc_gpio_init(bc_gpio_channel_t channel)
Initialize GPIO channel.
Definition: bc_gpio.c:301
GPIO channel operates as output.
Definition: bc_gpio.h:102
bc_gpio_mode_t
GPIO mode of operation.
Definition: bc_gpio.h:96