1 /***************************************************************************//**
2  * @file
3  * @brief General Purpose IO (GPIO) peripheral API
4  * @author Energy Micro AS
5  * @version 3.0.0
6  *******************************************************************************
7  * @section License
8  * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
9  *******************************************************************************
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute it
13  * freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must not
16  *    claim that you wrote the original software.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  *    misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
22  * obligation to support this Software. Energy Micro AS is providing the
23  * Software "AS IS", with no express or implied warranties of any kind,
24  * including, but not limited to, any implied warranties of merchantability
25  * or fitness for any particular purpose or warranties against infringement
26  * of any proprietary rights of a third party.
27  *
28  * Energy Micro AS will not be liable for any consequential, incidental, or
29  * special damages, or any other relief, or for any claim by any third party,
30  * arising from your use of this Software.
31  *
32  ******************************************************************************/
33 #ifndef __EM_GPIO_H
34 #define __EM_GPIO_H
35 
36 #include <stdbool.h>
37 #include "em_part.h"
38 #include "em_bitband.h"
39 #include "em_assert.h"
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /***************************************************************************//**
46  * @addtogroup EM_Library
47  * @{
48  ******************************************************************************/
49 
50 /***************************************************************************//**
51  * @addtogroup GPIO
52  * @{
53  ******************************************************************************/
54 
55 /*******************************************************************************
56  ********************************   ENUMS   ************************************
57  ******************************************************************************/
58 
59 /** GPIO ports identificator. */
60 typedef enum
61 {
62   gpioPortA = 0, /**< Port A */
63   gpioPortB = 1, /**< Port B */
64   gpioPortC = 2, /**< Port C */
65   gpioPortD = 3, /**< Port D */
66   gpioPortE = 4, /**< Port E */
67   gpioPortF = 5  /**< Port F */
68 } GPIO_Port_TypeDef;
69 
70 /** GPIO drive mode. */
71 typedef enum
72 {
73   /** Default 6mA */
74   gpioDriveModeStandard = GPIO_P_CTRL_DRIVEMODE_STANDARD,
75   /** 0.5 mA */
76   gpioDriveModeLowest   = GPIO_P_CTRL_DRIVEMODE_LOWEST,
77   /** 20 mA */
78   gpioDriveModeHigh     = GPIO_P_CTRL_DRIVEMODE_HIGH,
79   /** 2 mA */
80   gpioDriveModeLow      = GPIO_P_CTRL_DRIVEMODE_LOW
81 } GPIO_DriveMode_TypeDef;
82 
83 /** Pin mode. For more details on each mode, please refer to the EFM32
84  * reference manual. */
85 typedef enum
86 {
87   /** Input disabled. Pullup if DOUT is set. */
88   gpioModeDisabled                  = _GPIO_P_MODEL_MODE0_DISABLED,
89   /** Input enabled. Filter if DOUT is set */
90   gpioModeInput                     = _GPIO_P_MODEL_MODE0_INPUT,
91   /** Input enabled. DOUT determines pull direction */
92   gpioModeInputPull                 = _GPIO_P_MODEL_MODE0_INPUTPULL,
93   /** Input enabled with filter. DOUT determines pull direction */
94   gpioModeInputPullFilter           = _GPIO_P_MODEL_MODE0_INPUTPULLFILTER,
95   /** Push-pull output */
96   gpioModePushPull                  = _GPIO_P_MODEL_MODE0_PUSHPULL,
97   /** Push-pull output with drive-strength set by DRIVEMODE */
98   gpioModePushPullDrive             = _GPIO_P_MODEL_MODE0_PUSHPULLDRIVE,
99   /** Wired-or output */
100   gpioModeWiredOr                   = _GPIO_P_MODEL_MODE0_WIREDOR,
101   /** Wired-or output with pull-down */
102   gpioModeWiredOrPullDown           = _GPIO_P_MODEL_MODE0_WIREDORPULLDOWN,
103   /** Open-drain output */
104   gpioModeWiredAnd                  = _GPIO_P_MODEL_MODE0_WIREDAND,
105   /** Open-drain output with filter */
106   gpioModeWiredAndFilter            = _GPIO_P_MODEL_MODE0_WIREDANDFILTER,
107   /** Open-drain output with pullup */
108   gpioModeWiredAndPullUp            = _GPIO_P_MODEL_MODE0_WIREDANDPULLUP,
109   /** Open-drain output with filter and pullup */
110   gpioModeWiredAndPullUpFilter      = _GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER,
111   /** Open-drain output with drive-strength set by DRIVEMODE */
112   gpioModeWiredAndDrive             = _GPIO_P_MODEL_MODE0_WIREDANDDRIVE,
113   /** Open-drain output with filter and drive-strength set by DRIVEMODE */
114   gpioModeWiredAndDriveFilter       = _GPIO_P_MODEL_MODE0_WIREDANDDRIVEFILTER,
115   /** Open-drain output with pullup and drive-strength set by DRIVEMODE */
116   gpioModeWiredAndDrivePullUp       = _GPIO_P_MODEL_MODE0_WIREDANDDRIVEPULLUP,
117   /** Open-drain output with filter, pullup and drive-strength set by DRIVEMODE */
118   gpioModeWiredAndDrivePullUpFilter = _GPIO_P_MODEL_MODE0_WIREDANDDRIVEPULLUPFILTER
119 } GPIO_Mode_TypeDef;
120 
121 /*******************************************************************************
122  *****************************   PROTOTYPES   **********************************
123  ******************************************************************************/
124 
125 void GPIO_DbgLocationSet(unsigned int location);
126 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
127 __STATIC_INLINE void GPIO_EM4SetPinRetention(bool enable);
128 #endif
129 
130 /***************************************************************************//**
131  * @brief
132  *   Enable/disable serial wire clock pin.
133  *
134  * @note
135  *   Disabling SWDClk will disable the debug interface, which may result in
136  *   a lockout if done early in startup (before debugger is able to halt core).
137  *
138  * @param[in] enable
139  *   @li false - disable serial wire clock.
140  *   @li true - enable serial wire clock (default after reset).
141  ******************************************************************************/
GPIO_DbgSWDClkEnable(bool enable)142 __STATIC_INLINE void GPIO_DbgSWDClkEnable(bool enable)
143 {
144   BITBAND_Peripheral(&(GPIO->ROUTE), _GPIO_ROUTE_SWCLKPEN_SHIFT, (unsigned int)enable);
145 }
146 
147 
148 /***************************************************************************//**
149  * @brief
150  *   Enable/disable serial wire data pin.
151  *
152  * @note
153  *   Disabling SWDClk will disable the debug interface, which may result in
154  *   a lockout if done early in startup (before debugger is able to halt core).
155  *
156  * @param[in] enable
157  *   @li false - disable serial wire data pin.
158  *   @li true - enable serial wire data pin (default after reset).
159  ******************************************************************************/
GPIO_DbgSWDIOEnable(bool enable)160 __STATIC_INLINE void GPIO_DbgSWDIOEnable(bool enable)
161 {
162   BITBAND_Peripheral(&(GPIO->ROUTE), _GPIO_ROUTE_SWDIOPEN_SHIFT, (unsigned int)enable);
163 }
164 
165 
166 /***************************************************************************//**
167  * @brief
168  *   Enable/Disable serial wire output pin.
169  *
170  * @note
171  *   Enabling this pin is not sufficient to fully enable serial wire output
172  *   which is also dependent on issues outside the GPIO module. Please refer to
173  *   DBG_SWOEnable().
174  *
175  * @param[in] enable
176  *   @li false - disable serial wire viewer pin (default after reset).
177  *   @li true - enable serial wire viewer pin.
178  ******************************************************************************/
GPIO_DbgSWOEnable(bool enable)179 __STATIC_INLINE void GPIO_DbgSWOEnable(bool enable)
180 {
181   BITBAND_Peripheral(&(GPIO->ROUTE), _GPIO_ROUTE_SWOPEN_SHIFT, (unsigned int)enable);
182 }
183 
184 
185 void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode);
186 
187 
188 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
189 /**************************************************************************//**
190  * @brief
191  *   Disable GPIO pin wake-up from EM4.
192  *
193  * @param[in] pinmask
194  *   Bitmask containing the bitwise logic OR of which GPIO pin(s) to disable.
195  *   Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
196  *****************************************************************************/
GPIO_EM4DisablePinWakeup(uint32_t pinmask)197 __STATIC_INLINE void GPIO_EM4DisablePinWakeup(uint32_t pinmask)
198 {
199   EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
200 
201   GPIO->EM4WUEN &= ~pinmask;
202 }
203 
204 
205 /**************************************************************************//**
206  * @brief
207  *   Enable GPIO pin wake-up from EM4. When the function exits,
208  *   EM4 mode can be safely entered.
209  *
210  * @note
211  *   It is assumed that the GPIO pin modes are set correctly.
212  *   Valid modes are @ref gpioModeInput and @ref gpioModeInputPull.
213  *
214  * @param[in] pinmask
215  *   Bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.
216  *   Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
217  * @param[in] polaritymask
218  *   Bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.
219  *   Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
220  *****************************************************************************/
GPIO_EM4EnablePinWakeup(uint32_t pinmask,uint32_t polaritymask)221 __STATIC_INLINE void GPIO_EM4EnablePinWakeup(uint32_t pinmask,
222                                              uint32_t polaritymask)
223 {
224   EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
225   EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);
226 
227   GPIO->EM4WUPOL &= ~pinmask;               /* Set wakeup polarity */
228   GPIO->EM4WUPOL |= pinmask & polaritymask;
229   GPIO->EM4WUEN  |= pinmask;                /* Enable wakeup */
230 
231   GPIO_EM4SetPinRetention(true);            /* Enable pin retention */
232 
233   GPIO->CMD = GPIO_CMD_EM4WUCLR;            /* Clear wake-up logic */
234 }
235 
236 /**************************************************************************//**
237  * @brief
238  *   Check which GPIO pin(s) that caused a wake-up from EM4.
239  *
240  * @return
241  *   Bitmask containing the bitwise logic OR of which GPIO pin(s) caused the
242  *   wake-up. Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
243  *****************************************************************************/
GPIO_EM4GetPinWakeupCause(void)244 __STATIC_INLINE uint32_t GPIO_EM4GetPinWakeupCause(void)
245 {
246   return GPIO->EM4WUCAUSE & _GPIO_EM4WUCAUSE_MASK;
247 }
248 
249 
250 /**************************************************************************//**
251  * @brief
252  *   Enable GPIO pin retention of output enable, output value, pull enable and
253  *   pull direction in EM4.
254  *
255  * @param[in] enable
256  *   @li true - enable EM4 pin retention.
257  *   @li false - disable EM4 pin retention.
258  *****************************************************************************/
GPIO_EM4SetPinRetention(bool enable)259 __STATIC_INLINE void GPIO_EM4SetPinRetention(bool enable)
260 {
261   if (enable)
262   {
263     GPIO->CTRL |= GPIO_CTRL_EM4RET;
264   }
265   else
266   {
267     GPIO->CTRL &= ~GPIO_CTRL_EM4RET;
268   }
269 }
270 #endif
271 
272 
273 /***************************************************************************//**
274  * @brief
275  *   Enable/disable input sensing.
276  *
277  * @details
278  *   Disabling input sensing if not used, can save some energy consumption.
279  *
280  * @param[in] val
281  *   Bitwise logic OR of one or more of:
282  *   @li GPIO_INSENSE_INTSENSE - interrupt input sensing.
283  *   @li GPIO_INSENSE_PRSSENSE - peripheral reflex system input sensing.
284  *
285  * @param[in] mask
286  *   Mask containing bitwise logic OR of bits similar as for @p val used to indicate
287  *   which input sense options to disable/enable.
288  ******************************************************************************/
GPIO_InputSenseSet(uint32_t val,uint32_t mask)289 __STATIC_INLINE void GPIO_InputSenseSet(uint32_t val, uint32_t mask)
290 {
291   GPIO->INSENSE = (GPIO->INSENSE & ~mask) | (val & mask);
292 }
293 
294 
295 /***************************************************************************//**
296  * @brief
297  *   Clear one or more pending GPIO interrupts.
298  *
299  * @param[in] flags
300  *   Bitwise logic OR of GPIO interrupt sources to clear.
301  ******************************************************************************/
GPIO_IntClear(uint32_t flags)302 __STATIC_INLINE void GPIO_IntClear(uint32_t flags)
303 {
304   GPIO->IFC = flags;
305 }
306 
307 
308 void GPIO_IntConfig(GPIO_Port_TypeDef port,
309                     unsigned int pin,
310                     bool risingEdge,
311                     bool fallingEdge,
312                     bool enable);
313 
314 
315 /***************************************************************************//**
316  * @brief
317  *   Disable one or more GPIO interrupts.
318  *
319  * @param[in] flags
320  *   GPIO interrupt sources to disable.
321  ******************************************************************************/
GPIO_IntDisable(uint32_t flags)322 __STATIC_INLINE void GPIO_IntDisable(uint32_t flags)
323 {
324   GPIO->IEN &= ~flags;
325 }
326 
327 
328 /***************************************************************************//**
329  * @brief
330  *   Enable one or more GPIO interrupts.
331  *
332  * @note
333  *   Depending on the use, a pending interrupt may already be set prior to
334  *   enabling the interrupt. Consider using GPIO_IntClear() prior to enabling
335  *   if such a pending interrupt should be ignored.
336  *
337  * @param[in] flags
338  *   GPIO interrupt sources to enable.
339  ******************************************************************************/
GPIO_IntEnable(uint32_t flags)340 __STATIC_INLINE void GPIO_IntEnable(uint32_t flags)
341 {
342   GPIO->IEN |= flags;
343 }
344 
345 
346 /***************************************************************************//**
347  * @brief
348  *   Get pending GPIO interrupts.
349  *
350  * @return
351  *   GPIO interrupt sources pending.
352  ******************************************************************************/
GPIO_IntGet(void)353 __STATIC_INLINE uint32_t GPIO_IntGet(void)
354 {
355   return(GPIO->IF);
356 }
357 
358 
359 /***************************************************************************//**
360  * @brief
361  *   Get enabled and pending GPIO interrupt flags.
362  *   Useful for handling more interrupt sources in the same interrupt handler.
363  *
364  * @note
365  *   Interrupt flags are not cleared by the use of this function.
366  *
367  * @return
368  *   Pending and enabled GPIO interrupt sources.
369  *   The return value is the bitwise AND combination of
370  *   - the OR combination of enabled interrupt sources in GPIO_IEN register
371  *     and
372  *   - the OR combination of valid interrupt flags in GPIO_IF register.
373  ******************************************************************************/
GPIO_IntGetEnabled(void)374 __STATIC_INLINE uint32_t GPIO_IntGetEnabled(void)
375 {
376   uint32_t tmp;
377 
378   /* Store GPIO->IEN in temporary variable in order to define explicit order
379    * of volatile accesses. */
380   tmp = GPIO->IEN;
381 
382   /* Bitwise AND of pending and enabled interrupts */
383   return GPIO->IF & tmp;
384 }
385 
386 
387 /**************************************************************************//**
388  * @brief
389  *   Set one or more pending GPIO interrupts from SW.
390  *
391  * @param[in] flags
392  *   GPIO interrupt sources to set to pending.
393  *****************************************************************************/
GPIO_IntSet(uint32_t flags)394 __STATIC_INLINE void GPIO_IntSet(uint32_t flags)
395 {
396   GPIO->IFS = flags;
397 }
398 
399 
400 /***************************************************************************//**
401  * @brief
402  *   Locks the GPIO configuration.
403  ******************************************************************************/
GPIO_Lock(void)404 __STATIC_INLINE void GPIO_Lock(void)
405 {
406   GPIO->LOCK = GPIO_LOCK_LOCKKEY_LOCK;
407 }
408 
409 
410 unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin);
411 void GPIO_PinModeSet(GPIO_Port_TypeDef port,
412                      unsigned int pin,
413                      GPIO_Mode_TypeDef mode,
414                      unsigned int out);
415 void GPIO_PinOutClear(GPIO_Port_TypeDef port, unsigned int pin);
416 unsigned int GPIO_PinOutGet(GPIO_Port_TypeDef port, unsigned int pin);
417 void GPIO_PinOutSet(GPIO_Port_TypeDef port, unsigned int pin);
418 void GPIO_PinOutToggle(GPIO_Port_TypeDef port, unsigned int pin);
419 
420 uint32_t GPIO_PortInGet(GPIO_Port_TypeDef port);
421 void GPIO_PortOutClear(GPIO_Port_TypeDef port, uint32_t pins);
422 uint32_t GPIO_PortOutGet(GPIO_Port_TypeDef port);
423 void GPIO_PortOutSet(GPIO_Port_TypeDef port, uint32_t pins);
424 void GPIO_PortOutSetVal(GPIO_Port_TypeDef port, uint32_t val, uint32_t mask);
425 void GPIO_PortOutToggle(GPIO_Port_TypeDef port, uint32_t pins);
426 
427 /***************************************************************************//**
428  * @brief
429  *   Unlocks the GPIO configuration.
430  ******************************************************************************/
GPIO_Unlock(void)431 __STATIC_INLINE void GPIO_Unlock(void)
432 {
433   GPIO->LOCK = GPIO_LOCK_LOCKKEY_UNLOCK;
434 }
435 
436 
437 /** @} (end addtogroup GPIO) */
438 /** @} (end addtogroup EM_Library) */
439 
440 #ifdef __cplusplus
441 }
442 #endif
443 
444 #endif /* __EM_GPIO_H */
445