1 /***************************************************************************//**
2 * @file
3 * @brief General Purpose IO (GPIO) peripheral API
4 * devices.
5 * @author Energy Micro AS
6 * @version 3.0.0
7 *******************************************************************************
8 * @section License
9 * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
10 *******************************************************************************
11 *
12 * Permission is granted to anyone to use this software for any purpose,
13 * including commercial applications, and to alter it and redistribute it
14 * freely, subject to the following restrictions:
15 *
16 * 1. The origin of this software must not be misrepresented; you must not
17 * claim that you wrote the original software.
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 * 3. This notice may not be removed or altered from any source distribution.
21 *
22 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
23 * obligation to support this Software. Energy Micro AS is providing the
24 * Software "AS IS", with no express or implied warranties of any kind,
25 * including, but not limited to, any implied warranties of merchantability
26 * or fitness for any particular purpose or warranties against infringement
27 * of any proprietary rights of a third party.
28 *
29 * Energy Micro AS will not be liable for any consequential, incidental, or
30 * special damages, or any other relief, or for any claim by any third party,
31 * arising from your use of this Software.
32 *
33 ******************************************************************************/
34 #include "em_gpio.h"
35 #include "em_bitband.h"
36 #include "em_assert.h"
37
38 /***************************************************************************//**
39 * @addtogroup EM_Library
40 * @{
41 ******************************************************************************/
42
43 /***************************************************************************//**
44 * @addtogroup GPIO
45 * @brief General Purpose Input/Output (GPIO) API
46 * @{
47 ******************************************************************************/
48
49 /*******************************************************************************
50 ******************************* DEFINES ***********************************
51 ******************************************************************************/
52
53 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
54
55 /** Validation of pin typically usable in assert statements. */
56 #define GPIO_DRIVEMODE_VALID(mode) ((mode) <= 3)
57
58 /** Validation of pin typically usable in assert statements. */
59 #define GPIO_PIN_VALID(pin) ((pin) < 16)
60
61 /** Validation of port typically usable in assert statements. */
62 #define GPIO_PORT_VALID(port) ((port) <= gpioPortF)
63
64 /** @endcond */
65
66
67 /*******************************************************************************
68 ************************** GLOBAL FUNCTIONS *******************************
69 ******************************************************************************/
70
71 /***************************************************************************//**
72 * @brief
73 * Sets the pin location of the debug pins (Serial Wire interface).
74 *
75 * @note
76 * Changing the pins used for debugging uncontrolled, may result in a lockout.
77 *
78 * @param[in] location
79 * The debug pin location to use (0-3).
80 ******************************************************************************/
GPIO_DbgLocationSet(unsigned int location)81 void GPIO_DbgLocationSet(unsigned int location)
82 {
83 EFM_ASSERT(location < AFCHANLOC_MAX);
84
85 GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) |
86 (location << _GPIO_ROUTE_SWLOCATION_SHIFT);
87 }
88
89
90 /***************************************************************************//**
91 * @brief
92 * Sets the drive mode for a GPIO port.
93 *
94 * @param[in] port
95 * The GPIO port to access.
96 *
97 * @param[in] mode
98 * Drive mode to use for port.
99 ******************************************************************************/
GPIO_DriveModeSet(GPIO_Port_TypeDef port,GPIO_DriveMode_TypeDef mode)100 void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)
101 {
102 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));
103
104 GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))
105 | (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);
106 }
107
108
109 /***************************************************************************//**
110 * @brief
111 * Configure GPIO interrupt.
112 *
113 * @details
114 * If reconfiguring a GPIO interrupt that is already enabled, it is generally
115 * recommended to disable it first, see GPIO_Disable().
116 *
117 * The actual GPIO interrupt handler must be in place before enabling the
118 * interrupt.
119 *
120 * Notice that any pending interrupt for the selected pin is cleared by this
121 * function.
122 *
123 * @note
124 * A certain pin number can only be associated with one port. Ie, if GPIO
125 * interrupt 1 is assigned to port A/pin 1, then it is not possibly to use
126 * pin 1 from any other ports for interrupts. Please refer to the reference
127 * manual.
128 *
129 * @param[in] port
130 * The port to associate with @p pin.
131 *
132 * @param[in] pin
133 * The GPIO interrupt number (= port pin).
134 *
135 * @param[in] risingEdge
136 * Set to true if interrupts shall be enabled on rising edge, otherwise false.
137 *
138 * @param[in] fallingEdge
139 * Set to true if interrupts shall be enabled on falling edge, otherwise false.
140 *
141 * @param[in] enable
142 * Set to true if interrupt shall be enabled after configuration completed,
143 * false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().
144 ******************************************************************************/
GPIO_IntConfig(GPIO_Port_TypeDef port,unsigned int pin,bool risingEdge,bool fallingEdge,bool enable)145 void GPIO_IntConfig(GPIO_Port_TypeDef port,
146 unsigned int pin,
147 bool risingEdge,
148 bool fallingEdge,
149 bool enable)
150 {
151 uint32_t tmp;
152
153 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
154
155 /* There are two registers controlling the interrupt configuration:
156 * The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls
157 * pins 8-15. */
158 if (pin < 8)
159 {
160 GPIO->EXTIPSELL = (GPIO->EXTIPSELL & ~(0xF << (4 * pin))) |
161 (port << (4 * pin));
162 }
163 else
164 {
165 tmp = pin - 8;
166 GPIO->EXTIPSELH = (GPIO->EXTIPSELH & ~(0xF << (4 * tmp))) |
167 (port << (4 * tmp));
168 }
169
170 /* Enable/disable rising edge */
171 BITBAND_Peripheral(&(GPIO->EXTIRISE), pin, (unsigned int)risingEdge);
172
173 /* Enable/disable falling edge */
174 BITBAND_Peripheral(&(GPIO->EXTIFALL), pin, (unsigned int)fallingEdge);
175
176 /* Clear any pending interrupt */
177 GPIO->IFC = 1 << pin;
178
179 /* Finally enable/disable interrupt */
180 BITBAND_Peripheral(&(GPIO->IEN), pin, (unsigned int)enable);
181 }
182
183
184 /***************************************************************************//**
185 * @brief
186 * Read the pad value for a single pin in a GPIO port.
187 *
188 * @param[in] port
189 * The GPIO port to access.
190 *
191 * @param[in] pin
192 * The pin number to read.
193 *
194 * @return
195 * The pin value, 0 or 1.
196 ******************************************************************************/
GPIO_PinInGet(GPIO_Port_TypeDef port,unsigned int pin)197 unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin)
198 {
199 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
200
201 return((unsigned int)((GPIO->P[port].DIN >> pin) & 0x1));
202 }
203
204
205 /***************************************************************************//**
206 * @brief
207 * Set the mode for a GPIO pin.
208 *
209 * @param[in] port
210 * The GPIO port to access.
211 *
212 * @param[in] pin
213 * The pin number in the port.
214 *
215 * @param[in] mode
216 * The desired pin mode.
217 *
218 * @param[in] out
219 * Value to set for pin in DOUT register. The DOUT setting is important for
220 * even some input mode configurations, determining pull-up/down direction.
221 * Notice that this parameter is not used if disabling a pin, leaving the
222 * corresponding DOUT bit unchanged.
223 ******************************************************************************/
GPIO_PinModeSet(GPIO_Port_TypeDef port,unsigned int pin,GPIO_Mode_TypeDef mode,unsigned int out)224 void GPIO_PinModeSet(GPIO_Port_TypeDef port,
225 unsigned int pin,
226 GPIO_Mode_TypeDef mode,
227 unsigned int out)
228 {
229 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
230
231 /* If disabling pin, do not modify DOUT in order to reduce chance for */
232 /* glitch/spike (may not be sufficient precaution in all use cases) */
233 if (mode != gpioModeDisabled)
234 {
235 if (out)
236 {
237 GPIO->P[port].DOUTSET = 1 << pin;
238 }
239 else
240 {
241 GPIO->P[port].DOUTCLR = 1 << pin;
242 }
243 }
244
245 /* There are two registers controlling the pins for each port. The MODEL
246 * register controls pins 0-7 and MODEH controls pins 8-15. */
247 if (pin < 8)
248 {
249 GPIO->P[port].MODEL = (GPIO->P[port].MODEL & ~(0xF << (pin * 4))) |
250 (mode << (pin * 4));
251 }
252 else
253 {
254 GPIO->P[port].MODEH = (GPIO->P[port].MODEH & ~(0xF << ((pin - 8) * 4))) |
255 (mode << ((pin - 8) * 4));
256 }
257
258 if (mode == gpioModeDisabled)
259 {
260 if (out)
261 {
262 GPIO->P[port].DOUTSET = 1 << pin;
263 }
264 else
265 {
266 GPIO->P[port].DOUTCLR = 1 << pin;
267 }
268 }
269 }
270
271
272 /***************************************************************************//**
273 * @brief
274 * Set a single pin in GPIO data out port register to 0.
275 *
276 * @note
277 * In order for the setting to take effect on the output pad, the pin must
278 * have been configured properly. If not, it will take effect whenever the
279 * pin has been properly configured.
280 *
281 * @param[in] port
282 * The GPIO port to access.
283 *
284 * @param[in] pin
285 * The pin to set.
286 ******************************************************************************/
GPIO_PinOutClear(GPIO_Port_TypeDef port,unsigned int pin)287 void GPIO_PinOutClear(GPIO_Port_TypeDef port, unsigned int pin)
288 {
289 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
290
291 GPIO->P[port].DOUTCLR = 1 << pin;
292 }
293
294
295 /***************************************************************************//**
296 * @brief
297 * Get current setting for a pin in a GPIO port data out register.
298 *
299 * @param[in] port
300 * The GPIO port to access.
301 *
302 * @param[in] pin
303 * The pin to get setting for.
304 *
305 * @return
306 * The DOUT setting for the requested pin, 0 or 1.
307 ******************************************************************************/
GPIO_PinOutGet(GPIO_Port_TypeDef port,unsigned int pin)308 unsigned int GPIO_PinOutGet(GPIO_Port_TypeDef port, unsigned int pin)
309 {
310 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
311
312 return((unsigned int)((GPIO->P[port].DOUT >> pin) & 0x1));
313 }
314
315
316 /***************************************************************************//**
317 * @brief
318 * Set a single pin in GPIO data out register to 1.
319 *
320 * @note
321 * In order for the setting to take effect on the output pad, the pin must
322 * have been configured properly. If not, it will take effect whenever the
323 * pin has been properly configured.
324 *
325 * @param[in] port
326 * The GPIO port to access.
327 *
328 * @param[in] pin
329 * The pin to set.
330 ******************************************************************************/
GPIO_PinOutSet(GPIO_Port_TypeDef port,unsigned int pin)331 void GPIO_PinOutSet(GPIO_Port_TypeDef port, unsigned int pin)
332 {
333 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
334
335 GPIO->P[port].DOUTSET = 1 << pin;
336 }
337
338
339 /***************************************************************************//**
340 * @brief
341 * Toggle a single pin in GPIO port data out register.
342 *
343 * @note
344 * In order for the setting to take effect on the output pad, the pin must
345 * have been configured properly. If not, it will take effect whenever the
346 * pin has been properly configured.
347 *
348 * @param[in] port
349 * The GPIO port to access.
350 *
351 * @param[in] pin
352 * The pin to toggle.
353 ******************************************************************************/
GPIO_PinOutToggle(GPIO_Port_TypeDef port,unsigned int pin)354 void GPIO_PinOutToggle(GPIO_Port_TypeDef port, unsigned int pin)
355 {
356 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
357
358 GPIO->P[port].DOUTTGL = 1 << pin;
359 }
360
361
362 /***************************************************************************//**
363 * @brief
364 * Read the pad values for GPIO port.
365 *
366 * @param[in] port
367 * The GPIO port to access.
368 ******************************************************************************/
GPIO_PortInGet(GPIO_Port_TypeDef port)369 uint32_t GPIO_PortInGet(GPIO_Port_TypeDef port)
370 {
371 EFM_ASSERT(GPIO_PORT_VALID(port));
372
373 return(GPIO->P[port].DIN & _GPIO_P_DIN_DIN_MASK);
374 }
375
376
377 /***************************************************************************//**
378 * @brief
379 * Set bits in DOUT register for a port to 0.
380 *
381 * @note
382 * In order for the setting to take effect on the output pad, the pin must
383 * have been configured properly. If not, it will take effect whenever the
384 * pin has been properly configured.
385 *
386 * @param[in] port
387 * The GPIO port to access.
388 *
389 * @param[in] pins
390 * Bit mask for bits to clear in DOUT register.
391 ******************************************************************************/
GPIO_PortOutClear(GPIO_Port_TypeDef port,uint32_t pins)392 void GPIO_PortOutClear(GPIO_Port_TypeDef port, uint32_t pins)
393 {
394 EFM_ASSERT(GPIO_PORT_VALID(port));
395
396 GPIO->P[port].DOUTCLR = pins & _GPIO_P_DOUTCLR_DOUTCLR_MASK;
397 }
398
399
400 /***************************************************************************//**
401 * @brief
402 * Get current setting for a GPIO port data out register.
403 *
404 * @param[in] port
405 * The GPIO port to access.
406 *
407 * @return
408 * The data out setting for the requested port.
409 ******************************************************************************/
GPIO_PortOutGet(GPIO_Port_TypeDef port)410 uint32_t GPIO_PortOutGet(GPIO_Port_TypeDef port)
411 {
412 EFM_ASSERT(GPIO_PORT_VALID(port));
413
414 return(GPIO->P[port].DOUT & _GPIO_P_DOUT_DOUT_MASK);
415 }
416
417
418 /***************************************************************************//**
419 * @brief
420 * Set bits GPIO data out register to 1.
421 *
422 * @note
423 * In order for the setting to take effect on the respective output pads, the
424 * pins must have been configured properly. If not, it will take effect
425 * whenever the pin has been properly configured.
426 *
427 * @param[in] port
428 * The GPIO port to access.
429 *
430 * @param[in] pins
431 * Bit mask for bits to set to 1 in DOUT register.
432 ******************************************************************************/
GPIO_PortOutSet(GPIO_Port_TypeDef port,uint32_t pins)433 void GPIO_PortOutSet(GPIO_Port_TypeDef port, uint32_t pins)
434 {
435 EFM_ASSERT(GPIO_PORT_VALID(port));
436
437 GPIO->P[port].DOUTSET = pins & _GPIO_P_DOUTSET_DOUTSET_MASK;
438 }
439
440
441 /***************************************************************************//**
442 * @brief
443 * Set GPIO port data out register.
444 *
445 * @note
446 * In order for the setting to take effect on the respective output pads, the
447 * pins must have been configured properly. If not, it will take effect
448 * whenever the pin has been properly configured.
449 *
450 * @param[in] port
451 * The GPIO port to access.
452 *
453 * @param[in] val
454 * Value to write to port data out register.
455 *
456 * @param[in] mask
457 * Mask indicating which bits to modify.
458 ******************************************************************************/
GPIO_PortOutSetVal(GPIO_Port_TypeDef port,uint32_t val,uint32_t mask)459 void GPIO_PortOutSetVal(GPIO_Port_TypeDef port, uint32_t val, uint32_t mask)
460 {
461 EFM_ASSERT(GPIO_PORT_VALID(port));
462
463 GPIO->P[port].DOUT = (GPIO->P[port].DOUT & ~mask) | (val & mask);
464 }
465
466
467 /***************************************************************************//**
468 * @brief
469 * Toggle a single pin in GPIO port data out register.
470 *
471 * @note
472 * In order for the setting to take effect on the output pad, the pin must
473 * have been configured properly. If not, it will take effect whenever the
474 * pin has been properly configured.
475 *
476 * @param[in] port
477 * The GPIO port to access.
478 *
479 * @param[in] pins
480 * Bitmask with pins to toggle.
481 ******************************************************************************/
GPIO_PortOutToggle(GPIO_Port_TypeDef port,uint32_t pins)482 void GPIO_PortOutToggle(GPIO_Port_TypeDef port, uint32_t pins)
483 {
484 EFM_ASSERT(GPIO_PORT_VALID(port));
485
486 GPIO->P[port].DOUTTGL = pins & _GPIO_P_DOUTTGL_DOUTTGL_MASK;
487 }
488
489
490 /** @} (end addtogroup GPIO) */
491 /** @} (end addtogroup EM_Library) */
492