1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu, cc2538: refine gpio handling

- hide (more) internal functions
  - optimize gpio_init_af
  - remove obsolete code
This commit is contained in:
smlng 2017-08-25 17:49:12 +02:00
parent e01c23ef35
commit 8fb71afa79
5 changed files with 236 additions and 272 deletions

View File

@ -55,7 +55,7 @@ enum {
*
* @return A bit mask in which bit n is high.
*/
#define GPIO_PIN_MASK(n) ( 1 << (n) )
#define PIN_MASK(n) ( 1 << (n) )
/**
* @brief Extract the GPIO port number (0-3) from a GPIO number (0-31)
@ -99,28 +99,28 @@ enum {
*
* @param[in] gpio_num GPIO number (0-31)
*/
#define gpio_hardware_control(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->AFSEL |= GPIO_PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
#define gpio_hardware_control(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->AFSEL |= PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
/**
* @brief Enable software control for a given GPIO pin number
*
* @param[in] gpio_num GPIO number (0-31)
*/
#define gpio_software_control(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->AFSEL &= ~GPIO_PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
#define gpio_software_control(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->AFSEL &= ~PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
/**
* @brief Configure the given GPIO as an output
*
* @param[in] gpio_num GPIO number (0-31)
*/
#define gpio_dir_output(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DIR |= GPIO_PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
#define gpio_dir_output(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DIR |= PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
/**
* @brief Configure the given GPIO as an input
*
* @param[in] gpio_num GPIO number (0-31)
*/
#define gpio_dir_input(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DIR &= ~GPIO_PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
#define gpio_dir_input(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DIR &= ~PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
/**
* @brief Read the value of the given pin
@ -129,28 +129,17 @@ enum {
*/
#define cc2538_gpio_read(gpio_num) ( (GPIO_NUM_TO_DEV(gpio_num)->DATA >> GPIO_BIT_NUM(gpio_num)) & 1 )
/**
* @brief Set a specific GPIO output pin high
*
* @param[in] gpio_num GPIO number (0-31)
*/
#define cc2538_gpio_set(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DATA |= GPIO_PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
/**
* @brief Set a specific GPIO output pin low
*
* @param[in] gpio_num GPIO number (0-31)
*/
#define cc2538_gpio_clear(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DATA &= ~GPIO_PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
#define cc2538_gpio_clear(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DATA &= ~PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
/**
* @brief Toggle the output state of a specific GPIO pin
*
* @param[in] gpio_num GPIO number (0-31)
*/
#define cc2538_gpio_toggle(gpio_num) ( GPIO_NUM_TO_DEV(gpio_num)->DATA ^= GPIO_PIN_MASK(GPIO_BIT_NUM(gpio_num)) )
/** @name Unique names for each GPIO port/pin combination
* @name Unique names for each GPIO port/pin combination
* @deprecated will be removed after adaption of periph drivers,
* use GPIO_PIN macro instead
* @{
*/
enum {
@ -220,42 +209,113 @@ typedef struct {
} cc2538_gpio_t;
/**
* @brief IOC port component registers
* @brief GPIO port instance base address
*/
typedef struct {
cc2538_reg_t SEL[32]; /**< Port A to D SEL registers */
cc2538_reg_t OVER[32]; /**< Port A OVER register */
} cc2538_ioc_t;
#define GPIO_BASE (0x400d9000)
/**
* @name Values for IOC_PXX_SEL
* @name GPIO shift and masking
* @{
*/
#define IOC_SEL_UART0_TXD (0) /**< UART0 TXD */
#define IOC_SEL_UART1_RTS (1) /**< UART1 RTS */
#define IOC_SEL_UART1_TXD (2) /**< UART1 TXD */
#define IOC_SEL_SSI0_TXD (3) /**< SSI0 TXD */
#define IOC_SEL_SSI0_CLKOUT (4) /**< SSI0 CLKOUT */
#define IOC_SEL_SSI0_FSSOUT (5) /**< SSI0 FSSOUT */
#define IOC_SEL_SSI0_STXSER_EN (6) /**< SSI0 STXSER EN */
#define IOC_SEL_SSI1_TXD (7) /**< SSI1 TXD */
#define IOC_SEL_SSI1_CLKOUT (8) /**< SSI1 CLKOUT */
#define IOC_SEL_SSI1_FSSOUT (9) /**< SSI1 FSSOUT */
#define IOC_SEL_SSI1_STXSER_EN (10) /**< SSI1 STXSER EN */
#define IOC_SEL_I2C_CMSSDA (11) /**< I2C CMSSDA */
#define IOC_SEL_I2C_CMSSCL (12) /**< I2C CMSSCL */
#define IOC_SEL_GPT0_ICP1 (13) /**< GPT0 ICP1 */
#define IOC_SEL_GPT0_ICP2 (14) /**< GPT0 ICP2 */
#define IOC_SEL_GPT1_ICP1 (15) /**< GPT1 ICP1 */
#define IOC_SEL_GPT1_ICP2 (16) /**< GPT1 ICP2 */
#define IOC_SEL_GPT2_ICP1 (17) /**< GPT2 ICP1 */
#define IOC_SEL_GPT2_ICP2 (18) /**< GPT2 ICP2 */
#define IOC_SEL_GPT3_ICP1 (19) /**< GPT3 ICP1 */
#define IOC_SEL_GPT3_ICP2 (20) /**< GPT3 ICP2 */
#define GPIO_PORTNUM_SHIFT (12U) /**< bit shift for GPIO port */
#define GPIO_PORTNUM_MASK (0x00007000) /**< bit mask for GPIO port [0-3] */
#define GPIO_PIN_MASK (0x00000007) /**< bit mask for GPIO pin [0-7] */
#define GPIO_PORT_MASK (0xfffff000) /**< bit mask for GPIO port addr */
/** @} */
/**
* @name GPIO instance definitions
* @deprecated will be removed after adaption of periph drivers
* @{
*/
#define GPIO_A ((cc2538_gpio_t *)0x400d9000) /**< GPIO Port A instance */
#define GPIO_B ((cc2538_gpio_t *)0x400da000) /**< GPIO Port B instance */
#define GPIO_C ((cc2538_gpio_t *)0x400db000) /**< GPIO Port C instance */
#define GPIO_D ((cc2538_gpio_t *)0x400dc000) /**< GPIO Port D instance */
/** @} */
/**
* @brief IOC port component registers
*/
typedef struct {
cc2538_reg_t SEL[32]; /**< select special function for output pin*/
cc2538_reg_t OVER[32]; /**< override pin mode, enable alternate mode */
cc2538_reg_t PINS[21]; /**< select input pin for special functions */
} cc2538_ioc_t;
/**
* @name Peripheral Signal Select Values (for IOC_Pxx_SEL registers)
* @{
*/
typedef enum {
UART0_TXD = 0, /**< UART0 TXD */
UART1_RTS, /**< UART1 RTS */
UART1_TXD, /**< UART1 TXD */
SSI0_TXD, /**< SSI0 TXD */
SSI0_CLK_OUT, /**< SSI0 CLKOUT */
SSI0_FSS_OUT, /**< SSI0 FSSOUT */
SSI0_TX_SER, /**< SSI0 STXSER EN */
SSI1_TXD, /**< SSI1 TXD */
SSI1_CLK_OUT, /**< SSI1 CLKOUT */
SSI1_FSS_OUT, /**< SSI1 FSSOUT */
SSI1_TX_SER, /**< SSI1 STXSER EN */
I2C_SDA_OUT, /**< I2C CMSSDA */
I2C_SCL_OUT, /**< I2C CMSSCL */
GPT0_ICP1, /**< GPT0 ICP1 */
GPT0_ICP2, /**< GPT0 ICP2 */
GPT1_ICP1, /**< GPT1 ICP1 */
GPT1_ICP2, /**< GPT1 ICP2 */
GPT2_ICP1, /**< GPT2 ICP1 */
GPT2_ICP2, /**< GPT2 ICP2 */
GPT3_ICP1, /**< GPT3 ICP1 */
GPT3_ICP2 , /**< GPT3 ICP2 */
} cc2538_ioc_sel_t;
/** @} */
/**
* @name Pin select for periphical functions
* @{
*/
typedef enum {
UART0_RXD = 0, /**< UART0 RXD */
UART1_CTS, /**< UART1 CTS */
UART1_RXD, /**< UART1 RXD */
SSI0_CLK, /**< SSI0 CLK */
SSI0_RXD, /**< SSI0 RXD */
SSI0_FSS_IN, /**< SSI0 FSS IN */
SSI0_CLK_IN, /**< SSI0 CLK IN */
SSI1_CLK, /**< SSI1 CLK */
SSI1_RXD, /**< SSI1 RXD */
SSI1_FSS_IN, /**< SSI1 FSS IN */
SSI1_CLK_IN, /**< SSI1 CLK IN */
I2C_SDA_IN, /**< I2C SDA IN */
I2C_SCL_IN, /**< I2C SCL IN */
GPT0_OCP1, /**< GPT0 OCP1 */
GPT0_OCP2, /**< GPT0 OCP2 */
GPT1_OCP1, /**< GPT1 OCP1 */
GPT1_OCP2, /**< GPT1 OCP2 */
GPT2_OCP1, /**< GPT2 OCP1 */
GPT2_OCP2, /**< GPT2 OCP2 */
GPT3_OCP1, /**< GPT3 OCP1 */
GPT3_OCP2, /**< GPT3 OCP2 */
} cc2538_ioc_pin_t;
/** @} */
/**
* @brief Values to override pin configuration
*/
typedef enum {
OVERRIDE_DISABLE = 0x0,
OVERRIDE_ANALOG = 0x1,
OVERRIDE_PULLDOWN = 0x2,
OVERRIDE_PULLUP = 0x4,
OVERRIDE_ENABLE = 0x8,
} cc2538_ioc_over_t;
/**
* @name Values for IOC_PXX_OVER
* @deprecated will be removed after adaption of periph drivers,
* use cc2538_ioc_over_t instead
* @{
*/
#define IOC_OVERRIDE_OE 0x00000008 /**< Output Enable */
@ -266,20 +326,18 @@ typedef struct {
/** @} */
/**
* @name GPIO instance definitions
* @{
* @brief IOC instance definition
*/
#define GPIO_A ((cc2538_gpio_t *)0x400d9000) /**< GPIO Port A instance */
#define GPIO_B ((cc2538_gpio_t *)0x400da000) /**< GPIO Port B instance */
#define GPIO_C ((cc2538_gpio_t *)0x400db000) /**< GPIO Port C instance */
#define GPIO_D ((cc2538_gpio_t *)0x400dc000) /**< GPIO Port D instance */
/** @} */
#define IOC ((cc2538_ioc_t *)0x400d4000)
/**
* @name IOC instance definition
* @name Port control register addresses
* @deprecated will be removed after adaption of periph drivers,
* use IOC->OVER and IOC->SEL instead
* @{
*/
#define IOC ((cc2538_ioc_t *)0x400d4000) /**< IOC instance */
#define IOC_PXX_OVER (IOC->OVER)
#define IOC_PXX_SEL (IOC->SEL)
/** @} */
#ifdef __cplusplus

View File

@ -1,86 +0,0 @@
/*
* Copyright (C) 2014 Loci Controls Inc.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup cpu_cc2538_ioc CC2538 I/O Control
* @ingroup cpu_cc2538_regs
* @{
*
* @file
* @brief CC2538 I/O Control driver
*
* Header file with declarations for the I/O Control module
*
* @author Ian Martin <ian@locicontrols.com>
*
*/
#ifndef CC2538_IOC_H
#define CC2538_IOC_H
#include <stdint.h>
#include "cc2538.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Port control register addresses
* @{
*/
#define IOC_PXX_SEL ( (cc2538_reg_t*)0x400d4000 )
#define IOC_PXX_OVER ( (cc2538_reg_t*)0x400d4080 )
/** @} */
/** @name Peripheral Signal Select Values (for IOC_Pxx_SEL registers)
* @{
*/
enum {
UART0_TXD = 0, /**< UART0 TXD */
UART1_RTS = 1, /**< UART1 RTS */
UART1_TXD = 2, /**< UART1 TXD */
SSI0_TXD = 3, /**< SSI0 TXD */
SSI0_CLKOUT = 4, /**< SSI0 CLKOUT */
SSI0_FSSOUT = 5, /**< SSI0 FSSOUT */
SSI0_STXSER_EN = 6, /**< SSI0 STXSER EN */
SSI1_TXD = 7, /**< SSI1 TXD */
SSI1_CLKOUT = 8, /**< SSI1 CLKOUT */
SSI1_FSSOUT = 9, /**< SSI1 FSSOUT */
SSI1_STXSER_EN = 10, /**< SSI1 STXSER EN */
I2C_CMSSDA = 11, /**< I2C CMSSDA */
I2C_CMSSCL = 12, /**< I2C CMSSCL */
GPT0_ICP1 = 13, /**< GPT0 ICP1 */
GPT0_ICP2 = 14, /**< GPT0 ICP2 */
GPT1_ICP1 = 15, /**< GPT1 ICP1 */
GPT1_ICP2 = 16, /**< GPT1 ICP2 */
GPT2_ICP1 = 17, /**< GPT2 ICP1 */
GPT2_ICP2 = 18, /**< GPT2 ICP2 */
GPT3_ICP1 = 19, /**< GPT3 ICP1 */
GPT3_ICP2 = 20, /**< GPT3 ICP2 */
};
/** @} */
/**
* @name Values for IOC_PXX_OVER
* @{
*/
#define IOC_OVERRIDE_OE 0x00000008 /**< Output Enable */
#define IOC_OVERRIDE_PUE 0x00000004 /**< Pull Up Enable */
#define IOC_OVERRIDE_PDE 0x00000002 /**< Pull Down Enable */
#define IOC_OVERRIDE_ANA 0x00000001 /**< Analog Enable */
#define IOC_OVERRIDE_DIS 0x00000000 /**< Override Disabled */
/** @} */
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* CC2538_IOC_H */
/** @} */

View File

@ -24,7 +24,6 @@
#include "cc2538_gpio.h"
#include "cc2538_uart.h"
#include "cc2538_gptimer.h"
#include "cc2538_ioc.h"
#include "cc2538_soc_adc.h"
#include "cc2538_ssi.h"
#include "cc2538_rfcore.h"

View File

@ -34,13 +34,14 @@ extern "C" {
* @brief Starting offset of CPU_ID
*/
#define CPUID_ADDR (&IEEE_ADDR_MSWORD)
/**
* @brief Length of the CPU_ID in octets
*/
#define CPUID_LEN (8U)
/**
* @brief Define a custom type for GPIO pins
* @name Define a custom type for GPIO pins
* @{
*/
#define HAVE_GPIO_T
@ -55,14 +56,9 @@ typedef uint32_t gpio_t;
/** @} */
/**
* @name Internal GPIO shift and masking
* @{
* @brief Define custom value to speficy undefined or unused GPIOs
*/
#define PORTNUM_MASK (0x00007000) /**< bit mask for GPIO port [0-3] */
#define PORTNUM_SHIFT (12U) /**< bit shift for GPIO port */
#define PIN_MASK (0x00000007) /**< bit mask for GPIO pin [0-7] */
#define GPIO_MASK (0xfffff000) /**< bit mask for GPIO port addr */
/** @} */
#define GPIO_UNDEF (0xffffffff)
/**
* @brief Define a custom GPIO_PIN macro
@ -70,82 +66,17 @@ typedef uint32_t gpio_t;
* For the CC2538, we use OR the gpio ports base register address with the
* actual pin number.
*/
#define GPIO_PIN(port, pin) (gpio_t)(((uint32_t)GPIO_A + \
(port << PORTNUM_SHIFT)) | pin)
/**
* @brief Access GPIO low-level device
*
* @param[in] pin gpio pin
*
* @return pointer to gpio low level device address
*/
static inline cc2538_gpio_t *gpio(gpio_t pin)
{
return (cc2538_gpio_t *)(pin & GPIO_MASK);
}
/**
* @brief Helper function to get port number for gpio pin
*
* @param[in] pin gpio pin
*
* @return port number of gpio pin, [0=A - 3=D]
*/
static inline uint8_t gpio_port_num(gpio_t pin)
{
return (uint8_t)((pin & PORTNUM_MASK) >> PORTNUM_SHIFT) - 1;
}
/**
* @brief Helper function to get pin number for gpio pin
*
* @param[in] pin gpio pin
*
* @return pin number of gpio pin, [0 - 7]
*/
static inline uint8_t gpio_pin_num(gpio_t pin)
{
return (uint8_t)(pin & PIN_MASK);
}
/**
* @brief Helper function to get bit mask for gpio pin number
*
* @param[in] pin gpio pin
*
* @return bit mask for gpio pin number, 2^[0 - 7]
*/
static inline uint32_t gpio_pin_mask(gpio_t pin)
{
return (1 << (pin & PIN_MASK));
}
/**
* @brief Helper function to get CC2538 gpio number from port and pin
*
* @param[in] pin gpio pin
*
* @return number of gpio pin, [0 - 31]
*/
static inline uint8_t gpio_pp_num(gpio_t pin)
{
return (uint8_t)((gpio_port_num(pin) * 8) + gpio_pin_num(pin));
}
#define GPIO_PIN(port, pin) (gpio_t)(((uint32_t)GPIO_BASE + \
(port << GPIO_PORTNUM_SHIFT)) | pin)
/**
* @brief Configure an alternate function for the given pin
*
* @param[in] pin gpio pin
* @param[in] sel Setting for IOC select register, (-1) to ignore
* @param[in] over Setting for IOC override register, (-1) to ignore
* @param[in] sel Select pin peripheral function
* @param[in] over Override pin configuration
*/
void gpio_init_af(gpio_t pin, int sel, int over);
/**
* @brief Define a custom GPIO_UNDEF value
*/
#define GPIO_UNDEF 99
void gpio_init_af(gpio_t pin, uint8_t sel, uint8_t over);
/**
* @brief I2C configuration options
@ -171,12 +102,13 @@ typedef struct {
*/
#define HAVE_GPIO_MODE_T
typedef enum {
GPIO_IN = ((uint8_t)0x00), /**< input, no pull */
GPIO_IN_PD = ((uint8_t)IOC_OVERRIDE_PDE), /**< input, pull-down */
GPIO_IN_PU = ((uint8_t)IOC_OVERRIDE_PUE), /**< input, pull-up */
GPIO_OUT = ((uint8_t)IOC_OVERRIDE_OE), /**< output */
GPIO_OD = (0xff), /**< not supported */
GPIO_OD_PU = (0xff) /**< not supported */
GPIO_IN = ((uint8_t)OVERRIDE_DISABLE), /**< input, no pull */
GPIO_IN_ANALOG = ((uint8_t)OVERRIDE_ANALOG), /**< input, analog */
GPIO_IN_PD = ((uint8_t)OVERRIDE_PULLDOWN), /**< input, pull-down */
GPIO_IN_PU = ((uint8_t)OVERRIDE_PULLUP), /**< input, pull-up */
GPIO_OUT = ((uint8_t)OVERRIDE_ENABLE), /**< output */
GPIO_OD = (0xff), /**< not supported */
GPIO_OD_PU = (0xff) /**< not supported */
} gpio_mode_t;
/** @} */

View File

@ -33,6 +33,66 @@
static gpio_isr_ctx_t isr_ctx[4][8];
/**
* @brief Access GPIO low-level device
*
* @param[in] pin gpio pin
*
* @return pointer to gpio low level device address
*/
static inline cc2538_gpio_t *gpio(gpio_t pin)
{
return (cc2538_gpio_t *)(pin & GPIO_PORT_MASK);
}
/**
* @brief Helper function to get port number for gpio pin
*
* @param[in] pin gpio pin
*
* @return port number of gpio pin, [0=A - 3=D]
*/
static inline uint8_t _port_num(gpio_t pin)
{
return (uint8_t)((pin & GPIO_PORTNUM_MASK) >> GPIO_PORTNUM_SHIFT) - 1;
}
/**
* @brief Helper function to get pin number for gpio pin
*
* @param[in] pin gpio pin
*
* @return pin number of gpio pin, [0 - 7]
*/
static inline uint8_t _pin_num(gpio_t pin)
{
return (uint8_t)(pin & GPIO_PIN_MASK);
}
/**
* @brief Helper function to get bit mask for gpio pin number
*
* @param[in] pin gpio pin
*
* @return bit mask for gpio pin number, 2^[0 - 7]
*/
static inline uint32_t _pin_mask(gpio_t pin)
{
return (1 << (pin & GPIO_PIN_MASK));
}
/**
* @brief Helper function to get CC2538 gpio number from port and pin
*
* @param[in] pin gpio pin
*
* @return number of gpio pin, [0 - 31]
*/
static inline uint8_t _pp_num(gpio_t pin)
{
return (uint8_t)((_port_num(pin) * GPIO_BITS_PER_PORT) + _pin_num(pin));
}
int gpio_init(gpio_t pin, gpio_mode_t mode)
{
/* check if mode is valid */
@ -40,20 +100,19 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
return -1;
}
DEBUG("GPIO %"PRIu32", PORT: %u, PIN: %u\n", (uint32_t)pin, gpio_port_num(pin), gpio_pin_num(pin));
DEBUG("GPIO %"PRIu32", PORT: %u, PIN: %u\n", (uint32_t)pin, _port_num(pin), _pin_num(pin));
/* disable any alternate function and any eventual interrupts */
gpio(pin)->IE &= ~gpio_pin_mask(pin);
gpio(pin)->AFSEL &= ~gpio_pin_mask(pin);
gpio(pin)->IE &= ~_pin_mask(pin);
gpio(pin)->AFSEL &= ~_pin_mask(pin);
/* configure pull configuration */
IOC_PXX_OVER[gpio_pp_num(pin)] = mode;
IOC->OVER[_pp_num(pin)] = mode;
/* set pin direction */
if (mode == IOC_OVERRIDE_OE) {
gpio(pin)->DIR |= gpio_pin_mask(pin);
if (mode == GPIO_OUT) {
gpio(pin)->DIR |= _pin_mask(pin);
}
else {
gpio(pin)->DIR &= ~gpio_pin_mask(pin);
gpio(pin)->DIR &= ~_pin_mask(pin);
}
return 0;
@ -67,88 +126,89 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
}
/* store the callback information for later: */
isr_ctx[gpio_port_num(pin)][gpio_pin_num(pin)].cb = cb;
isr_ctx[gpio_port_num(pin)][gpio_pin_num(pin)].arg = arg;
isr_ctx[_port_num(pin)][_pin_num(pin)].cb = cb;
isr_ctx[_port_num(pin)][_pin_num(pin)].arg = arg;
/* enable power-up interrupts for this GPIO port: */
SYS_CTRL->IWE |= (1 << gpio_port_num(pin));
SYS_CTRL->IWE |= (1 << _port_num(pin));
/* configure the active flank(s) */
gpio(pin)->IS &= ~gpio_pin_mask(pin);
gpio(pin)->IS &= ~_pin_mask(pin);
switch(flank) {
case GPIO_FALLING:
gpio(pin)->IBE &= ~gpio_pin_mask(pin);
gpio(pin)->IEV &= ~gpio_pin_mask(pin);
gpio(pin)->P_EDGE_CTRL |= (1 << gpio_pp_num(pin));
gpio(pin)->IBE &= ~_pin_mask(pin);
gpio(pin)->IEV &= ~_pin_mask(pin);
gpio(pin)->P_EDGE_CTRL |= (1 << _pp_num(pin));
break;
case GPIO_RISING:
gpio(pin)->IBE &= ~gpio_pin_mask(pin);
gpio(pin)->IEV |= gpio_pin_mask(pin);
gpio(pin)->P_EDGE_CTRL &= ~(1 << gpio_pp_num(pin));
gpio(pin)->IBE &= ~_pin_mask(pin);
gpio(pin)->IEV |= _pin_mask(pin);
gpio(pin)->P_EDGE_CTRL &= ~(1 << _pp_num(pin));
break;
case GPIO_BOTH:
gpio(pin)->IBE |= gpio_pin_mask(pin);
gpio(pin)->IBE |= _pin_mask(pin);
break;
default:
return -1;
}
/* reset interrupt status */
gpio(pin)->IC = gpio_pin_mask(pin);
gpio(pin)->PI_IEN |= (1 << gpio_pp_num(pin));
gpio(pin)->IC = _pin_mask(pin);
gpio(pin)->PI_IEN |= (1 << _pp_num(pin));
/* enable global interrupt for the selected GPIO port */
NVIC_EnableIRQ(GPIO_PORT_A_IRQn + gpio_port_num(pin));
NVIC_EnableIRQ(GPIO_PORT_A_IRQn + _port_num(pin));
/* unmask pin interrupt */
gpio(pin)->IE |= gpio_pin_mask(pin);
gpio(pin)->IE |= _pin_mask(pin);
return 0;
}
void gpio_irq_enable(gpio_t pin)
{
gpio(pin)->IE |= gpio_pin_mask(pin);
gpio(pin)->IE |= _pin_mask(pin);
}
void gpio_irq_disable(gpio_t pin)
{
gpio(pin)->IE &= ~gpio_pin_mask(pin);
gpio(pin)->IE &= ~_pin_mask(pin);
}
int gpio_read(gpio_t pin)
{
return (int)(gpio(pin)->DATA & gpio_pin_mask(pin));
return (int)(gpio(pin)->DATA & _pin_mask(pin));
}
void gpio_set(gpio_t pin)
{
gpio(pin)->DATA |= gpio_pin_mask(pin);
gpio(pin)->DATA |= _pin_mask(pin);
}
void gpio_clear(gpio_t pin)
{
gpio(pin)->DATA &= ~gpio_pin_mask(pin);
gpio(pin)->DATA &= ~_pin_mask(pin);
}
void gpio_toggle(gpio_t pin)
{
gpio(pin)->DATA ^= gpio_pin_mask(pin);
gpio(pin)->DATA ^= _pin_mask(pin);
}
void gpio_write(gpio_t pin, int value)
{
if (value) {
gpio(pin)->DATA |= gpio_pin_mask(pin);
gpio(pin)->DATA |= _pin_mask(pin);
}
else {
gpio(pin)->DATA &= ~gpio_pin_mask(pin);
gpio(pin)->DATA &= ~_pin_mask(pin);
}
}
static inline void handle_isr(cc2538_gpio_t *gpio, int port_num)
static inline void handle_isr(uint8_t port_num)
{
uint32_t state = gpio->MIS;
gpio->IC = 0x000000ff;
gpio->IRQ_DETECT_ACK = (0xff << (port_num * GPIO_BITS_PER_PORT));
cc2538_gpio_t *port = ((cc2538_gpio_t *)GPIO_BASE) + port_num;
uint32_t state = port->MIS;
port->IC = 0x000000ff;
port->IRQ_DETECT_ACK = (0xff << (port_num * GPIO_BITS_PER_PORT));
for (int i = 0; i < GPIO_BITS_PER_PORT; i++) {
if (state & (1 << i)) {
@ -162,39 +222,40 @@ static inline void handle_isr(cc2538_gpio_t *gpio, int port_num)
/** @brief Interrupt service routine for Port A */
void isr_gpioa(void)
{
handle_isr(GPIO_A, 0);
handle_isr(0);
}
/** @brief Interrupt service routine for Port B */
void isr_gpiob(void)
{
handle_isr(GPIO_B, 1);
handle_isr(1);
}
/** @brief Interrupt service routine for Port C */
void isr_gpioc(void)
{
handle_isr(GPIO_C, 2);
handle_isr(2);
}
/** @brief Interrupt service routine for Port D */
void isr_gpiod(void)
{
handle_isr(GPIO_D, 3);
handle_isr(3);
}
/* CC2538 specific add-on GPIO functions */
void gpio_init_af(gpio_t pin, int sel, int over)
void gpio_init_af(gpio_t pin, uint8_t sel, uint8_t over)
{
assert(pin != GPIO_UNDEF);
if (over >= 0) {
IOC_PXX_OVER[gpio_pp_num(pin)] = over;
IOC->OVER[_pp_num(pin)] = over;
if (over != GPIO_OUT) {
IOC->PINS[sel] = _pp_num(pin);
}
if(sel >= 0) {
IOC_PXX_SEL[gpio_pp_num(pin)] = sel;
else {
IOC->SEL[_pp_num(pin)] = sel;
}
/* enable alternative function mode */
gpio(pin)->AFSEL |= gpio_pin_mask(pin);
gpio(pin)->AFSEL |= _pin_mask(pin);
}