/* * 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_gpio CC2538 General-Purpose I/O * @ingroup cpu_cc2538_regs * @{ * * @file * @brief Driver for the cc2538 GPIO controller * * Header file with register and macro declarations for the cc2538 GPIO module * * @author Ian Martin * * @{ */ #ifndef CC2538_GPIO_H #define CC2538_GPIO_H #include #include "cc2538.h" #ifdef __cplusplus extern "C" { #endif /** * @name Numeric representation of the four GPIO ports * @{ */ enum { PORT_A = 0, PORT_B = 1, PORT_C = 2, PORT_D = 3, }; /** @} */ #define GPIO_PORT_SHIFT 3 /**< Right-shift amount to obtain the port number from a GPIO number */ #define GPIO_BITS_PER_PORT ( 1 << GPIO_PORT_SHIFT ) /**< Number of bits per GPIO port (8) */ #define GPIO_BIT_MASK ( GPIO_BITS_PER_PORT - 1 ) /**< Mask to obtain the bit number from a GPIO number */ /** * @brief Generate a bit mask in which only the specified bit is high. * * @param[in] n Number of the bit to set high in the mask. * * @return A bit mask in which bit n is high. */ #define GPIO_PIN_MASK(n) ( 1 << (n) ) /** * @brief Extract the GPIO port number (0-3) from a GPIO number (0-31) * * @param[in] gpio_num GPIO number (0-31) * * @return Corresponding GPIO port number (0-3) */ #define GPIO_NUM_TO_PORT_NUM(gpio_num) ( (gpio_num) >> GPIO_PORT_SHIFT ) /** * @brief Extract the GPIO port bit number (0-7) from a GPIO number (0-31) * * @param[in] gpio_num GPIO number (0-31) * * @return Corresponding GPIO port bit number (0-7) */ #define GPIO_BIT_NUM(gpio_num) ( (gpio_num) & GPIO_BIT_MASK ) /** * @brief Generate a GPIO number given a port and bit number * * @param[in] port_num GPIO port (PORT_A, PORT_B, PORT_C, or PORT_D) * @param[in] bit_num GPIO bit number (0-7) * * @return Corresponding GPIO number (0-31) */ #define GPIO_PXX_TO_NUM(port_num, bit_num) ( ((port_num) << GPIO_PORT_SHIFT) | (bit_num) ) /** * @brief Obtain the GPIO port instance given a GPIO number (0-31) * * @param[in] gpio_num GPIO number (0-31) * * @return Corresponding GPIO port instance */ #define GPIO_NUM_TO_DEV(gpio_num) ( GPIO_A + GPIO_NUM_TO_PORT_NUM(gpio_num) ) /** * @brief Enable hardware (peripheral) control for a given GPIO pin number * * @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)) ) /** * @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)) ) /** * @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)) ) /** * @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 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)) ) /** * @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 * @{ */ enum { GPIO_PA0 = GPIO_PXX_TO_NUM(PORT_A, 0), /**< PA0 */ GPIO_PA1 = GPIO_PXX_TO_NUM(PORT_A, 1), /**< PA1 */ GPIO_PA2 = GPIO_PXX_TO_NUM(PORT_A, 2), /**< PA2 */ GPIO_PA3 = GPIO_PXX_TO_NUM(PORT_A, 3), /**< PA3 */ GPIO_PA4 = GPIO_PXX_TO_NUM(PORT_A, 4), /**< PA4 */ GPIO_PA5 = GPIO_PXX_TO_NUM(PORT_A, 5), /**< PA5 */ GPIO_PA6 = GPIO_PXX_TO_NUM(PORT_A, 6), /**< PA6 */ GPIO_PA7 = GPIO_PXX_TO_NUM(PORT_A, 7), /**< PA7 */ GPIO_PB0 = GPIO_PXX_TO_NUM(PORT_B, 0), /**< PB0 */ GPIO_PB1 = GPIO_PXX_TO_NUM(PORT_B, 1), /**< PB1 */ GPIO_PB2 = GPIO_PXX_TO_NUM(PORT_B, 2), /**< PB2 */ GPIO_PB3 = GPIO_PXX_TO_NUM(PORT_B, 3), /**< PB3 */ GPIO_PB4 = GPIO_PXX_TO_NUM(PORT_B, 4), /**< PB4 */ GPIO_PB5 = GPIO_PXX_TO_NUM(PORT_B, 5), /**< PB5 */ GPIO_PB6 = GPIO_PXX_TO_NUM(PORT_B, 6), /**< PB6 */ GPIO_PB7 = GPIO_PXX_TO_NUM(PORT_B, 7), /**< PB7 */ GPIO_PC0 = GPIO_PXX_TO_NUM(PORT_C, 0), /**< PC0 */ GPIO_PC1 = GPIO_PXX_TO_NUM(PORT_C, 1), /**< PC1 */ GPIO_PC2 = GPIO_PXX_TO_NUM(PORT_C, 2), /**< PC2 */ GPIO_PC3 = GPIO_PXX_TO_NUM(PORT_C, 3), /**< PC3 */ GPIO_PC4 = GPIO_PXX_TO_NUM(PORT_C, 4), /**< PC4 */ GPIO_PC5 = GPIO_PXX_TO_NUM(PORT_C, 5), /**< PC5 */ GPIO_PC6 = GPIO_PXX_TO_NUM(PORT_C, 6), /**< PC6 */ GPIO_PC7 = GPIO_PXX_TO_NUM(PORT_C, 7), /**< PC7 */ GPIO_PD0 = GPIO_PXX_TO_NUM(PORT_D, 0), /**< PD0 */ GPIO_PD1 = GPIO_PXX_TO_NUM(PORT_D, 1), /**< PD1 */ GPIO_PD2 = GPIO_PXX_TO_NUM(PORT_D, 2), /**< PD2 */ GPIO_PD3 = GPIO_PXX_TO_NUM(PORT_D, 3), /**< PD3 */ GPIO_PD4 = GPIO_PXX_TO_NUM(PORT_D, 4), /**< PD4 */ GPIO_PD5 = GPIO_PXX_TO_NUM(PORT_D, 5), /**< PD5 */ GPIO_PD6 = GPIO_PXX_TO_NUM(PORT_D, 6), /**< PD6 */ GPIO_PD7 = GPIO_PXX_TO_NUM(PORT_D, 7), /**< PD7 */ }; /** @} */ /** * @brief GPIO port component registers */ typedef struct { cc2538_reg_t RESERVED1[255]; /**< Reserved addresses */ cc2538_reg_t DATA; /**< GPIO_A Data Register */ cc2538_reg_t DIR; /**< GPIO_A data direction register */ cc2538_reg_t IS; /**< GPIO_A Interrupt Sense register */ cc2538_reg_t IBE; /**< GPIO_A Interrupt Both-Edges register */ cc2538_reg_t IEV; /**< GPIO_A Interrupt Event Register */ cc2538_reg_t IE; /**< GPIO_A Interrupt mask register */ cc2538_reg_t RIS; /**< GPIO_A Raw Interrupt Status register */ cc2538_reg_t MIS; /**< GPIO_A Masked Interrupt Status register */ cc2538_reg_t IC; /**< GPIO_A Interrupt Clear register */ cc2538_reg_t AFSEL; /**< GPIO_A Alternate Function / mode control select register */ cc2538_reg_t RESERVED2[63]; /**< Reserved addresses */ cc2538_reg_t GPIOLOCK; /**< GPIO_A Lock register */ cc2538_reg_t GPIOCR; /**< GPIO_A Commit Register */ cc2538_reg_t RESERVED3[118]; /**< Reserved addresses */ cc2538_reg_t PMUX; /**< GPIO_A The PMUX register */ cc2538_reg_t P_EDGE_CTRL; /**< GPIO_A The Port Edge Control register */ cc2538_reg_t RESERVED4[2]; /**< Reserved addresses */ cc2538_reg_t PI_IEN; /**< GPIO_A The Power-up Interrupt Enable register */ cc2538_reg_t RESERVED5[1]; /**< Reserved addresses */ cc2538_reg_t IRQ_DETECT_ACK; /**< GPIO_A IRQ Detect ACK register */ cc2538_reg_t USB_IRQ_ACK; /**< GPIO_A IRQ Detect ACK for USB */ cc2538_reg_t IRQ_DETECT_UNMASK; /**< GPIO_A IRQ Detect ACK for masked interrupts */ cc2538_reg_t RESERVED6[567]; /**< Reserved addresses */ } cc2538_gpio_t; /** * @brief IOC port component registers */ typedef struct { cc2538_reg_t PA_SEL[8]; /**< Port A SEL register */ cc2538_reg_t PB_SEL[8]; /**< Port B SEL register */ cc2538_reg_t PC_SEL[8]; /**< Port C SEL register */ cc2538_reg_t PD_SEL[8]; /**< Port D SEL register */ cc2538_reg_t PA_OVER[8]; /**< Port A OVER register */ cc2538_reg_t PB_OVER[8]; /**< Port B OVER register */ cc2538_reg_t PC_OVER[8]; /**< Port C OVER register */ cc2538_reg_t PD_OVER[8]; /**< Port D OVER register */ } cc2538_ioc_t; /** * @name Values for IOC_PXX_SEL * @{ */ #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 */ /** @} */ /** * @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 */ /** @} */ /** * @name GPIO instance definitions * @{ */ #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 */ /** @} */ /** * @name IOC instance definition * @{ */ #define IOC ((cc2538_ioc_t *)0x400d4000) /**< IOC instance */ /** @} */ /** * @brief Initialize a GPIO port. * @details Initializes the port to a default state, disables interrupts and * clears any pending interrupts. * @param[in] gpio_port A pointer to the port's instance, e.g. "GPIO_A". */ void cc2538_gpio_port_init(cc2538_gpio_t* gpio_port); /** * @brief Initialize all four GPIO ports. */ void cc2538_gpio_init(void); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* CC2538_GPIO_H */ /** @} */ /** @} */