2011-02-17 11:33:15 +08:00
|
|
|
/***************************************************************************//**
|
|
|
|
* @file
|
|
|
|
* @brief General Purpose IO (GPIO) peripheral API for EFM32
|
|
|
|
* devices.
|
|
|
|
* @author Energy Micro AS
|
2011-12-27 15:44:29 +08:00
|
|
|
* @version 2.3.2
|
2011-02-17 11:33:15 +08:00
|
|
|
*******************************************************************************
|
|
|
|
* @section License
|
|
|
|
* <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
|
|
|
|
*******************************************************************************
|
|
|
|
*
|
|
|
|
* This source code is the property of Energy Micro AS. The source and compiled
|
|
|
|
* code may only be used on Energy Micro "EFM32" microcontrollers.
|
|
|
|
*
|
|
|
|
* This copyright notice may not be removed from the source code nor changed.
|
|
|
|
*
|
|
|
|
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
|
|
|
|
* obligation to support this Software. Energy Micro AS is providing the
|
|
|
|
* Software "AS IS", with no express or implied warranties of any kind,
|
|
|
|
* including, but not limited to, any implied warranties of merchantability
|
|
|
|
* or fitness for any particular purpose or warranties against infringement
|
|
|
|
* of any proprietary rights of a third party.
|
|
|
|
*
|
|
|
|
* Energy Micro AS will not be liable for any consequential, incidental, or
|
|
|
|
* special damages, or any other relief, or for any claim by any third party,
|
|
|
|
* arising from your use of this Software.
|
|
|
|
*
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#include "efm32_gpio.h"
|
|
|
|
#include "efm32_bitband.h"
|
|
|
|
#include "efm32_assert.h"
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @addtogroup EFM32_Library
|
|
|
|
* @{
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @addtogroup GPIO
|
2011-06-20 09:56:28 +08:00
|
|
|
* @brief General Purpose Input/Output (GPIO) API for EFM32
|
2011-02-17 11:33:15 +08:00
|
|
|
* @{
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
******************************* DEFINES ***********************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
|
|
|
|
|
|
|
/** Validation of pin typically usable in assert statements. */
|
|
|
|
#define GPIO_DRIVEMODE_VALID(mode) ((mode) <= 3)
|
|
|
|
|
|
|
|
/** Validation of pin typically usable in assert statements. */
|
|
|
|
#define GPIO_PIN_VALID(pin) ((pin) < 16)
|
|
|
|
|
|
|
|
/** Validation of port typically usable in assert statements. */
|
|
|
|
#define GPIO_PORT_VALID(port) ((port) <= gpioPortF)
|
|
|
|
|
2011-06-20 09:56:28 +08:00
|
|
|
/** @endcond */
|
2011-02-17 11:33:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
************************** GLOBAL FUNCTIONS *******************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Sets the pin location of the debug pins (Serial Wire interface).
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* Changing the pins used for debugging uncontrolled, may result in a lockout.
|
|
|
|
*
|
|
|
|
* @param[in] location
|
|
|
|
* The debug pin location to use (0-3).
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_DbgLocationSet(unsigned int location)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(location < AFCHANLOC_MAX);
|
|
|
|
|
|
|
|
GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) |
|
|
|
|
(location << _GPIO_ROUTE_SWLOCATION_SHIFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Sets the drive mode for a GPIO port.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] mode
|
|
|
|
* Drive mode to use for port.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));
|
|
|
|
|
|
|
|
GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))
|
|
|
|
| (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Configure GPIO interrupt.
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* If reconfiguring a GPIO interrupt that is already enabled, it is generally
|
|
|
|
* recommended to disable it first, see GPIO_Disable().
|
|
|
|
*
|
|
|
|
* The actual GPIO interrupt handler must be in place before enabling the
|
|
|
|
* interrupt.
|
|
|
|
*
|
|
|
|
* Notice that any pending interrupt for the selected pin is cleared by this
|
|
|
|
* function.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* A certain pin number can only be associated with one port. Ie, if GPIO
|
|
|
|
* interrupt 1 is assigned to port A/pin 1, then it is not possibly to use
|
|
|
|
* pin 1 from any other ports for interrupts. Please refer to the reference
|
|
|
|
* manual.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The port to associate with @p pin.
|
|
|
|
*
|
|
|
|
* @param[in] pin
|
|
|
|
* The GPIO interrupt number (= port pin).
|
|
|
|
*
|
|
|
|
* @param[in] risingEdge
|
|
|
|
* Set to true if interrupts shall be enabled on rising edge, otherwise false.
|
|
|
|
*
|
|
|
|
* @param[in] fallingEdge
|
|
|
|
* Set to true if interrupts shall be enabled on falling edge, otherwise false.
|
|
|
|
*
|
|
|
|
* @param[in] enable
|
|
|
|
* Set to true if interrupt shall be enabled after configuration completed,
|
|
|
|
* false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_IntConfig(GPIO_Port_TypeDef port,
|
|
|
|
unsigned int pin,
|
|
|
|
bool risingEdge,
|
|
|
|
bool fallingEdge,
|
|
|
|
bool enable)
|
|
|
|
{
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
|
|
|
|
|
|
|
|
/* There are two registers controlling the interrupt configuration:
|
|
|
|
* The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls
|
|
|
|
* pins 8-15. */
|
|
|
|
if (pin < 8)
|
|
|
|
{
|
|
|
|
GPIO->EXTIPSELL = (GPIO->EXTIPSELL & ~(0xF << (4 * pin))) |
|
|
|
|
(port << (4 * pin));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp = pin - 8;
|
|
|
|
GPIO->EXTIPSELH = (GPIO->EXTIPSELH & ~(0xF << (4 * tmp))) |
|
|
|
|
(port << (4 * tmp));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enable/disable rising edge */
|
2011-06-20 09:56:28 +08:00
|
|
|
BITBAND_Peripheral(&(GPIO->EXTIRISE), pin, (unsigned int)risingEdge);
|
2011-02-17 11:33:15 +08:00
|
|
|
|
|
|
|
/* Enable/disable falling edge */
|
2011-06-20 09:56:28 +08:00
|
|
|
BITBAND_Peripheral(&(GPIO->EXTIFALL), pin, (unsigned int)fallingEdge);
|
2011-02-17 11:33:15 +08:00
|
|
|
|
|
|
|
/* Clear any pending interrupt */
|
|
|
|
GPIO->IFC = 1 << pin;
|
|
|
|
|
|
|
|
/* Finally enable/disable interrupt */
|
2011-06-20 09:56:28 +08:00
|
|
|
BITBAND_Peripheral(&(GPIO->IEN), pin, (unsigned int)enable);
|
2011-02-17 11:33:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Read the pad value for a single pin in a GPIO port.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pin
|
|
|
|
* The pin number to read.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* The pin value, 0 or 1.
|
|
|
|
******************************************************************************/
|
|
|
|
unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
|
|
|
|
|
|
|
|
return((unsigned int)((GPIO->P[port].DIN >> pin) & 0x1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Set the mode for a GPIO pin.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pin
|
|
|
|
* The pin number in the port.
|
|
|
|
*
|
|
|
|
* @param[in] mode
|
|
|
|
* The desired pin mode.
|
|
|
|
*
|
|
|
|
* @param[in] out
|
|
|
|
* Value to set for pin in DOUT register. The DOUT setting is important for
|
|
|
|
* even some input mode configurations, determining pull-up/down direction.
|
|
|
|
* Notice that this parameter is not used if disabling a pin, leaving the
|
|
|
|
* corresponding DOUT bit unchanged.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PinModeSet(GPIO_Port_TypeDef port,
|
|
|
|
unsigned int pin,
|
|
|
|
GPIO_Mode_TypeDef mode,
|
|
|
|
unsigned int out)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
|
|
|
|
|
|
|
|
/* If disabling pin, do not modify DOUT in order to reduce chance for */
|
|
|
|
/* glitch/spike (may not be sufficient precaution in all use cases) */
|
|
|
|
if (mode != gpioModeDisabled)
|
|
|
|
{
|
|
|
|
if (out)
|
|
|
|
{
|
|
|
|
GPIO->P[port].DOUTSET = 1 << pin;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GPIO->P[port].DOUTCLR = 1 << pin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There are two registers controlling the pins for each port. The MODEL
|
|
|
|
* register controls pins 0-7 and MODEH controls pins 8-15. */
|
|
|
|
if (pin < 8)
|
|
|
|
{
|
|
|
|
GPIO->P[port].MODEL = (GPIO->P[port].MODEL & ~(0xF << (pin * 4))) |
|
|
|
|
(mode << (pin * 4));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GPIO->P[port].MODEH = (GPIO->P[port].MODEH & ~(0xF << ((pin - 8) * 4))) |
|
|
|
|
(mode << ((pin - 8) * 4));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == gpioModeDisabled)
|
|
|
|
{
|
|
|
|
if (out)
|
|
|
|
{
|
|
|
|
GPIO->P[port].DOUTSET = 1 << pin;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GPIO->P[port].DOUTCLR = 1 << pin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Set a single pin in GPIO data out port register to 0.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* In order for the setting to take effect on the output pad, the pin must
|
|
|
|
* have been configured properly. If not, it will take effect whenever the
|
|
|
|
* pin has been properly configured.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pin
|
|
|
|
* The pin to set.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PinOutClear(GPIO_Port_TypeDef port, unsigned int pin)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
|
|
|
|
|
|
|
|
GPIO->P[port].DOUTCLR = 1 << pin;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Get current setting for a pin in a GPIO port data out register.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pin
|
|
|
|
* The pin to get setting for.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* The DOUT setting for the requested pin, 0 or 1.
|
|
|
|
******************************************************************************/
|
|
|
|
unsigned int GPIO_PinOutGet(GPIO_Port_TypeDef port, unsigned int pin)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
|
|
|
|
|
|
|
|
return((unsigned int)((GPIO->P[port].DOUT >> pin) & 0x1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Set a single pin in GPIO data out register to 1.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* In order for the setting to take effect on the output pad, the pin must
|
|
|
|
* have been configured properly. If not, it will take effect whenever the
|
|
|
|
* pin has been properly configured.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pin
|
|
|
|
* The pin to set.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PinOutSet(GPIO_Port_TypeDef port, unsigned int pin)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
|
|
|
|
|
|
|
|
GPIO->P[port].DOUTSET = 1 << pin;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Toggle a single pin in GPIO port data out register.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* In order for the setting to take effect on the output pad, the pin must
|
|
|
|
* have been configured properly. If not, it will take effect whenever the
|
|
|
|
* pin has been properly configured.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pin
|
|
|
|
* The pin to toggle.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PinOutToggle(GPIO_Port_TypeDef port, unsigned int pin)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
|
|
|
|
|
|
|
|
GPIO->P[port].DOUTTGL = 1 << pin;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Read the pad values for GPIO port.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
******************************************************************************/
|
|
|
|
uint32_t GPIO_PortInGet(GPIO_Port_TypeDef port)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port));
|
|
|
|
|
|
|
|
return(GPIO->P[port].DIN & _GPIO_P_DIN_DIN_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Set bits in DOUT register for a port to 0.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* In order for the setting to take effect on the output pad, the pin must
|
|
|
|
* have been configured properly. If not, it will take effect whenever the
|
|
|
|
* pin has been properly configured.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pins
|
|
|
|
* Bit mask for bits to clear in DOUT register.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PortOutClear(GPIO_Port_TypeDef port, uint32_t pins)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port));
|
|
|
|
|
|
|
|
GPIO->P[port].DOUTCLR = pins & _GPIO_P_DOUTCLR_DOUTCLR_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Get current setting for a GPIO port data out register.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* The data out setting for the requested port.
|
|
|
|
******************************************************************************/
|
|
|
|
uint32_t GPIO_PortOutGet(GPIO_Port_TypeDef port)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port));
|
|
|
|
|
|
|
|
return(GPIO->P[port].DOUT & _GPIO_P_DOUT_DOUT_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Set bits GPIO data out register to 1.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* In order for the setting to take effect on the respective output pads, the
|
|
|
|
* pins must have been configured properly. If not, it will take effect
|
|
|
|
* whenever the pin has been properly configured.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pins
|
|
|
|
* Bit mask for bits to set to 1 in DOUT register.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PortOutSet(GPIO_Port_TypeDef port, uint32_t pins)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port));
|
|
|
|
|
|
|
|
GPIO->P[port].DOUTSET = pins & _GPIO_P_DOUTSET_DOUTSET_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Set GPIO port data out register.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* In order for the setting to take effect on the respective output pads, the
|
|
|
|
* pins must have been configured properly. If not, it will take effect
|
|
|
|
* whenever the pin has been properly configured.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] val
|
|
|
|
* Value to write to port data out register.
|
|
|
|
*
|
|
|
|
* @param[in] mask
|
|
|
|
* Mask indicating which bits to modify.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PortOutSetVal(GPIO_Port_TypeDef port, uint32_t val, uint32_t mask)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port));
|
|
|
|
|
|
|
|
GPIO->P[port].DOUT = (GPIO->P[port].DOUT & ~mask) | (val & mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Toggle a single pin in GPIO port data out register.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* In order for the setting to take effect on the output pad, the pin must
|
|
|
|
* have been configured properly. If not, it will take effect whenever the
|
|
|
|
* pin has been properly configured.
|
|
|
|
*
|
|
|
|
* @param[in] port
|
|
|
|
* The GPIO port to access.
|
|
|
|
*
|
|
|
|
* @param[in] pins
|
|
|
|
* Bitmask with pins to toggle.
|
|
|
|
******************************************************************************/
|
|
|
|
void GPIO_PortOutToggle(GPIO_Port_TypeDef port, uint32_t pins)
|
|
|
|
{
|
|
|
|
EFM_ASSERT(GPIO_PORT_VALID(port));
|
|
|
|
|
|
|
|
GPIO->P[port].DOUTTGL = pins & _GPIO_P_DOUTTGL_DOUTTGL_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} (end addtogroup GPIO) */
|
|
|
|
/** @} (end addtogroup EFM32_Library) */
|