Embedded System Design 2 - Project
interrupt.c
Go to the documentation of this file.
1 /***************************************************************************//**
2  * @file interrupt.c
3  * @brief Interrupt functionality.
4  * @version 3.1
5  * @author Brecht Van Eeckhoudt
6  *
7  * ******************************************************************************
8  *
9  * @section Versions
10  *
11  * @li v1.0: Started from https://github.com/Fescron/Project-LabEmbeddedDesign1
12  * @li v1.1: Added dbprintln(""); above dbinfo statements in IRQ handlers to fix
13  * overwriting of text.
14  * @li v1.2: Disabled the RTC counter if GPIO handlers are called, only added necessary includes
15  * in header file, moved the others to the source file, updated documentation.
16  * @li v1.3: Started using set method for the static variable `ADXL_triggered`, added GPIO
17  * wakeup initialization method here, renamed file.
18  * @li v1.4: Stopped disabling the GPIO clock.
19  * @li v1.5: Started using getters/setters to indicate an interrupt to `main.c`.
20  * @li v1.6: Moved IRQ handler of RTC to this `delay.c`.
21  * @li v1.7: Updated clear pending interrupt logic.
22  * @li v1.8: Updated code with new DEFINE checks.
23  * @li v1.9: Removed error calls for "unknown" pins and added flag check for custom Happy Gecko board pinout.
24  * @li v2.0: Stopped disabling the RTC counter on pin interrupts.
25  * @li v2.1: Disabled the RTC counter on a button push because it confused delays called in LoRaWAN code.
26  * @li v2.2: Changed error numbering.
27  * @li v3.0: Updated version number.
28  * @li v3.1: Removed `static` before the local variables (not necessary).
29  *
30  * ******************************************************************************
31  *
32  * @note
33  * Other interrupt handlers can be found in `delay.c` and `adc.c`.
34  *
35  * ******************************************************************************
36  *
37  * @section License
38  *
39  * **Copyright (C) 2019 - Brecht Van Eeckhoudt**
40  *
41  * This program is free software: you can redistribute it and/or modify
42  * it under the terms of the **GNU General Public License** as published by
43  * the Free Software Foundation, either **version 3** of the License, or
44  * (at your option) any later version.
45  *
46  * This program is distributed in the hope that it will be useful,
47  * but WITHOUT ANY WARRANTY; without even the implied warranty of
48  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49  * GNU General Public License for more details.
50  *
51  * *A copy of the GNU General Public License can be found in the `LICENSE`
52  * file along with this source code.*
53  *
54  * @n
55  *
56  * Some methods use code obtained from examples from [Silicon Labs' GitHub](https://github.com/SiliconLabs/peripheral_examples).
57  * These sections are licensed under the Silabs License Agreement. See the file
58  * "Silabs_License_Agreement.txt" for details. Before using this software for
59  * any purpose, you must agree to the terms of that agreement.
60  *
61  ******************************************************************************/
62 
63 
64 #include <stdint.h> /* (u)intXX_t */
65 #include <stdbool.h> /* "bool", "true", "false" */
66 #include "em_device.h" /* Include necessary MCU-specific header file */
67 #include "em_cmu.h" /* Clock management unit */
68 #include "em_gpio.h" /* General Purpose IO */
69 #include "em_rtc.h" /* Real Time Counter (RTC) */
70 
71 #include "interrupt.h" /* Corresponding header file */
72 #include "pin_mapping.h" /* PORT and PIN definitions */
73 #include "debug_dbprint.h" /* Enable or disable printing to UART */
74 #include "util.h" /* Utility functionality */
75 #include "ADXL362.h" /* Functions related to the accelerometer */
76 
77 
78 /* Local variables */
79 volatile bool PB0_triggered = false; /* Volatile because it's modified by an interrupt service routine */
80 volatile bool PB1_triggered = false; /* Volatile because it's modified by an interrupt service routine */
81 
82 
83 /**************************************************************************//**
84  * @brief
85  * Initialize GPIO wake-up functionality.
86  *
87  * @details
88  * Initialize buttons `PB0` and `PB1` on falling-edge interrupts and
89  * `ADXL_INT1` on rising-edge interrupts.
90  *****************************************************************************/
91 void initGPIOwakeup (void)
92 {
93  /* Enable necessary clocks (just in case) */
94  CMU_ClockEnable(cmuClock_HFPER, true); /* GPIO is a High Frequency Peripheral */
95  CMU_ClockEnable(cmuClock_GPIO, true);
96 
97  /* Configure PB0 and PB1 as input with glitch filter enabled, last argument sets pull direction */
98  GPIO_PinModeSet(PB0_PORT, PB0_PIN, gpioModeInputPullFilter, 1);
99  GPIO_PinModeSet(PB1_PORT, PB1_PIN, gpioModeInputPullFilter, 1);
100 
101  /* Configure ADXL_INT1 as input, the last argument enables the filter */
102  GPIO_PinModeSet(ADXL_INT1_PORT, ADXL_INT1_PIN, gpioModeInput, 1);
103 
104  /* Clear all odd pin interrupt flags (just in case)
105  * NVIC_ClearPendingIRQ(GPIO_ODD_IRQn); would also work but is less "readable" */
106  GPIO_IntClear(0xAAAA);
107 
108  /* Clear all even pin interrupt flags (just in case)
109  * NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn); would also work but is less "readable" */
110  GPIO_IntClear(0x5555);
111 
112  /* All pending interrupts can be cleared with GPIO_IntClear(0xFFFF); */
113 
114  /* Enable IRQ for even numbered GPIO pins */
115  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
116 
117  /* Enable IRQ for odd numbered GPIO pins */
118  NVIC_EnableIRQ(GPIO_ODD_IRQn);
119 
120  /* Enable falling-edge interrupts for PB pins */
121  GPIO_ExtIntConfig(PB0_PORT, PB0_PIN, PB0_PIN, false, true, true);
122  GPIO_ExtIntConfig(PB1_PORT, PB1_PIN, PB1_PIN, false, true, true);
123 
124  /* Enable rising-edge interrupts for ADXL_INT1 */
125  GPIO_ExtIntConfig(ADXL_INT1_PORT, ADXL_INT1_PIN, ADXL_INT1_PIN, true, false, true);
126 
127 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
128  dbinfo("GPIO wake-up initialized");
129 #endif /* DEBUG_DBPRINT */
130 
131 }
132 
133 
134 /**************************************************************************//**
135  * @brief
136  * Getter for the `PB0_triggered` and `PB1_triggered` variables.
137  *
138  * @param[in] number
139  * @li `0` - `PB0_triggered` selected.
140  * @li `1` - `PB1_triggered` selected.
141  *
142  * @return
143  * The value of `PB0_triggered` or `PB1_triggered`.
144  *****************************************************************************/
145 bool BTN_getTriggered (uint8_t number)
146 {
147  if (number == 0) return (PB0_triggered);
148  else if (number == 1) return (PB1_triggered);
149  else
150  {
151 
152 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
153  dbcrit("Non-existing button selected!");
154 #endif /* DEBUG_DBPRINT */
155 
156  error(18);
157 
158  return (false);
159  }
160 }
161 
162 
163 /**************************************************************************//**
164  * @brief
165  * Setter for the `PB0_triggered` and `PB1_triggered` variable.
166  *
167  * @param[in] number
168  * @li `0` - `PB0_triggered selected`.
169  * @li `1` - `PB1_triggered selected`.
170  *
171  * @param[in] value
172  * The boolean value to set to the selected variable.
173  *****************************************************************************/
174 void BTN_setTriggered (uint8_t number, bool value)
175 {
176  if (number == 0) PB0_triggered = value;
177  else if (number == 1) PB1_triggered = value;
178  else
179  {
180 
181 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
182  dbcrit("Non-existing button selected!");
183 #endif /* DEBUG_DBPRINT */
184 
185  error(19);
186  }
187 }
188 
189 
190 /**************************************************************************//**
191  * @brief
192  * GPIO Even IRQ for pushbuttons on even-numbered pins.
193  *
194  * @details
195  * The RTC is also disabled on a button press (*manual wake-up*)
196  *
197  * @note
198  * The *weak* definition for this method is located in `system_efm32hg.h`.
199  *****************************************************************************/
201 {
202  /* Read interrupt flags */
203  uint32_t flags = GPIO_IntGet();
204 
205  /* Check if PB1 is pushed */
206  if (flags == 0x400)
207  {
208  /* Disable the counter (manual wakeup) */
209  RTC_Enable(false);
210 
211  PB1_triggered = true;
212  }
213 
214  /* Clear all even pin interrupt flags */
215  GPIO_IntClear(0x5555);
216 }
217 
218 
219 /**************************************************************************//**
220  * @brief
221  * GPIO Odd IRQ for pushbuttons on odd-numbered pins.
222  *
223  * @details
224  * The RTC is also disabled on a button press (*manual wakeup*).
225  *
226  * @note
227  * The *weak* definition for this method is located in `system_efm32hg.h`.
228  *****************************************************************************/
230 {
231  /* Read interrupt flags */
232  uint32_t flags = GPIO_IntGet();
233 
234  /* Check if PB0 is pushed */
235  if (flags == 0x200)
236  {
237  /* Disable the counter (manual wake-up) */
238  RTC_Enable(false);
239 
240  PB0_triggered = true;
241  }
242 
243  /* Check if INT1 is triggered */
244 #if CUSTOM_BOARD == 1 /* Custom Happy Gecko pinout */
245  if (flags == 0x8) ADXL_setTriggered(true);
246 #else /* Regular Happy Gecko pinout */
247  if (flags == 0x80) ADXL_setTriggered(true);
248 #endif /* Board pinout selection */
249 
250  /* Clear all odd pin interrupt flags */
251  GPIO_IntClear(0xAAAA);
252 }
volatile bool PB0_triggered
Definition: interrupt.c:79
void BTN_setTriggered(uint8_t number, bool value)
Setter for the PB0_triggered and PB1_triggered variable.
Definition: interrupt.c:174
void GPIO_ODD_IRQHandler(void)
GPIO Odd IRQ for pushbuttons on odd-numbered pins.
Definition: interrupt.c:229
All code for the ADXL362 accelerometer.
#define ADXL_INT1_PORT
Definition: pin_mapping.h:77
#define PB0_PIN
Definition: pin_mapping.h:90
void dbinfo(char *message)
Print an info string (char array) to USARTx and go to the next line.
Definition: dbprint.c:503
volatile bool PB1_triggered
Definition: interrupt.c:80
void ADXL_setTriggered(bool triggered)
Setter for the ADXL_triggered variable.
Definition: ADXL362.c:202
void initGPIOwakeup(void)
Initialize GPIO wake-up functionality.
Definition: interrupt.c:91
void error(uint8_t number)
Error method.
Definition: util.c:131
void GPIO_EVEN_IRQHandler(void)
GPIO Even IRQ for pushbuttons on even-numbered pins.
Definition: interrupt.c:200
Utility functionality.
#define PB1_PORT
Definition: pin_mapping.h:91
The pin definitions for the regular and custom Happy Gecko board.
Interrupt functionality.
#define PB0_PORT
Definition: pin_mapping.h:89
Enable or disable printing to UART with dbprint.
#define PB1_PIN
Definition: pin_mapping.h:92
void dbcrit(char *message)
Print a critical error string (char array) in red to USARTx and go to the next line.
Definition: dbprint.c:539
bool BTN_getTriggered(uint8_t number)
Getter for the PB0_triggered and PB1_triggered variables.
Definition: interrupt.c:145
#define ADXL_INT1_PIN
Definition: pin_mapping.h:78