1 /***************************************************************************//**
\r
3 * @brief General Purpose IO (GPIO) peripheral API
\r
5 *******************************************************************************
\r
7 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
\r
8 *******************************************************************************
\r
10 * Permission is granted to anyone to use this software for any purpose,
\r
11 * including commercial applications, and to alter it and redistribute it
\r
12 * freely, subject to the following restrictions:
\r
14 * 1. The origin of this software must not be misrepresented; you must not
\r
15 * claim that you wrote the original software.
\r
16 * 2. Altered source versions must be plainly marked as such, and must not be
\r
17 * misrepresented as being the original software.
\r
18 * 3. This notice may not be removed or altered from any source distribution.
\r
20 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
\r
21 * obligation to support this Software. Silicon Labs is providing the
\r
22 * Software "AS IS", with no express or implied warranties of any kind,
\r
23 * including, but not limited to, any implied warranties of merchantability
\r
24 * or fitness for any particular purpose or warranties against infringement
\r
25 * of any proprietary rights of a third party.
\r
27 * Silicon Labs will not be liable for any consequential, incidental, or
\r
28 * special damages, or any other relief, or for any claim by any third party,
\r
29 * arising from your use of this Software.
\r
31 ******************************************************************************/
\r
34 #ifndef __SILICON_LABS_EM_GPIO_H_
\r
35 #define __SILICON_LABS_EM_GPIO_H_
\r
37 #include "em_device.h"
\r
38 #if defined(GPIO_COUNT) && (GPIO_COUNT > 0)
\r
40 #include <stdbool.h>
\r
41 #include "em_bitband.h"
\r
42 #include "em_assert.h"
\r
48 /***************************************************************************//**
\r
49 * @addtogroup EM_Library
\r
51 ******************************************************************************/
\r
53 /***************************************************************************//**
\r
56 ******************************************************************************/
\r
58 /*******************************************************************************
\r
59 ******************************** ENUMS ************************************
\r
60 ******************************************************************************/
\r
62 /** GPIO ports identificator. */
\r
65 gpioPortA = 0, /**< Port A */
\r
66 gpioPortB = 1, /**< Port B */
\r
67 gpioPortC = 2, /**< Port C */
\r
68 gpioPortD = 3, /**< Port D */
\r
69 gpioPortE = 4, /**< Port E */
\r
70 gpioPortF = 5 /**< Port F */
\r
71 } GPIO_Port_TypeDef;
\r
73 /** GPIO drive mode. */
\r
77 gpioDriveModeStandard = GPIO_P_CTRL_DRIVEMODE_STANDARD,
\r
79 gpioDriveModeLowest = GPIO_P_CTRL_DRIVEMODE_LOWEST,
\r
81 gpioDriveModeHigh = GPIO_P_CTRL_DRIVEMODE_HIGH,
\r
83 gpioDriveModeLow = GPIO_P_CTRL_DRIVEMODE_LOW
\r
84 } GPIO_DriveMode_TypeDef;
\r
86 /** Pin mode. For more details on each mode, please refer to the EFM32
\r
87 * reference manual. */
\r
90 /** Input disabled. Pullup if DOUT is set. */
\r
91 gpioModeDisabled = _GPIO_P_MODEL_MODE0_DISABLED,
\r
92 /** Input enabled. Filter if DOUT is set */
\r
93 gpioModeInput = _GPIO_P_MODEL_MODE0_INPUT,
\r
94 /** Input enabled. DOUT determines pull direction */
\r
95 gpioModeInputPull = _GPIO_P_MODEL_MODE0_INPUTPULL,
\r
96 /** Input enabled with filter. DOUT determines pull direction */
\r
97 gpioModeInputPullFilter = _GPIO_P_MODEL_MODE0_INPUTPULLFILTER,
\r
98 /** Push-pull output */
\r
99 gpioModePushPull = _GPIO_P_MODEL_MODE0_PUSHPULL,
\r
100 /** Push-pull output with drive-strength set by DRIVEMODE */
\r
101 gpioModePushPullDrive = _GPIO_P_MODEL_MODE0_PUSHPULLDRIVE,
\r
102 /** Wired-or output */
\r
103 gpioModeWiredOr = _GPIO_P_MODEL_MODE0_WIREDOR,
\r
104 /** Wired-or output with pull-down */
\r
105 gpioModeWiredOrPullDown = _GPIO_P_MODEL_MODE0_WIREDORPULLDOWN,
\r
106 /** Open-drain output */
\r
107 gpioModeWiredAnd = _GPIO_P_MODEL_MODE0_WIREDAND,
\r
108 /** Open-drain output with filter */
\r
109 gpioModeWiredAndFilter = _GPIO_P_MODEL_MODE0_WIREDANDFILTER,
\r
110 /** Open-drain output with pullup */
\r
111 gpioModeWiredAndPullUp = _GPIO_P_MODEL_MODE0_WIREDANDPULLUP,
\r
112 /** Open-drain output with filter and pullup */
\r
113 gpioModeWiredAndPullUpFilter = _GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER,
\r
114 /** Open-drain output with drive-strength set by DRIVEMODE */
\r
115 gpioModeWiredAndDrive = _GPIO_P_MODEL_MODE0_WIREDANDDRIVE,
\r
116 /** Open-drain output with filter and drive-strength set by DRIVEMODE */
\r
117 gpioModeWiredAndDriveFilter = _GPIO_P_MODEL_MODE0_WIREDANDDRIVEFILTER,
\r
118 /** Open-drain output with pullup and drive-strength set by DRIVEMODE */
\r
119 gpioModeWiredAndDrivePullUp = _GPIO_P_MODEL_MODE0_WIREDANDDRIVEPULLUP,
\r
120 /** Open-drain output with filter, pullup and drive-strength set by DRIVEMODE */
\r
121 gpioModeWiredAndDrivePullUpFilter = _GPIO_P_MODEL_MODE0_WIREDANDDRIVEPULLUPFILTER
\r
122 } GPIO_Mode_TypeDef;
\r
125 /*******************************************************************************
\r
126 ******************************* DEFINES ***********************************
\r
127 ******************************************************************************/
\r
129 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
\r
131 /** Validation of pin typically usable in assert statements. */
\r
132 #define GPIO_PIN_VALID(pin) ((pin) < 16)
\r
134 /** Validation of port typically usable in assert statements. */
\r
135 #define GPIO_PORT_VALID(port) ((port) <= gpioPortF)
\r
140 /*******************************************************************************
\r
141 ***************************** PROTOTYPES **********************************
\r
142 ******************************************************************************/
\r
144 void GPIO_DbgLocationSet(unsigned int location);
\r
146 void GPIO_IntConfig(GPIO_Port_TypeDef port,
\r
152 void GPIO_PinModeSet(GPIO_Port_TypeDef port,
\r
154 GPIO_Mode_TypeDef mode,
\r
157 # if defined( GPIO_CTRL_EM4RET )
\r
158 __STATIC_INLINE void GPIO_EM4SetPinRetention(bool enable);
\r
161 /***************************************************************************//**
\r
163 * Enable/disable serial wire clock pin.
\r
166 * Disabling SWDClk will disable the debug interface, which may result in
\r
167 * a lockout if done early in startup (before debugger is able to halt core).
\r
169 * @param[in] enable
\r
170 * @li false - disable serial wire clock.
\r
171 * @li true - enable serial wire clock (default after reset).
\r
172 ******************************************************************************/
\r
173 __STATIC_INLINE void GPIO_DbgSWDClkEnable(bool enable)
\r
175 BITBAND_Peripheral(&(GPIO->ROUTE), _GPIO_ROUTE_SWCLKPEN_SHIFT, (unsigned int)enable);
\r
179 /***************************************************************************//**
\r
181 * Enable/disable serial wire data pin.
\r
184 * Disabling SWDClk will disable the debug interface, which may result in
\r
185 * a lockout if done early in startup (before debugger is able to halt core).
\r
187 * @param[in] enable
\r
188 * @li false - disable serial wire data pin.
\r
189 * @li true - enable serial wire data pin (default after reset).
\r
190 ******************************************************************************/
\r
191 __STATIC_INLINE void GPIO_DbgSWDIOEnable(bool enable)
\r
193 BITBAND_Peripheral(&(GPIO->ROUTE), _GPIO_ROUTE_SWDIOPEN_SHIFT, (unsigned int)enable);
\r
197 #if defined( GPIO_ROUTE_SWOPEN )
\r
198 /***************************************************************************//**
\r
200 * Enable/Disable serial wire output pin.
\r
203 * Enabling this pin is not sufficient to fully enable serial wire output
\r
204 * which is also dependent on issues outside the GPIO module. Please refer to
\r
207 * @param[in] enable
\r
208 * @li false - disable serial wire viewer pin (default after reset).
\r
209 * @li true - enable serial wire viewer pin.
\r
210 ******************************************************************************/
\r
211 __STATIC_INLINE void GPIO_DbgSWOEnable(bool enable)
\r
213 BITBAND_Peripheral(&(GPIO->ROUTE), _GPIO_ROUTE_SWOPEN_SHIFT, (unsigned int)enable);
\r
217 void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode);
\r
220 # if defined( _GPIO_EM4WUEN_MASK )
\r
221 /**************************************************************************//**
\r
223 * Disable GPIO pin wake-up from EM4.
\r
225 * @param[in] pinmask
\r
226 * Bitmask containing the bitwise logic OR of which GPIO pin(s) to disable.
\r
227 * Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
\r
228 *****************************************************************************/
\r
229 __STATIC_INLINE void GPIO_EM4DisablePinWakeup(uint32_t pinmask)
\r
231 EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
\r
233 GPIO->EM4WUEN &= ~pinmask;
\r
238 # if defined( _GPIO_EM4WUEN_MASK )
\r
239 /**************************************************************************//**
\r
241 * Enable GPIO pin wake-up from EM4. When the function exits,
\r
242 * EM4 mode can be safely entered.
\r
245 * It is assumed that the GPIO pin modes are set correctly.
\r
246 * Valid modes are @ref gpioModeInput and @ref gpioModeInputPull.
\r
248 * @param[in] pinmask
\r
249 * Bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.
\r
250 * Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
\r
251 * @param[in] polaritymask
\r
252 * Bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.
\r
253 * Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
\r
254 *****************************************************************************/
\r
255 __STATIC_INLINE void GPIO_EM4EnablePinWakeup(uint32_t pinmask,
\r
256 uint32_t polaritymask)
\r
258 EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
\r
259 EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);
\r
261 GPIO->EM4WUPOL &= ~pinmask; /* Set wakeup polarity */
\r
262 GPIO->EM4WUPOL |= pinmask & polaritymask;
\r
263 GPIO->EM4WUEN |= pinmask; /* Enable wakeup */
\r
265 GPIO_EM4SetPinRetention(true); /* Enable pin retention */
\r
267 GPIO->CMD = GPIO_CMD_EM4WUCLR; /* Clear wake-up logic */
\r
271 #if defined( _GPIO_EM4WUCAUSE_MASK )
\r
272 /**************************************************************************//**
\r
274 * Check which GPIO pin(s) that caused a wake-up from EM4.
\r
277 * Bitmask containing the bitwise logic OR of which GPIO pin(s) caused the
\r
278 * wake-up. Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
\r
279 *****************************************************************************/
\r
280 __STATIC_INLINE uint32_t GPIO_EM4GetPinWakeupCause(void)
\r
282 return GPIO->EM4WUCAUSE & _GPIO_EM4WUCAUSE_MASK;
\r
287 # if defined( GPIO_CTRL_EM4RET )
\r
288 /**************************************************************************//**
\r
290 * Enable GPIO pin retention of output enable, output value, pull enable and
\r
291 * pull direction in EM4.
\r
293 * @param[in] enable
\r
294 * @li true - enable EM4 pin retention.
\r
295 * @li false - disable EM4 pin retention.
\r
296 *****************************************************************************/
\r
297 __STATIC_INLINE void GPIO_EM4SetPinRetention(bool enable)
\r
301 GPIO->CTRL |= GPIO_CTRL_EM4RET;
\r
305 GPIO->CTRL &= ~GPIO_CTRL_EM4RET;
\r
311 /***************************************************************************//**
\r
313 * Enable/disable input sensing.
\r
316 * Disabling input sensing if not used, can save some energy consumption.
\r
319 * Bitwise logic OR of one or more of:
\r
320 * @li GPIO_INSENSE_INT - interrupt input sensing.
\r
321 * @li GPIO_INSENSE_PRS - peripheral reflex system input sensing.
\r
324 * Mask containing bitwise logic OR of bits similar as for @p val used to indicate
\r
325 * which input sense options to disable/enable.
\r
326 ******************************************************************************/
\r
327 __STATIC_INLINE void GPIO_InputSenseSet(uint32_t val, uint32_t mask)
\r
329 GPIO->INSENSE = (GPIO->INSENSE & ~mask) | (val & mask);
\r
333 /***************************************************************************//**
\r
335 * Clear one or more pending GPIO interrupts.
\r
338 * Bitwise logic OR of GPIO interrupt sources to clear.
\r
339 ******************************************************************************/
\r
340 __STATIC_INLINE void GPIO_IntClear(uint32_t flags)
\r
346 /***************************************************************************//**
\r
348 * Disable one or more GPIO interrupts.
\r
351 * GPIO interrupt sources to disable.
\r
352 ******************************************************************************/
\r
353 __STATIC_INLINE void GPIO_IntDisable(uint32_t flags)
\r
355 GPIO->IEN &= ~flags;
\r
359 /***************************************************************************//**
\r
361 * Enable one or more GPIO interrupts.
\r
364 * Depending on the use, a pending interrupt may already be set prior to
\r
365 * enabling the interrupt. Consider using GPIO_IntClear() prior to enabling
\r
366 * if such a pending interrupt should be ignored.
\r
369 * GPIO interrupt sources to enable.
\r
370 ******************************************************************************/
\r
371 __STATIC_INLINE void GPIO_IntEnable(uint32_t flags)
\r
373 GPIO->IEN |= flags;
\r
377 /***************************************************************************//**
\r
379 * Get pending GPIO interrupts.
\r
382 * GPIO interrupt sources pending.
\r
383 ******************************************************************************/
\r
384 __STATIC_INLINE uint32_t GPIO_IntGet(void)
\r
390 /***************************************************************************//**
\r
392 * Get enabled and pending GPIO interrupt flags.
\r
393 * Useful for handling more interrupt sources in the same interrupt handler.
\r
396 * Interrupt flags are not cleared by the use of this function.
\r
399 * Pending and enabled GPIO interrupt sources.
\r
400 * The return value is the bitwise AND combination of
\r
401 * - the OR combination of enabled interrupt sources in GPIO_IEN register
\r
403 * - the OR combination of valid interrupt flags in GPIO_IF register.
\r
404 ******************************************************************************/
\r
405 __STATIC_INLINE uint32_t GPIO_IntGetEnabled(void)
\r
409 /* Store GPIO->IEN in temporary variable in order to define explicit order
\r
410 * of volatile accesses. */
\r
413 /* Bitwise AND of pending and enabled interrupts */
\r
414 return GPIO->IF & tmp;
\r
418 /**************************************************************************//**
\r
420 * Set one or more pending GPIO interrupts from SW.
\r
423 * GPIO interrupt sources to set to pending.
\r
424 *****************************************************************************/
\r
425 __STATIC_INLINE void GPIO_IntSet(uint32_t flags)
\r
431 /***************************************************************************//**
\r
433 * Locks the GPIO configuration.
\r
434 ******************************************************************************/
\r
435 __STATIC_INLINE void GPIO_Lock(void)
\r
437 GPIO->LOCK = GPIO_LOCK_LOCKKEY_LOCK;
\r
441 /***************************************************************************//**
\r
443 * Read the pad value for a single pin in a GPIO port.
\r
446 * The GPIO port to access.
\r
449 * The pin number to read.
\r
452 * The pin value, 0 or 1.
\r
453 ******************************************************************************/
\r
454 __STATIC_INLINE unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin)
\r
456 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
\r
458 return((unsigned int)((GPIO->P[port].DIN >> pin) & 0x1));
\r
462 /***************************************************************************//**
\r
464 * Set a single pin in GPIO data out port register to 0.
\r
467 * In order for the setting to take effect on the output pad, the pin must
\r
468 * have been configured properly. If not, it will take effect whenever the
\r
469 * pin has been properly configured.
\r
472 * The GPIO port to access.
\r
476 ******************************************************************************/
\r
477 __STATIC_INLINE void GPIO_PinOutClear(GPIO_Port_TypeDef port, unsigned int pin)
\r
479 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
\r
481 GPIO->P[port].DOUTCLR = 1 << pin;
\r
485 /***************************************************************************//**
\r
487 * Get current setting for a pin in a GPIO port data out register.
\r
490 * The GPIO port to access.
\r
493 * The pin to get setting for.
\r
496 * The DOUT setting for the requested pin, 0 or 1.
\r
497 ******************************************************************************/
\r
498 __STATIC_INLINE unsigned int GPIO_PinOutGet(GPIO_Port_TypeDef port, unsigned int pin)
\r
500 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
\r
502 return((unsigned int)((GPIO->P[port].DOUT >> pin) & 0x1));
\r
506 /***************************************************************************//**
\r
508 * Set a single pin in GPIO data out register to 1.
\r
511 * In order for the setting to take effect on the output pad, the pin must
\r
512 * have been configured properly. If not, it will take effect whenever the
\r
513 * pin has been properly configured.
\r
516 * The GPIO port to access.
\r
520 ******************************************************************************/
\r
521 __STATIC_INLINE void GPIO_PinOutSet(GPIO_Port_TypeDef port, unsigned int pin)
\r
523 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
\r
525 GPIO->P[port].DOUTSET = 1 << pin;
\r
529 /***************************************************************************//**
\r
531 * Toggle a single pin in GPIO port data out register.
\r
534 * In order for the setting to take effect on the output pad, the pin must
\r
535 * have been configured properly. If not, it will take effect whenever the
\r
536 * pin has been properly configured.
\r
539 * The GPIO port to access.
\r
542 * The pin to toggle.
\r
543 ******************************************************************************/
\r
544 __STATIC_INLINE void GPIO_PinOutToggle(GPIO_Port_TypeDef port, unsigned int pin)
\r
546 EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
\r
548 GPIO->P[port].DOUTTGL = 1 << pin;
\r
552 /***************************************************************************//**
\r
554 * Read the pad values for GPIO port.
\r
557 * The GPIO port to access.
\r
558 ******************************************************************************/
\r
559 __STATIC_INLINE uint32_t GPIO_PortInGet(GPIO_Port_TypeDef port)
\r
561 EFM_ASSERT(GPIO_PORT_VALID(port));
\r
563 return(GPIO->P[port].DIN & _GPIO_P_DIN_DIN_MASK);
\r
567 /***************************************************************************//**
\r
569 * Set bits in DOUT register for a port to 0.
\r
572 * In order for the setting to take effect on the output pad, the pin must
\r
573 * have been configured properly. If not, it will take effect whenever the
\r
574 * pin has been properly configured.
\r
577 * The GPIO port to access.
\r
580 * Bit mask for bits to clear in DOUT register.
\r
581 ******************************************************************************/
\r
582 __STATIC_INLINE void GPIO_PortOutClear(GPIO_Port_TypeDef port, uint32_t pins)
\r
584 EFM_ASSERT(GPIO_PORT_VALID(port));
\r
586 GPIO->P[port].DOUTCLR = pins & _GPIO_P_DOUTCLR_DOUTCLR_MASK;
\r
590 /***************************************************************************//**
\r
592 * Get current setting for a GPIO port data out register.
\r
595 * The GPIO port to access.
\r
598 * The data out setting for the requested port.
\r
599 ******************************************************************************/
\r
600 __STATIC_INLINE uint32_t GPIO_PortOutGet(GPIO_Port_TypeDef port)
\r
602 EFM_ASSERT(GPIO_PORT_VALID(port));
\r
604 return(GPIO->P[port].DOUT & _GPIO_P_DOUT_DOUT_MASK);
\r
608 /***************************************************************************//**
\r
610 * Set bits GPIO data out register to 1.
\r
613 * In order for the setting to take effect on the respective output pads, the
\r
614 * pins must have been configured properly. If not, it will take effect
\r
615 * whenever the pin has been properly configured.
\r
618 * The GPIO port to access.
\r
621 * Bit mask for bits to set to 1 in DOUT register.
\r
622 ******************************************************************************/
\r
623 __STATIC_INLINE void GPIO_PortOutSet(GPIO_Port_TypeDef port, uint32_t pins)
\r
625 EFM_ASSERT(GPIO_PORT_VALID(port));
\r
627 GPIO->P[port].DOUTSET = pins & _GPIO_P_DOUTSET_DOUTSET_MASK;
\r
631 /***************************************************************************//**
\r
633 * Set GPIO port data out register.
\r
636 * In order for the setting to take effect on the respective output pads, the
\r
637 * pins must have been configured properly. If not, it will take effect
\r
638 * whenever the pin has been properly configured.
\r
641 * The GPIO port to access.
\r
644 * Value to write to port data out register.
\r
647 * Mask indicating which bits to modify.
\r
648 ******************************************************************************/
\r
649 __STATIC_INLINE void GPIO_PortOutSetVal(GPIO_Port_TypeDef port, uint32_t val, uint32_t mask)
\r
651 EFM_ASSERT(GPIO_PORT_VALID(port));
\r
653 GPIO->P[port].DOUT = (GPIO->P[port].DOUT & ~mask) | (val & mask);
\r
657 /***************************************************************************//**
\r
659 * Toggle a single pin in GPIO port data out register.
\r
662 * In order for the setting to take effect on the output pad, the pin must
\r
663 * have been configured properly. If not, it will take effect whenever the
\r
664 * pin has been properly configured.
\r
667 * The GPIO port to access.
\r
670 * Bitmask with pins to toggle.
\r
671 ******************************************************************************/
\r
672 __STATIC_INLINE void GPIO_PortOutToggle(GPIO_Port_TypeDef port, uint32_t pins)
\r
674 EFM_ASSERT(GPIO_PORT_VALID(port));
\r
676 GPIO->P[port].DOUTTGL = pins & _GPIO_P_DOUTTGL_DOUTTGL_MASK;
\r
680 /***************************************************************************//**
\r
682 * Unlocks the GPIO configuration.
\r
683 ******************************************************************************/
\r
684 __STATIC_INLINE void GPIO_Unlock(void)
\r
686 GPIO->LOCK = GPIO_LOCK_LOCKKEY_UNLOCK;
\r
690 /** @} (end addtogroup GPIO) */
\r
691 /** @} (end addtogroup EM_Library) */
\r
697 #endif /* defined(GPIO_COUNT) && (GPIO_COUNT > 0) */
\r
698 #endif /* __SILICON_LABS_EM_GPIO_H_ */
\r