From 8fb71afa790aef92ee118bcc39abfc99e43a52e5 Mon Sep 17 00:00:00 2001 From: smlng Date: Fri, 25 Aug 2017 17:49:12 +0200 Subject: [PATCH] cpu, cc2538: refine gpio handling - hide (more) internal functions - optimize gpio_init_af - remove obsolete code --- cpu/cc2538/include/cc2538_gpio.h | 170 +++++++++++++++++++++---------- cpu/cc2538/include/cc2538_ioc.h | 86 ---------------- cpu/cc2538/include/cpu_conf.h | 1 - cpu/cc2538/include/periph_cpu.h | 100 +++--------------- cpu/cc2538/periph/gpio.c | 151 +++++++++++++++++++-------- 5 files changed, 236 insertions(+), 272 deletions(-) delete mode 100644 cpu/cc2538/include/cc2538_ioc.h diff --git a/cpu/cc2538/include/cc2538_gpio.h b/cpu/cc2538/include/cc2538_gpio.h index d58938d6a8..c9cbfefaa6 100644 --- a/cpu/cc2538/include/cc2538_gpio.h +++ b/cpu/cc2538/include/cc2538_gpio.h @@ -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 diff --git a/cpu/cc2538/include/cc2538_ioc.h b/cpu/cc2538/include/cc2538_ioc.h deleted file mode 100644 index ed170fcc6f..0000000000 --- a/cpu/cc2538/include/cc2538_ioc.h +++ /dev/null @@ -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 - * - */ - -#ifndef CC2538_IOC_H -#define CC2538_IOC_H - -#include - -#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 */ -/** @} */ diff --git a/cpu/cc2538/include/cpu_conf.h b/cpu/cc2538/include/cpu_conf.h index b2c1e0f2e7..eb9fc3b103 100644 --- a/cpu/cc2538/include/cpu_conf.h +++ b/cpu/cc2538/include/cpu_conf.h @@ -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" diff --git a/cpu/cc2538/include/periph_cpu.h b/cpu/cc2538/include/periph_cpu.h index 7a6d3d1906..8ce2e13f64 100644 --- a/cpu/cc2538/include/periph_cpu.h +++ b/cpu/cc2538/include/periph_cpu.h @@ -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; /** @} */ diff --git a/cpu/cc2538/periph/gpio.c b/cpu/cc2538/periph/gpio.c index d9103e86ee..83a33c86c4 100644 --- a/cpu/cc2538/periph/gpio.c +++ b/cpu/cc2538/periph/gpio.c @@ -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); }