]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/SilLabs_Code/emlib/em_gpio.c
54a82dfd0fdb6a156c4e0d17b53b3579b62b1dec
[freertos] / FreeRTOS / Demo / CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio / Source / SilLabs_Code / 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.0.0\r
6  *******************************************************************************\r
7  * @section License\r
8  * <b>(C) Copyright 2014 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  * @addtogroup EM_Library\r
40  * @{\r
41  ******************************************************************************/\r
42 \r
43 /***************************************************************************//**\r
44  * @addtogroup GPIO\r
45  * @brief General Purpose Input/Output (GPIO) API\r
46  * @{\r
47  ******************************************************************************/\r
48 \r
49 /*******************************************************************************\r
50  *******************************   DEFINES   ***********************************\r
51  ******************************************************************************/\r
52 \r
53 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
54 \r
55 /** Validation of pin typically usable in assert statements. */\r
56 #define GPIO_DRIVEMODE_VALID(mode)    ((mode) <= 3)\r
57 \r
58 /** @endcond */\r
59 \r
60 \r
61 /*******************************************************************************\r
62  **************************   GLOBAL FUNCTIONS   *******************************\r
63  ******************************************************************************/\r
64 \r
65 /***************************************************************************//**\r
66  * @brief\r
67  *   Sets the pin location of the debug pins (Serial Wire interface).\r
68  *\r
69  * @note\r
70  *   Changing the pins used for debugging uncontrolled, may result in a lockout.\r
71  *\r
72  * @param[in] location\r
73  *   The debug pin location to use (0-3).\r
74  ******************************************************************************/\r
75 void GPIO_DbgLocationSet(unsigned int location)\r
76 {\r
77 #if defined ( _GPIO_ROUTE_SWLOCATION_MASK )\r
78   EFM_ASSERT(location < AFCHANLOC_MAX);\r
79 \r
80   GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) |\r
81                 (location << _GPIO_ROUTE_SWLOCATION_SHIFT);\r
82 #else\r
83   (void)location;\r
84 #endif\r
85 }\r
86 \r
87 \r
88 /***************************************************************************//**\r
89  * @brief\r
90  *   Sets the drive mode for a GPIO port.\r
91  *\r
92  * @param[in] port\r
93  *   The GPIO port to access.\r
94  *\r
95  * @param[in] mode\r
96  *   Drive mode to use for port.\r
97  ******************************************************************************/\r
98 void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)\r
99 {\r
100   EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));\r
101 \r
102   GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))\r
103                        | (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);\r
104 }\r
105 \r
106 \r
107 /***************************************************************************//**\r
108  * @brief\r
109  *   Configure GPIO interrupt.\r
110  *\r
111  * @details\r
112  *   If reconfiguring a GPIO interrupt that is already enabled, it is generally\r
113  *   recommended to disable it first, see GPIO_Disable().\r
114  *\r
115  *   The actual GPIO interrupt handler must be in place before enabling the\r
116  *   interrupt.\r
117  *\r
118  *   Notice that any pending interrupt for the selected pin is cleared by this\r
119  *   function.\r
120  *\r
121  * @note\r
122  *   A certain pin number can only be associated with one port. Ie, if GPIO\r
123  *   interrupt 1 is assigned to port A/pin 1, then it is not possibly to use\r
124  *   pin 1 from any other ports for interrupts. Please refer to the reference\r
125  *   manual.\r
126  *\r
127  * @param[in] port\r
128  *   The port to associate with @p pin.\r
129  *\r
130  * @param[in] pin\r
131  *   The GPIO interrupt number (= port pin).\r
132  *\r
133  * @param[in] risingEdge\r
134  *   Set to true if interrupts shall be enabled on rising edge, otherwise false.\r
135  *\r
136  * @param[in] fallingEdge\r
137  *   Set to true if interrupts shall be enabled on falling edge, otherwise false.\r
138  *\r
139  * @param[in] enable\r
140  *   Set to true if interrupt shall be enabled after configuration completed,\r
141  *   false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().\r
142  ******************************************************************************/\r
143 void GPIO_IntConfig(GPIO_Port_TypeDef port,\r
144                     unsigned int pin,\r
145                     bool risingEdge,\r
146                     bool fallingEdge,\r
147                     bool enable)\r
148 {\r
149   uint32_t tmp;\r
150 \r
151   EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));\r
152 \r
153   /* There are two registers controlling the interrupt configuration:\r
154    * The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls\r
155    * pins 8-15. */\r
156   if (pin < 8)\r
157   {\r
158     GPIO->EXTIPSELL = (GPIO->EXTIPSELL & ~(0xF << (4 * pin))) |\r
159                       (port << (4 * pin));\r
160   }\r
161   else\r
162   {\r
163     tmp             = pin - 8;\r
164     GPIO->EXTIPSELH = (GPIO->EXTIPSELH & ~(0xF << (4 * tmp))) |\r
165                       (port << (4 * tmp));\r
166   }\r
167 \r
168   /* Enable/disable rising edge */\r
169   BITBAND_Peripheral(&(GPIO->EXTIRISE), pin, (unsigned int)risingEdge);\r
170 \r
171   /* Enable/disable falling edge */\r
172   BITBAND_Peripheral(&(GPIO->EXTIFALL), pin, (unsigned int)fallingEdge);\r
173 \r
174   /* Clear any pending interrupt */\r
175   GPIO->IFC = 1 << pin;\r
176 \r
177   /* Finally enable/disable interrupt */\r
178   BITBAND_Peripheral(&(GPIO->IEN), pin, (unsigned int)enable);\r
179 }\r
180 \r
181 \r
182 /***************************************************************************//**\r
183  * @brief\r
184  *   Set the mode for a GPIO pin.\r
185  *\r
186  * @param[in] port\r
187  *   The GPIO port to access.\r
188  *\r
189  * @param[in] pin\r
190  *   The pin number in the port.\r
191  *\r
192  * @param[in] mode\r
193  *   The desired pin mode.\r
194  *\r
195  * @param[in] out\r
196  *   Value to set for pin in DOUT register. The DOUT setting is important for\r
197  *   even some input mode configurations, determining pull-up/down direction.\r
198  ******************************************************************************/\r
199 void GPIO_PinModeSet(GPIO_Port_TypeDef port,\r
200                      unsigned int pin,\r
201                      GPIO_Mode_TypeDef mode,\r
202                      unsigned int out)\r
203 {\r
204   EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));\r
205 \r
206   /* If disabling pin, do not modify DOUT in order to reduce chance for */\r
207   /* glitch/spike (may not be sufficient precaution in all use cases) */\r
208   if (mode != gpioModeDisabled)\r
209   {\r
210     if (out)\r
211     {\r
212       GPIO->P[port].DOUTSET = 1 << pin;\r
213     }\r
214     else\r
215     {\r
216       GPIO->P[port].DOUTCLR = 1 << pin;\r
217     }\r
218   }\r
219 \r
220   /* There are two registers controlling the pins for each port. The MODEL\r
221    * register controls pins 0-7 and MODEH controls pins 8-15. */\r
222   if (pin < 8)\r
223   {\r
224     GPIO->P[port].MODEL = (GPIO->P[port].MODEL & ~(0xF << (pin * 4))) |\r
225                           (mode << (pin * 4));\r
226   }\r
227   else\r
228   {\r
229     GPIO->P[port].MODEH = (GPIO->P[port].MODEH & ~(0xF << ((pin - 8) * 4))) |\r
230                           (mode << ((pin - 8) * 4));\r
231   }\r
232 \r
233   if (mode == gpioModeDisabled)\r
234   {\r
235     if (out)\r
236     {\r
237       GPIO->P[port].DOUTSET = 1 << pin;\r
238     }\r
239     else\r
240     {\r
241       GPIO->P[port].DOUTCLR = 1 << pin;\r
242     }\r
243   }\r
244 }\r
245 \r
246 /** @} (end addtogroup GPIO) */\r
247 /** @} (end addtogroup EM_Library) */\r
248 \r
249 #endif /* defined(GPIO_COUNT) && (GPIO_COUNT > 0) */\r