843 lines
22 KiB
C
843 lines
22 KiB
C
/*****************************************************************************
|
|
*
|
|
* \file
|
|
*
|
|
* \brief GPIO software driver interface for AVR UC3.
|
|
*
|
|
* Copyright (c) 2010-2018 Microchip Technology Inc. and its subsidiaries.
|
|
*
|
|
* \asf_license_start
|
|
*
|
|
* \page License
|
|
*
|
|
* Subject to your compliance with these terms, you may use Microchip
|
|
* software and any derivatives exclusively with Microchip products.
|
|
* It is your responsibility to comply with third party license terms applicable
|
|
* to your use of third party software (including open source software) that
|
|
* may accompany Microchip software.
|
|
*
|
|
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
|
|
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
|
|
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
|
|
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
|
|
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
|
|
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
|
|
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
|
|
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
|
|
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
|
|
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
|
|
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
|
|
*
|
|
* \asf_license_stop
|
|
*
|
|
*****************************************************************************/
|
|
/*
|
|
* Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
|
|
*/
|
|
|
|
#include "gpio.h"
|
|
|
|
/** \name Peripheral Bus Interface
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/** \brief Enables specific module modes for a set of pins.
|
|
*
|
|
* \param gpiomap The pin map.
|
|
* \param size The number of pins in \a gpiomap.
|
|
*
|
|
* \return \ref GPIO_SUCCESS or \ref GPIO_INVALID_ARGUMENT.
|
|
*/
|
|
uint32_t gpio_enable_module(const gpio_map_t gpiomap, uint32_t size)
|
|
{
|
|
uint32_t status = GPIO_SUCCESS;
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
status |= gpio_enable_module_pin(gpiomap->pin, gpiomap->function);
|
|
gpiomap++;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/** \brief Enables a specific module mode for a pin.
|
|
*
|
|
* \note A pin and pin function index can be found in the device part header
|
|
* file. The \c AVR32_*_PIN constants map a GPIO number from the device
|
|
* datasheet to the appropriate pin function, while the corresponding
|
|
* \c AVR32_*_FUNCTION macro contains the appropriate function index.
|
|
* \n\n
|
|
* For example, the constants \c AVR32_PWM_3_PIN and
|
|
* \c AVR32_PWM_3_FUNCTION contain the pin and function index of the PWM
|
|
* module, channel 3, for the current device (if available).
|
|
*
|
|
* \param pin The pin number.
|
|
* \param function The pin function.
|
|
*
|
|
* \return \ref GPIO_SUCCESS or \ref GPIO_INVALID_ARGUMENT.
|
|
*/
|
|
uint32_t gpio_enable_module_pin(uint32_t pin, uint32_t function)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Enable the correct function. */
|
|
switch (function) {
|
|
case 0: /* A function. */
|
|
gpio_port->pmr0c = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1c = 1 << (pin & 0x1F);
|
|
#if (AVR32_GPIO_H_VERSION >= 210)
|
|
gpio_port->pmr2c = 1 << (pin & 0x1F);
|
|
#endif
|
|
break;
|
|
|
|
case 1: /* B function. */
|
|
gpio_port->pmr0s = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1c = 1 << (pin & 0x1F);
|
|
#if (AVR32_GPIO_H_VERSION >= 210)
|
|
gpio_port->pmr2c = 1 << (pin & 0x1F);
|
|
#endif
|
|
break;
|
|
|
|
case 2: /* C function. */
|
|
gpio_port->pmr0c = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1s = 1 << (pin & 0x1F);
|
|
#if (AVR32_GPIO_H_VERSION >= 210)
|
|
gpio_port->pmr2c = 1 << (pin & 0x1F);
|
|
#endif
|
|
break;
|
|
|
|
case 3: /* D function. */
|
|
gpio_port->pmr0s = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1s = 1 << (pin & 0x1F);
|
|
#if (AVR32_GPIO_H_VERSION >= 210)
|
|
gpio_port->pmr2c = 1 << (pin & 0x1F);
|
|
#endif
|
|
break;
|
|
|
|
#if (AVR32_GPIO_H_VERSION >= 210)
|
|
case 4: /* E function. */
|
|
gpio_port->pmr0c = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1c = 1 << (pin & 0x1F);
|
|
gpio_port->pmr2s = 1 << (pin & 0x1F);
|
|
break;
|
|
|
|
case 5: /* F function. */
|
|
gpio_port->pmr0s = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1c = 1 << (pin & 0x1F);
|
|
gpio_port->pmr2s = 1 << (pin & 0x1F);
|
|
break;
|
|
|
|
case 6: /* G function. */
|
|
gpio_port->pmr0c = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1s = 1 << (pin & 0x1F);
|
|
gpio_port->pmr2s = 1 << (pin & 0x1F);
|
|
break;
|
|
|
|
case 7: /* H function. */
|
|
gpio_port->pmr0s = 1 << (pin & 0x1F);
|
|
gpio_port->pmr1s = 1 << (pin & 0x1F);
|
|
gpio_port->pmr2s = 1 << (pin & 0x1F);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
return GPIO_INVALID_ARGUMENT;
|
|
}
|
|
|
|
/* Disable GPIO control. */
|
|
gpio_port->gperc = 1 << (pin & 0x1F);
|
|
|
|
return GPIO_SUCCESS;
|
|
}
|
|
|
|
/** \brief Enables the GPIO mode of a set of pins.
|
|
*
|
|
* \param gpiomap The pin map.
|
|
* \param size The number of pins in \a gpiomap.
|
|
*/
|
|
void gpio_enable_gpio(const gpio_map_t gpiomap, uint32_t size)
|
|
{
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
gpio_enable_gpio_pin(gpiomap->pin);
|
|
gpiomap++;
|
|
}
|
|
}
|
|
|
|
/** \brief Enables the GPIO mode of a pin.
|
|
*
|
|
* \param pin The pin number.\n
|
|
* Refer to the product header file `uc3x.h' (where x is the part
|
|
* number; e.g. x = a0512) for pin definitions. E.g., to enable the
|
|
* GPIO mode of PX21, AVR32_PIN_PX21 can be used. Module pins such as
|
|
* AVR32_PWM_3_PIN for PWM channel 3 can also be used to release
|
|
* module pins for GPIO.
|
|
*/
|
|
void gpio_enable_gpio_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->oderc = 1 << (pin & 0x1F);
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Enables the pull-up resistor of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_enable_pin_pull_up(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->puers = 1 << (pin & 0x1F);
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
gpio_port->pderc = 1 << (pin & 0x1F);
|
|
#endif
|
|
}
|
|
|
|
/** \brief Disables the pull-up resistor of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_disable_pin_pull_up(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->puerc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
/* Added support of Pull-up Resistor, Pull-down Resistor and Buskeeper Control. */
|
|
|
|
/** \brief Enables the pull-down resistor of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_enable_pin_pull_down(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->puerc = 1 << (pin & 0x1F);
|
|
gpio_port->pders = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Disables the pull-down resistor of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_disable_pin_pull_down(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->pderc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Enables the buskeeper functionality on a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_enable_pin_buskeeper(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->puers = 1 << (pin & 0x1F);
|
|
gpio_port->pders = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Disables the buskeeper functionality on a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_disable_pin_buskeeper(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->puerc = 1 << (pin & 0x1F);
|
|
gpio_port->pderc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
#endif
|
|
|
|
/** \brief Configuration functionality on a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
* \param flags The configuration.
|
|
*/
|
|
void gpio_configure_pin(uint32_t pin, uint32_t flags)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Both pull-up and pull-down set means buskeeper */
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
if (flags & GPIO_PULL_DOWN) {
|
|
gpio_port->pders = 1 << (pin & 0x1F);
|
|
} else {
|
|
gpio_port->pderc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
#endif
|
|
if (flags & GPIO_PULL_UP) {
|
|
gpio_port->puers = 1 << (pin & 0x1F);
|
|
} else {
|
|
gpio_port->puerc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/* Enable open-drain mode if requested */
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
if (flags & GPIO_OPEN_DRAIN) {
|
|
gpio_port->odmers = 1 << (pin & 0x1F);
|
|
} else {
|
|
gpio_port->odmerc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
/* Select drive strength */
|
|
if (flags & GPIO_DRIVE_LOW) {
|
|
gpio_port->odcr0s = 1 << (pin & 0x1F);
|
|
} else {
|
|
gpio_port->odcr0c = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
if (flags & GPIO_DRIVE_HIGH) {
|
|
gpio_port->odcr1s = 1 << (pin & 0x1F);
|
|
} else {
|
|
gpio_port->odcr1c = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Select interrupt level for group */
|
|
if (flags & GPIO_INTERRUPT) {
|
|
if (flags & GPIO_BOTHEDGES) {
|
|
gpio_port->imr0c = 1 << (pin & 0x1F);
|
|
gpio_port->imr1c = 1 << (pin & 0x1F);
|
|
} else if (flags & GPIO_RISING) {
|
|
gpio_port->imr0s = 1 << (pin & 0x1F);
|
|
gpio_port->imr1c = 1 << (pin & 0x1F);
|
|
} else if (flags & GPIO_FALLING) {
|
|
gpio_port->imr0c = 1 << (pin & 0x1F);
|
|
gpio_port->imr1s = 1 << (pin & 0x1F);
|
|
}
|
|
}
|
|
|
|
/* Select direction and initial pin state */
|
|
if (flags & GPIO_DIR_OUTPUT) {
|
|
if (flags & GPIO_INIT_HIGH) {
|
|
gpio_port->ovrs = 1 << (pin & 0x1F);
|
|
} else {
|
|
gpio_port->ovrc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
gpio_port->oders = 1 << (pin & 0x1F);
|
|
} else {
|
|
gpio_port->oderc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/* Enable GPIO */
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Configuration functionality on a port.
|
|
*
|
|
* \param port The port number.
|
|
* \param mask The mask.
|
|
* \param flags The configuration.
|
|
*/
|
|
void gpio_configure_group(uint32_t port, uint32_t mask, uint32_t flags)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[port];
|
|
|
|
/* Both pull-up and pull-down set means buskeeper */
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
if (flags & GPIO_PULL_DOWN) {
|
|
gpio_port->pders = mask;
|
|
} else {
|
|
gpio_port->pderc = mask;
|
|
}
|
|
|
|
#endif
|
|
if (flags & GPIO_PULL_UP) {
|
|
gpio_port->puers = mask;
|
|
} else {
|
|
gpio_port->puerc = mask;
|
|
}
|
|
|
|
/* Enable open-drain mode if requested */
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
if (flags & GPIO_OPEN_DRAIN) {
|
|
gpio_port->odmers = mask;
|
|
} else {
|
|
gpio_port->odmerc = mask;
|
|
}
|
|
|
|
if (flags & GPIO_OPEN_DRAIN) {
|
|
gpio_port->pders = mask;
|
|
} else {
|
|
gpio_port->pderc = mask;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(AVR32_GPIO_200_H_INCLUDED) || defined(AVR32_GPIO_210_H_INCLUDED) || \
|
|
defined(AVR32_GPIO_212_H_INCLUDED)
|
|
/* Select drive strength */
|
|
if (flags & GPIO_DRIVE_LOW) {
|
|
gpio_port->odcr0s = mask;
|
|
} else {
|
|
gpio_port->odcr0c = mask;
|
|
}
|
|
|
|
if (flags & GPIO_DRIVE_HIGH) {
|
|
gpio_port->odcr1s = mask;
|
|
} else {
|
|
gpio_port->odcr1c = mask;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Select interrupt level for group */
|
|
if (flags & GPIO_INTERRUPT) {
|
|
if (flags & GPIO_BOTHEDGES) {
|
|
gpio_port->imr0c = mask;
|
|
gpio_port->imr1c = mask;
|
|
} else if (flags & GPIO_RISING) {
|
|
gpio_port->imr0s = mask;
|
|
gpio_port->imr1c = mask;
|
|
} else if (flags & GPIO_FALLING) {
|
|
gpio_port->imr0c = mask;
|
|
gpio_port->imr1s = mask;
|
|
}
|
|
}
|
|
|
|
/* Select direction and initial pin state */
|
|
if (flags & GPIO_DIR_OUTPUT) {
|
|
if (flags & GPIO_INIT_HIGH) {
|
|
gpio_port->ovrs = mask;
|
|
} else {
|
|
gpio_port->ovrc = mask;
|
|
}
|
|
|
|
gpio_port->oders = mask;
|
|
} else {
|
|
gpio_port->oderc = mask;
|
|
}
|
|
|
|
/* Enable GPIO */
|
|
gpio_port->gpers = mask;
|
|
}
|
|
|
|
/** \brief Returns the value of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*
|
|
* \return The pin value.
|
|
*/
|
|
bool gpio_get_pin_value(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
return (gpio_port->pvr >> (pin & 0x1F)) & 1;
|
|
}
|
|
|
|
/** \brief Returns the output value set for a GPIO pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*
|
|
* \return The pin output value.
|
|
*
|
|
* \note This function must be used in conjunction with \ref gpio_set_gpio_pin,
|
|
* \ref gpio_clr_gpio_pin and \ref gpio_tgl_gpio_pin.
|
|
*/
|
|
bool gpio_get_gpio_pin_output_value(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
return (gpio_port->ovr >> (pin & 0x1F)) & 1;
|
|
}
|
|
|
|
/** \brief Returns the output value set for a GPIO pin using open drain.
|
|
*
|
|
* \param pin The pin number.
|
|
*
|
|
* \return The pin output value.
|
|
*
|
|
* \note This function must be used in conjunction with
|
|
* \ref gpio_set_gpio_open_drain_pin, \ref gpio_clr_gpio_open_drain_pin
|
|
* and \ref gpio_tgl_gpio_open_drain_pin.
|
|
*/
|
|
bool gpio_get_gpio_open_drain_pin_output_value(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
return ((gpio_port->oder >> (pin & 0x1F)) & 1) ^ 1;
|
|
}
|
|
|
|
/** \brief Drives a GPIO pin to 1.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_set_gpio_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Value to be driven on the I/O line: 1. */
|
|
gpio_port->ovrs = 1 << (pin & 0x1F);
|
|
/* The GPIO output driver is enabled for that pin. */
|
|
gpio_port->oders = 1 << (pin & 0x1F);
|
|
/* The GPIO module controls that pin. */
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Drives a GPIO pin to 1.
|
|
*
|
|
* \param pin The pin number.
|
|
*
|
|
* \note The function \ref gpio_configure_pin must be called before.
|
|
*/
|
|
void gpio_set_pin_high(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Value to be driven on the I/O line: 1. */
|
|
gpio_port->ovrs = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Drives a GPIO port to 1.
|
|
*
|
|
* \param port The port number.
|
|
* \param mask The mask.
|
|
*/
|
|
void gpio_set_group_high(uint32_t port, uint32_t mask)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[port];
|
|
|
|
/* Value to be driven on the I/O group: 1. */
|
|
gpio_port->ovrs = mask;
|
|
}
|
|
|
|
/** \brief Drives a GPIO pin to 0.
|
|
*
|
|
* \param pin The pin number.
|
|
*
|
|
* \note The function \ref gpio_configure_pin must be called before.
|
|
*/
|
|
void gpio_set_pin_low(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Value to be driven on the I/O line: 0. */
|
|
gpio_port->ovrc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Drives a GPIO pin to 0.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_clr_gpio_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Value to be driven on the I/O line: 0. */
|
|
gpio_port->ovrc = 1 << (pin & 0x1F);
|
|
/* The GPIO output driver is enabled for that pin. */
|
|
gpio_port->oders = 1 << (pin & 0x1F);
|
|
/* The GPIO module controls that pin. */
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Drives a GPIO port to 0.
|
|
*
|
|
* \param port The port number.
|
|
* \param mask The mask.
|
|
*/
|
|
void gpio_set_group_low(uint32_t port, uint32_t mask)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[port];
|
|
|
|
/* Value to be driven on the I/O group: 0. */
|
|
gpio_port->ovrc = mask;
|
|
}
|
|
|
|
/** \brief Toggles a GPIO pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_tgl_gpio_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Toggle the I/O line. */
|
|
gpio_port->ovrt = 1 << (pin & 0x1F);
|
|
/* The GPIO output driver is enabled for that pin. */
|
|
gpio_port->oders = 1 << (pin & 0x1F);
|
|
/* The GPIO module controls that pin. */
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Toggles a GPIO pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*
|
|
* \note The function \ref gpio_configure_pin must be called before.
|
|
*/
|
|
void gpio_toggle_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Toggle the I/O line. */
|
|
gpio_port->ovrt = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Toggles a GPIO group.
|
|
*
|
|
* \param port The port number.
|
|
* \param mask The mask.
|
|
*/
|
|
void gpio_toggle_group(uint32_t port, uint32_t mask)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[port];
|
|
|
|
/* Toggle the I/O port. */
|
|
gpio_port->ovrt = mask;
|
|
}
|
|
|
|
/** \brief Drives a GPIO pin to 1 using open drain.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_set_gpio_open_drain_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* The GPIO output driver is disabled for that pin. */
|
|
gpio_port->oderc = 1 << (pin & 0x1F);
|
|
/* The GPIO module controls that pin. */
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Drives a GPIO pin to 0 using open drain.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_clr_gpio_open_drain_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Value to be driven on the I/O line: 0. */
|
|
gpio_port->ovrc = 1 << (pin & 0x1F);
|
|
/* The GPIO output driver is enabled for that pin. */
|
|
gpio_port->oders = 1 << (pin & 0x1F);
|
|
/* The GPIO module controls that pin. */
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Toggles a GPIO pin using open drain.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_tgl_gpio_open_drain_pin(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Value to be driven on the I/O line if the GPIO output driver is
|
|
* enabled: 0. */
|
|
gpio_port->ovrc = 1 << (pin & 0x1F);
|
|
/* The GPIO output driver is toggled for that pin. */
|
|
gpio_port->odert = 1 << (pin & 0x1F);
|
|
/* The GPIO module controls that pin. */
|
|
gpio_port->gpers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Enables the glitch filter of a pin.
|
|
*
|
|
* When the glitch filter is enabled, a glitch with duration of less than 1
|
|
* clock cycle is automatically rejected, while a pulse with duration of 2 clock
|
|
* cycles or more is accepted. For pulse durations between 1 clock cycle and 2
|
|
* clock cycles, the pulse may or may not be taken into account, depending on
|
|
* the precise timing of its occurrence. Thus for a pulse to be guaranteed
|
|
* visible it must exceed 2 clock cycles, whereas for a glitch to be reliably
|
|
* filtered out, its duration must not exceed 1 clock cycle. The filter
|
|
* introduces 2 clock cycles latency.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_enable_pin_glitch_filter(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->gfers = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Disables the glitch filter of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_disable_pin_glitch_filter(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->gferc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Configure the edge detector of an input pin
|
|
*
|
|
* \param pin The pin number.
|
|
* \param mode The edge detection mode (\ref GPIO_PIN_CHANGE,
|
|
* \ref GPIO_RISING_EDGE or \ref GPIO_FALLING_EDGE).
|
|
*
|
|
* \return \ref GPIO_SUCCESS or \ref GPIO_INVALID_ARGUMENT.
|
|
*/
|
|
static uint32_t gpio_configure_edge_detector(uint32_t pin, uint32_t mode)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Configure the edge detector. */
|
|
switch (mode) {
|
|
case GPIO_PIN_CHANGE:
|
|
gpio_port->imr0c = 1 << (pin & 0x1F);
|
|
gpio_port->imr1c = 1 << (pin & 0x1F);
|
|
break;
|
|
|
|
case GPIO_RISING_EDGE:
|
|
gpio_port->imr0s = 1 << (pin & 0x1F);
|
|
gpio_port->imr1c = 1 << (pin & 0x1F);
|
|
break;
|
|
|
|
case GPIO_FALLING_EDGE:
|
|
gpio_port->imr0c = 1 << (pin & 0x1F);
|
|
gpio_port->imr1s = 1 << (pin & 0x1F);
|
|
break;
|
|
|
|
default:
|
|
return GPIO_INVALID_ARGUMENT;
|
|
}
|
|
|
|
return GPIO_SUCCESS;
|
|
}
|
|
|
|
/** \brief Enables the interrupt of a pin with the specified settings.
|
|
*
|
|
* \param pin The pin number.
|
|
* \param mode The trigger mode (\ref GPIO_PIN_CHANGE, \ref GPIO_RISING_EDGE or
|
|
* \ref GPIO_FALLING_EDGE).
|
|
*
|
|
* \return \ref GPIO_SUCCESS or \ref GPIO_INVALID_ARGUMENT.
|
|
*/
|
|
uint32_t gpio_enable_pin_interrupt(uint32_t pin, uint32_t mode)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
/* Enable the glitch filter. */
|
|
gpio_port->gfers = 1 << (pin & 0x1F);
|
|
|
|
/* Configure the edge detector. */
|
|
if (GPIO_INVALID_ARGUMENT == gpio_configure_edge_detector(pin, mode)) {
|
|
return(GPIO_INVALID_ARGUMENT);
|
|
}
|
|
|
|
/* Enable interrupt. */
|
|
gpio_port->iers = 1 << (pin & 0x1F);
|
|
|
|
return GPIO_SUCCESS;
|
|
}
|
|
|
|
/** \brief Disables the interrupt of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_disable_pin_interrupt(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
gpio_port->ierc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/** \brief Gets the interrupt flag of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*
|
|
* \return The pin interrupt flag.
|
|
*/
|
|
bool gpio_get_pin_interrupt_flag(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
return (gpio_port->ifr >> (pin & 0x1F)) & 1;
|
|
}
|
|
|
|
/** \brief Clears the interrupt flag of a pin.
|
|
*
|
|
* \param pin The pin number.
|
|
*/
|
|
void gpio_clear_pin_interrupt_flag(uint32_t pin)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
#if (AVR32_GPIO_H_VERSION == 211)
|
|
/* GPIO erratum - Writing a one to the GPIO.IFRC register */
|
|
/* to clear an interrupt will be ignored if interrupt is enabled for the */
|
|
/* corresponding port. */
|
|
/* Work around for the erratum - Disable the interrupt, clear it by
|
|
* writing */
|
|
/* a one to GPIO.IFRC, then enable the interrupt. */
|
|
|
|
/* Save interrupt enable register. */
|
|
uint32_t const gpio_ier = gpio_port->ier;
|
|
|
|
/* Disable interrupt. */
|
|
gpio_port->ierc = gpio_ier;
|
|
|
|
/* Clear pin interrupt. */
|
|
gpio_port->ifrc = 1 << (pin & 0x1F);
|
|
|
|
/* Restore interrupt enable register. */
|
|
gpio_port->ier = gpio_ier;
|
|
#else
|
|
gpio_port->ifrc = 1 << (pin & 0x1F);
|
|
#endif
|
|
}
|
|
|
|
#if UC3L
|
|
|
|
/** \brief Configure the peripheral event trigger mode of a pin
|
|
*
|
|
* \param pin The pin number.
|
|
* \param mode The trigger mode (\ref GPIO_PIN_CHANGE, \ref GPIO_RISING_EDGE or
|
|
* \ref GPIO_FALLING_EDGE).
|
|
* \param use_igf use the Input Glitch Filter (true) or not (false).
|
|
*
|
|
* \return \ref GPIO_SUCCESS or \ref GPIO_INVALID_ARGUMENT.
|
|
*/
|
|
uint32_t gpio_configure_pin_periph_event_mode(uint32_t pin, uint32_t mode,
|
|
uint32_t use_igf)
|
|
{
|
|
volatile avr32_gpio_port_t *gpio_port = &AVR32_GPIO.port[pin >> 5];
|
|
|
|
if (true == use_igf) {
|
|
/* Enable the glitch filter. */
|
|
gpio_port->gfers = 1 << (pin & 0x1F);
|
|
} else {
|
|
/* Disable the glitch filter. */
|
|
gpio_port->gferc = 1 << (pin & 0x1F);
|
|
}
|
|
|
|
/* Configure the edge detector. */
|
|
return gpio_configure_edge_detector(pin, mode);
|
|
}
|
|
|
|
#endif
|
|
|
|
/** @} */
|