GlobLib
HAL and API libraries for MCUs and hardware.
stm32f103cb_gpio.c
Go to the documentation of this file.
1 
17 #include "stm32f103cb_gpio.h"
18 
19 #define PORTA_EXTICR 0x0
20 #define PORTB_EXTICR 0x1
21 #define PORTC_EXTICR 0x2
22 
23 static void ( *pin0_handler)(void);
24 static void ( *pin1_handler)(void);
25 static void ( *pin2_handler)(void);
26 static void ( *pin3_handler)(void);
27 static void ( *pin4_handler)(void);
28 static void ( *pin5_handler)(void);
29 static void ( *pin6_handler)(void);
30 static void ( *pin7_handler)(void);
31 static void ( *pin8_handler)(void);
32 static void ( *pin9_handler)(void);
33 static void ( *pin10_handler)(void);
34 static void ( *pin11_handler)(void);
35 static void ( *pin12_handler)(void);
36 static void ( *pin13_handler)(void);
37 static void ( *pin14_handler)(void);
38 static void ( *pin15_handler)(void);
39 
40 static mcu_error gpio_setEXTIPortMask(gpio_pin pin, uint8_t mask, void (*handle)(void));
41 static uint8_t gpio_translatePin(gpio_pin pin);
42 
43 //Initialize a port's pin to a function defined by macro definitions passed in as mode
45 {
46  //Determine the pin offset from the actual pin
47  uint8_t correspontingPin = gpio_translatePin(pin);
48 
49 
50  //Enable corresponding clock
51  switch(port)
52  {
53 
54  case PORTA:
55  rcc_periph_clock_enable(RCC_GPIOA);
56  break;
57 
58  case PORTB:
59  rcc_periph_clock_enable(RCC_GPIOB);
60  break;
61 
62  case PORTC:
63  rcc_periph_clock_enable(RCC_GPIOC);
64  break;
65  default:
66 
67  if(MCU_debugIsEnabled()){
68 
70  }
71  return E_GPIO_PIN;
72  break;
73 
74  }
75 
76  //STM32f1 has two function registers. Higher pin numbers need to be shifted down. (P170 Reference manual)
77  if(correspontingPin > 0x07){
78 
79  (*((volatile unsigned long *)(GPIO_BASE+port+CRH_OFFSET))) |= (mode<<((correspontingPin-0x08)<<2));
80  (*((volatile unsigned long *)(GPIO_BASE+port+CRH_OFFSET))) &= ~((mode^0xF)<<((correspontingPin-0x08)<<2));
81  }
82  else{
83  (*((volatile unsigned long *)(GPIO_BASE+port+CRL_OFFSET))) |= (mode<<(correspontingPin<<2));
84  (*((volatile unsigned long *)(GPIO_BASE+port+CRL_OFFSET))) &= ~((mode^0xF)<<(correspontingPin<<2));
85  }
86  return E_GPIO_NOERROR;
87 
88 }
89 
90 //Set a corresponing port's pin high
91 void pinHigh(gpio_port port, gpio_pin pin){
92 
93  (*((volatile unsigned long *)(GPIO_BASE+port+BSRR_OFFSET))) |= pin;
94 }
95 
96 //Set a corresponding port's pin low
97 void pinLow(gpio_port port, gpio_pin pin){
98 
99  (*((volatile unsigned long *)(GPIO_BASE+port+BRR_OFFSET))) |= pin;
100 }
101 
102 //Set a corresponding port's pin to a given state (defined as macro definition)
103 void pinWrite(gpio_port port, gpio_pin pin, gpio_state state)
104 {
105  if(state)
106  {
107  pinLow(port,pin);
108  }
109  else
110  {
111  pinHigh(port,pin);
112  }
113 }
114 
115 //Toggle a given port's pin
116 void pinToggle(gpio_port port, gpio_pin pin){
117 
118  pinWrite(port,pin,pinRead(port,pin));
119 
120 }
121 
122 //Read the input state of a port's pin.
123 uint8_t pinRead(gpio_port port, gpio_pin pin){
124 
125  if(*((volatile unsigned long *)((GPIO_BASE+port+IDR_OFFSET))) & pin){
126  return 1;
127  }
128  else{
129  return 0;
130  }
131 }
132 
133 mcu_error GPIO_ISREnable(gpio_port port, gpio_pin pin, gpio_isr trigger, void (*handle)(void)){
134 
135 
136  //Need to enable clock first
137  rcc_periph_clock_enable(RCC_AFIO);
138 
139  uint8_t correspondingPin = gpio_translatePin(pin);
140 
141  //Check to make sure pin is available
142  if((EXTI_IMR & pin)){
143 
144  if(MCU_debugIsEnabled()){
145 
147  }
148  return E_GPIO_ISR;
149  }
150 
151  //Setup the pin
152  pinSetup(GPIO_DI,port,pin);
153 
154  //Configure the EXTI line to be mapped to that port
155  switch(port){
156 
157  case PORTA:
158 
159  gpio_setEXTIPortMask(pin, PORTA_EXTICR, handle);
160  break;
161 
162  case PORTB:
163 
164  gpio_setEXTIPortMask(pin, PORTB_EXTICR, handle);
165  break;
166 
167  case PORTC:
168 
169  gpio_setEXTIPortMask(pin, PORTC_EXTICR, handle);
170  break;
171 
172  default:
173 
174  if(MCU_debugIsEnabled()){
175 
177  }
178  return E_GPIO_PORT;
179  break;
180  }
181 
182  //Set the mask to let interrupts through
183  exti_enable_request(pin);
184 
185  //Set rising or falling
186  if((trigger == GPIO_RISING)){
187 
188  exti_set_trigger(pin,EXTI_TRIGGER_RISING);
189 
190  }
191 
192  else if((trigger == GPIO_FALLING)){
193 
194  exti_set_trigger(pin,EXTI_TRIGGER_FALLING);
195 
196  }
197 
198  else if (trigger == GPIO_BOTH){
199 
200  exti_set_trigger(pin,EXTI_TRIGGER_BOTH);
201  }
202  else{
203 
204  if(MCU_debugIsEnabled()){
205 
207  }
208  return E_GPIO_TRIGGER;
209  }
210 
211 
212  //Enable interrupts
213 
214  if(correspondingPin == 0){
215 
216  nvic_enable_irq(NVIC_EXTI0_IRQ);
217  }
218  else if(correspondingPin == 1){
219 
220  nvic_enable_irq(NVIC_EXTI1_IRQ);
221  }
222  else if(correspondingPin == 2){
223 
224  nvic_enable_irq(NVIC_EXTI2_IRQ);
225  }
226  else if(correspondingPin == 3){
227 
228  nvic_enable_irq(NVIC_EXTI3_IRQ);
229  }
230  else if(correspondingPin == 4){
231 
232  nvic_enable_irq(NVIC_EXTI4_IRQ);
233  }
234  else if(correspondingPin <= 9){
235 
236  nvic_enable_irq(NVIC_EXTI9_5_IRQ);
237  }
238  else if(correspondingPin <= 15){
239  nvic_enable_irq(NVIC_EXTI15_10_IRQ);
240 
241  }
242  else{
243 
244  if(MCU_debugIsEnabled()){
245 
247  }
248  return E_GPIO_PIN;
249  }
250 
251  return E_GPIO_NOERROR;
252 
253 }
254 
255 //Sets the correct external interrupt configuration register for the given pin
256 //Page 190 Reference manual
257 static mcu_error gpio_setEXTIPortMask(gpio_pin pin, uint8_t mask, void (*handle)(void)){
258 
259  switch(pin){
260 
261  case PIN0:
262 
263  AFIO_EXTICR(0) &= ~(0xF);
264  AFIO_EXTICR(0) |= (mask);
265  pin0_handler = handle;
266  break;
267 
268  case PIN1:
269 
270  AFIO_EXTICR(0) &= ~(0xF<<4);
271  AFIO_EXTICR(0) |= (mask << 0x4);
272  pin1_handler = handle;
273  break;
274 
275  case PIN2:
276 
277  AFIO_EXTICR(0) &= ~(0xF<<8);
278  AFIO_EXTICR(0) |= (mask << 0x8);
279  pin2_handler = handle;
280  break;
281 
282  case PIN3:
283 
284  AFIO_EXTICR(0) &= ~(0xF<<12);
285  AFIO_EXTICR(0) |= (mask << 0xC);
286  pin3_handler = handle;
287  break;
288 
289  case PIN4:
290 
291  AFIO_EXTICR(1) &= ~(0xF);
292  AFIO_EXTICR(1) |= (mask);
293  pin4_handler = handle;
294  break;
295 
296  case PIN5:
297 
298  AFIO_EXTICR(1) &= ~(0xF<<4);
299  AFIO_EXTICR(1) |= (mask << 0x4);
300  pin5_handler = handle;
301  break;
302 
303  case PIN6:
304 
305  AFIO_EXTICR(1) &= ~(0xF<<8);
306  AFIO_EXTICR(1) |= (mask << 0x8);
307  pin6_handler = handle;
308  break;
309 
310  case PIN7:
311 
312  AFIO_EXTICR(1) &= ~(0xF<<12);
313  AFIO_EXTICR(1) |= (mask << 0xC);
314  pin7_handler = handle;
315  break;
316 
317  case PIN8:
318 
319  AFIO_EXTICR(2) &= ~(0xF);
320  AFIO_EXTICR(2) |= (mask);
321  pin8_handler = handle;
322  break;
323 
324  case PIN9:
325 
326  AFIO_EXTICR(2) &= ~(0xF<<4);
327  AFIO_EXTICR(2) |= (mask << 0x4);
328  pin9_handler = handle;
329  break;
330 
331  case PIN10:
332 
333  AFIO_EXTICR(2) &= ~(0xF<<8);
334  AFIO_EXTICR(2) |= (mask << 0x8);
335  pin10_handler = handle;
336  break;
337 
338  case PIN11:
339 
340  AFIO_EXTICR(2) &= ~(0xF<<12);
341  AFIO_EXTICR(2) |= (mask << 0xC);
342  pin11_handler = handle;
343  break;
344 
345  case PIN12:
346 
347  AFIO_EXTICR(3) &= ~(0xF);
348  AFIO_EXTICR(3) |= (mask);
349  pin12_handler = handle;
350  break;
351 
352  case PIN13:
353 
354  AFIO_EXTICR(3) &= ~(0xF<<4);
355  AFIO_EXTICR(3) |= (mask << 0x4);
356  pin13_handler = handle;
357  break;
358 
359  case PIN14:
360 
361  AFIO_EXTICR(3) &= ~(0xF<<8);
362  AFIO_EXTICR(3) |= (mask << 0x8);
363  pin14_handler = handle;
364  break;
365 
366  case PIN15:
367  AFIO_EXTICR(3) &= ~(0xF<<12);
368  AFIO_EXTICR(3) |= (mask << 0xC);
369  pin15_handler = handle;
370  break;
371 
372  default:
373 
374  if(MCU_debugIsEnabled()){
375 
377  }
378  return E_GPIO_PIN;
379  break;
380 
381  }
382 
383  return E_GPIO_NOERROR;
384 
385 }
386 void exti0_isr(void){
387 
388  exti_reset_request(EXTI0);
389  pin0_handler();
390 }
391 
392 void exti1_isr(void){
393 
394  exti_reset_request(EXTI1);
395  pin1_handler();
396 }
397 
398 void exti2_isr(void){
399 
400  exti_reset_request(EXTI2);
401  pin2_handler();
402 }
403 
404 void exti3_isr(void){
405 
406  exti_reset_request(EXTI3);
407  pin3_handler();
408 }
409 
410 void exti4_isr(void){
411 
412  exti_reset_request(EXTI4);
413  pin4_handler();
414 }
415 
416 void exti9_5_isr(void){
417 
418 
419  //Pin 5 interrupt
420  if((EXTI_PR & PIN5) != 0){
421 
422  exti_reset_request(EXTI5);
423  pin5_handler();
424  }
425  if((EXTI_PR & PIN6) != 0){
426 
427  exti_reset_request(EXTI6);
428  pin6_handler();
429  }
430  if((EXTI_PR & PIN7) != 0){
431 
432  exti_reset_request(EXTI7);
433  pin7_handler();
434  }
435  if((EXTI_PR & PIN8) != 0){
436 
437  exti_reset_request(EXTI8);
438  pin8_handler();
439  }
440  if((EXTI_PR & PIN9) != 0){
441 
442  exti_reset_request(EXTI9);
443  pin9_handler();
444  }
445 
446 }
447 
448 void exti15_10_isr(void){
449 
450  if((EXTI_PR & PIN10) != 0){
451 
452  exti_reset_request(EXTI10);
453  pin10_handler();
454  }
455 
456  if((EXTI_PR & PIN11) != 0){
457 
458  exti_reset_request(EXTI11);
459  pin11_handler();
460  }
461  if((EXTI_PR & PIN12) != 0){
462 
463  exti_reset_request(EXTI12);
464  pin12_handler();
465  }
466  if((EXTI_PR & PIN13) != 0){
467 
468  exti_reset_request(EXTI13);
469  pin13_handler();
470  }
471  if((EXTI_PR & PIN14) != 0){
472 
473  exti_reset_request(EXTI14);
474  pin14_handler();
475  }
476  if((EXTI_PR & PIN15) != 0){
477 
478  exti_reset_request(EXTI15);
479  pin15_handler();
480  }
481 
482 }
483 
485 
486  uint8_t correspondingPin = gpio_translatePin(pin);
487 
488  //Disable NVIC
489  if(correspondingPin == 0){
490 
491  nvic_enable_irq(NVIC_EXTI0_IRQ);
492  }
493  else if(correspondingPin == 1){
494 
495  nvic_enable_irq(NVIC_EXTI1_IRQ);
496  }
497  else if(correspondingPin == 2){
498 
499  nvic_enable_irq(NVIC_EXTI2_IRQ);
500  }
501  else if(correspondingPin == 3){
502 
503  nvic_enable_irq(NVIC_EXTI3_IRQ);
504  }
505  else if(correspondingPin == 4){
506 
507  nvic_enable_irq(NVIC_EXTI4_IRQ);
508  }
509  else if(correspondingPin <= 9){
510 
511  nvic_enable_irq(NVIC_EXTI9_5_IRQ);
512  }
513  else if(correspondingPin <= 15){
514  nvic_enable_irq(NVIC_EXTI15_10_IRQ);
515 
516  }
517  else{
518 
519  if(MCU_debugIsEnabled()){
520 
522  }
523  return E_GPIO_PIN;
524  }
525 
526  //Disable Mask
527  exti_disable_request(pin);
528  return E_GPIO_NOERROR;
529 }
530 
531 static uint8_t gpio_translatePin(gpio_pin pin){
532 
533  uint8_t correspontingPin;
534 
535  switch(pin){
536 
537  case PIN0:
538  correspontingPin = 0x00;
539  break;
540 
541  case PIN1:
542  correspontingPin = 0x01;
543  break;
544 
545  case PIN2:
546  correspontingPin = 0x02;
547  break;
548 
549  case PIN3:
550  correspontingPin = 0x03;
551  break;
552 
553  case PIN4:
554  correspontingPin = 0x04;
555  break;
556 
557  case PIN5:
558  correspontingPin = 0x05;
559  break;
560 
561  case PIN6:
562  correspontingPin = 0x06;
563  break;
564 
565  case PIN7:
566  correspontingPin = 0x07;
567  break;
568 
569  case PIN8:
570  correspontingPin = 0x08;
571  break;
572 
573  case PIN9:
574  correspontingPin = 0x09;
575  break;
576 
577  case PIN10:
578  correspontingPin = 0x0A;
579  break;
580 
581  case PIN11:
582  correspontingPin = 0x0B;
583  break;
584 
585  case PIN12:
586  correspontingPin = 0x0C;
587  break;
588 
589  case PIN13:
590  correspontingPin = 0x0D;
591  break;
592 
593  case PIN14:
594  correspontingPin = 0x0E;
595  break;
596 
597  case PIN15:
598  correspontingPin = 0x0F;
599  break;
600 
601  default:
602  correspontingPin = 0;
603  break;
604  }
605 
606  return correspontingPin;
607 }
608 
Pin 3 of the port.
Pin 9 of the port.
gpio_port
GPIO ports available for the MCU.
Header file for stm32f103 GPIO.
void pinToggle(gpio_port port, gpio_pin pin)
Toggle the output of a given pin on a port.
void pinLow(gpio_port port, gpio_pin pin)
Set a given gpio pin on a port to logic low.
gpio_state
GPIO pin states.
ERROR GPIO: Port doesn&#39;t exist.
Pin 4 of the port.
void MCU_printError(mcu_error errorNum)
Print a given error number as a character stream.
Control register low memory offset.
Pin 1 of the port.
Base memory address for GPIO peripheral.
uint8_t MCU_debugIsEnabled(void)
Checks if debug is enabled.
mcu_error GPIO_ISRDisable(gpio_pin pin)
Disable interrupts on a gpio port / pin.
ERROR GPIO: Pin doesn&#39;t exist.
Port bit set/reset register.
void pinHigh(gpio_port port, gpio_pin pin)
Set a given gpio pin on a port to logic high.
ERROR GPIO: ISR EXTI line in use.
Pin 0 of the port.
Setup the port for digital input.
Pin 2 of the port.
Interrupt occurs on falling edge detection.
gpio_pin
GPIO pins available for each port.
Pin 13 of the port.
Pin 7 of the port.
Interrupt occurs on rising edge detection.
Interrupt occurs on rising and falling edge detection.
Pin 8 of the port.
Pin 6 of the port.
Port B of the MCU.
gpio_isr
GPIO interrupt options for pins.
Pin 15 of the port.
ERROR GPIO: ISR trigger doesn&#39;t exist.
mcu_error pinSetup(gpio_mode mode, gpio_port port, gpio_pin pin)
Setup a GPIO pin for a given function.
void pinWrite(gpio_port port, gpio_pin pin, gpio_state state)
Set a given gpio pin on a port to a logic state.
Pin 11 of the port.
Pin 5 of the port.
uint8_t pinRead(gpio_port port, gpio_pin pin)
Read the current digital value of an input pin.
Pin 14 of the port.
Port bit reset register.
Pin 10 of the port.
ERROR GPIO: No Error.
mcu_error GPIO_ISREnable(gpio_port port, gpio_pin pin, gpio_isr trigger, void(*handle)(void))
Setup interrupts on a gpio port / pin.
Port C of the MCU.
gpio_mode
GPIO setup options.
Port A of the MCU.
Port input data register.
Pin 12 of the port.
mcu_error
Error enumerators for the Debug peripheral.
Control register high memory offset.