]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SiLabs_Source/emlib/em_gpio.c
Replace Gecko Simplicity Studio project that had multiple build configurations with...
[freertos] / FreeRTOS / Demo / CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio / SiLabs_Source / emlib / em_gpio.c
1 /***************************************************************************//**\r
2  * @file em_gpio.c\r
3  * @brief General Purpose IO (GPIO) peripheral API\r
4  *   devices.\r
5  * @version 4.2.1\r
6  *******************************************************************************\r
7  * @section License\r
8  * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
9  *******************************************************************************\r
10  *\r
11  * Permission is granted to anyone to use this software for any purpose,\r
12  * including commercial applications, and to alter it and redistribute it\r
13  * freely, subject to the following restrictions:\r
14  *\r
15  * 1. The origin of this software must not be misrepresented; you must not\r
16  *    claim that you wrote the original software.\r
17  * 2. Altered source versions must be plainly marked as such, and must not be\r
18  *    misrepresented as being the original software.\r
19  * 3. This notice may not be removed or altered from any source distribution.\r
20  *\r
21  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
22  * obligation to support this Software. Silicon Labs is providing the\r
23  * Software "AS IS", with no express or implied warranties of any kind,\r
24  * including, but not limited to, any implied warranties of merchantability\r
25  * or fitness for any particular purpose or warranties against infringement\r
26  * of any proprietary rights of a third party.\r
27  *\r
28  * Silicon Labs will not be liable for any consequential, incidental, or\r
29  * special damages, or any other relief, or for any claim by any third party,\r
30  * arising from your use of this Software.\r
31  *\r
32  ******************************************************************************/\r
33 \r
34 \r
35 #include "em_gpio.h"\r
36 \r
37 #if defined(GPIO_COUNT) && (GPIO_COUNT > 0)\r
38 \r
39 /***************************************************************************//**\r
40  * @addtogroup EM_Library\r
41  * @{\r
42  ******************************************************************************/\r
43 \r
44 /***************************************************************************//**\r
45  * @addtogroup GPIO\r
46  * @brief General Purpose Input/Output (GPIO) API\r
47  * @{\r
48  ******************************************************************************/\r
49 \r
50 /*******************************************************************************\r
51  *******************************   DEFINES   ***********************************\r
52  ******************************************************************************/\r
53 \r
54 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
55 \r
56 /** Validation of pin typically usable in assert statements. */\r
57 #define GPIO_DRIVEMODE_VALID(mode)    ((mode) <= 3)\r
58 #define GPIO_STRENGHT_VALID(strenght) (!((strenght) & \\r
59                                          ~(_GPIO_P_CTRL_DRIVESTRENGTH_MASK \\r
60                                            | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK)))\r
61 /** @endcond */\r
62 \r
63 \r
64 /*******************************************************************************\r
65  **************************   GLOBAL FUNCTIONS   *******************************\r
66  ******************************************************************************/\r
67 \r
68 /***************************************************************************//**\r
69  * @brief\r
70  *   Sets the pin location of the debug pins (Serial Wire interface).\r
71  *\r
72  * @note\r
73  *   Changing the pins used for debugging uncontrolled, may result in a lockout.\r
74  *\r
75  * @param[in] location\r
76  *   The debug pin location to use (0-3).\r
77  ******************************************************************************/\r
78 void GPIO_DbgLocationSet(unsigned int location)\r
79 {\r
80 #if defined ( _GPIO_ROUTE_SWLOCATION_MASK )\r
81   EFM_ASSERT(location < AFCHANLOC_MAX);\r
82 \r
83   GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) |\r
84                 (location << _GPIO_ROUTE_SWLOCATION_SHIFT);\r
85 #else\r
86   (void)location;\r
87 #endif\r
88 }\r
89 \r
90 #if defined (_GPIO_P_CTRL_DRIVEMODE_MASK)\r
91 /***************************************************************************//**\r
92  * @brief\r
93  *   Sets the drive mode for a GPIO port.\r
94  *\r
95  * @param[in] port\r
96  *   The GPIO port to access.\r
97  *\r
98  * @param[in] mode\r
99  *   Drive mode to use for port.\r
100  ******************************************************************************/\r
101 void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)\r
102 {\r
103   EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));\r
104 \r
105   GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))\r
106                        | (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);\r
107 }\r
108 #endif\r
109 \r
110 \r
111 #if defined (_GPIO_P_CTRL_DRIVESTRENGTH_MASK)\r
112 /***************************************************************************//**\r
113  * @brief\r
114  *   Sets the drive strength for a GPIO port.\r
115  *\r
116  * @param[in] port\r
117  *   The GPIO port to access.\r
118  *\r
119  * @param[in] strength\r
120  *   Drive strength to use for port.\r
121  ******************************************************************************/\r
122 void GPIO_DriveStrengthSet(GPIO_Port_TypeDef port,\r
123                            GPIO_DriveStrength_TypeDef strength)\r
124 {\r
125   EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_STRENGHT_VALID(strength));\r
126   BUS_RegMaskedWrite(&GPIO->P[port].CTRL,\r
127                      _GPIO_P_CTRL_DRIVESTRENGTH_MASK | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK,\r
128                      strength);\r
129 }\r
130 #endif\r
131 \r
132 /***************************************************************************//**\r
133  * @brief\r
134  *   Configure GPIO interrupt.\r
135  *\r
136  * @details\r
137  *   If reconfiguring a GPIO interrupt that is already enabled, it is generally\r
138  *   recommended to disable it first, see GPIO_Disable().\r
139  *\r
140  *   The actual GPIO interrupt handler must be in place before enabling the\r
141  *   interrupt.\r
142  *\r
143  *   Notice that any pending interrupt for the selected pin is cleared by this\r
144  *   function.\r
145  *\r
146  * @note\r
147  *   A certain pin number can only be associated with one port. Ie, if GPIO\r
148  *   interrupt 1 is assigned to port A/pin 1, then it is not possibly to use\r
149  *   pin 1 from any other ports for interrupts. Please refer to the reference\r
150  *   manual.\r
151  *\r
152  * @param[in] port\r
153  *   The port to associate with @p pin.\r
154  *\r
155  * @param[in] pin\r
156  *   The GPIO interrupt number (= port pin).\r
157  *\r
158  * @param[in] risingEdge\r
159  *   Set to true if interrupts shall be enabled on rising edge, otherwise false.\r
160  *\r
161  * @param[in] fallingEdge\r
162  *   Set to true if interrupts shall be enabled on falling edge, otherwise false.\r
163  *\r
164  * @param[in] enable\r
165  *   Set to true if interrupt shall be enabled after configuration completed,\r
166  *   false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().\r
167  ******************************************************************************/\r
168 void GPIO_IntConfig(GPIO_Port_TypeDef port,\r
169                     unsigned int pin,\r
170                     bool risingEdge,\r
171                     bool fallingEdge,\r
172                     bool enable)\r
173 {\r
174   uint32_t tmp;\r
175 \r
176   EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));\r
177 \r
178   /* There are two registers controlling the interrupt configuration:\r
179    * The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls\r
180    * pins 8-15. */\r
181   if (pin < 8)\r
182   {\r
183     BUS_RegMaskedWrite(&GPIO->EXTIPSELL,\r
184                        0xF << (4 * pin),\r
185                        port << (4 * pin));\r
186   }\r
187   else\r
188   {\r
189     tmp             = pin - 8;\r
190     BUS_RegMaskedWrite(&GPIO->EXTIPSELH,\r
191                        0xF << (4 * tmp),\r
192                        port << (4 * tmp));\r
193   }\r
194 \r
195   /* Enable/disable rising edge */\r
196   BUS_RegBitWrite(&(GPIO->EXTIRISE), pin, risingEdge);\r
197 \r
198   /* Enable/disable falling edge */\r
199   BUS_RegBitWrite(&(GPIO->EXTIFALL), pin, fallingEdge);\r
200 \r
201   /* Clear any pending interrupt */\r
202   GPIO->IFC = 1 << pin;\r
203 \r
204   /* Finally enable/disable interrupt */\r
205   BUS_RegBitWrite(&(GPIO->IEN), pin, enable);\r
206 }\r
207 \r
208 \r
209 /***************************************************************************//**\r
210  * @brief\r
211  *   Set the mode for a GPIO pin.\r
212  *\r
213  * @param[in] port\r
214  *   The GPIO port to access.\r
215  *\r
216  * @param[in] pin\r
217  *   The pin number in the port.\r
218  *\r
219  * @param[in] mode\r
220  *   The desired pin mode.\r
221  *\r
222  * @param[in] out\r
223  *   Value to set for pin in DOUT register. The DOUT setting is important for\r
224  *   even some input mode configurations, determining pull-up/down direction.\r
225  ******************************************************************************/\r
226 void GPIO_PinModeSet(GPIO_Port_TypeDef port,\r
227                      unsigned int pin,\r
228                      GPIO_Mode_TypeDef mode,\r
229                      unsigned int out)\r
230 {\r
231   EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));\r
232 \r
233   /* If disabling pin, do not modify DOUT in order to reduce chance for */\r
234   /* glitch/spike (may not be sufficient precaution in all use cases) */\r
235   if (mode != gpioModeDisabled)\r
236   {\r
237     if (out)\r
238     {\r
239       GPIO_PinOutSet(port, pin);\r
240     }\r
241     else\r
242     {\r
243       GPIO_PinOutClear(port, pin);\r
244     }\r
245   }\r
246 \r
247   /* There are two registers controlling the pins for each port. The MODEL\r
248    * register controls pins 0-7 and MODEH controls pins 8-15. */\r
249   if (pin < 8)\r
250   {\r
251     BUS_RegMaskedWrite(&GPIO->P[port].MODEL,\r
252                        0xF << (pin * 4),\r
253                        mode << (pin * 4));\r
254   }\r
255   else\r
256   {\r
257     BUS_RegMaskedWrite(&GPIO->P[port].MODEH,\r
258                        0xF << ((pin - 8) * 4),\r
259                        mode << ((pin - 8) * 4));\r
260   }\r
261 \r
262   if (mode == gpioModeDisabled)\r
263   {\r
264     if (out)\r
265     {\r
266       GPIO_PinOutSet(port, pin);\r
267     }\r
268     else\r
269     {\r
270       GPIO_PinOutClear(port, pin);\r
271     }\r
272   }\r
273 }\r
274 \r
275 #if defined( _GPIO_EM4WUEN_MASK )\r
276 /**************************************************************************//**\r
277  * @brief\r
278  *   Enable GPIO pin wake-up from EM4. When the function exits,\r
279  *   EM4 mode can be safely entered.\r
280  *\r
281  * @note\r
282  *   It is assumed that the GPIO pin modes are set correctly.\r
283  *   Valid modes are @ref gpioModeInput and @ref gpioModeInputPull.\r
284  *\r
285  * @param[in] pinmask\r
286  *   Bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.\r
287  *   Refer to Reference Manuals for pinmask to GPIO port/pin mapping.\r
288  * @param[in] polaritymask\r
289  *   Bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.\r
290  *   Refer to Reference Manuals for pinmask to GPIO port/pin mapping.\r
291  *****************************************************************************/\r
292 void GPIO_EM4EnablePinWakeup(uint32_t pinmask, uint32_t polaritymask)\r
293 {\r
294   EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);\r
295 \r
296 #if defined( _GPIO_EM4WUPOL_MASK )\r
297   EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);\r
298   GPIO->EM4WUPOL &= ~pinmask;               /* Set wakeup polarity */\r
299   GPIO->EM4WUPOL |= pinmask & polaritymask;\r
300 #elif defined( _GPIO_EXTILEVEL_MASK )\r
301   EFM_ASSERT((polaritymask & ~_GPIO_EXTILEVEL_MASK) == 0);\r
302   GPIO->EXTILEVEL &= ~pinmask;\r
303   GPIO->EXTILEVEL |= pinmask & polaritymask;\r
304 #endif\r
305   GPIO->EM4WUEN  |= pinmask;                /* Enable wakeup */\r
306 \r
307   GPIO_EM4SetPinRetention(true);            /* Enable pin retention */\r
308 \r
309 #if defined( _GPIO_CMD_EM4WUCLR_MASK )\r
310   GPIO->CMD = GPIO_CMD_EM4WUCLR;            /* Clear wake-up logic */\r
311 #elif defined( _GPIO_IFC_EM4WU_MASK )\r
312   GPIO_IntClear(pinmask);\r
313 #endif\r
314 }\r
315 #endif\r
316 \r
317 /** @} (end addtogroup GPIO) */\r
318 /** @} (end addtogroup EM_Library) */\r
319 \r
320 #endif /* defined(GPIO_COUNT) && (GPIO_COUNT > 0) */\r