diff --git a/cpu/cc2538/dev/gpio.c b/cpu/cc2538/dev/gpio.c index 581e52839..eb561c757 100644 --- a/cpu/cc2538/dev/gpio.c +++ b/cpu/cc2538/dev/gpio.c @@ -79,69 +79,41 @@ notify(uint8_t mask, uint8_t port) } } /*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port A */ -void -gpio_port_a_isr() +/** \brief Interrupt service routine for Port \a port + * \param port Number between 0 and 3. Port A: 0, Port B: 1, etc. + */ +static void +gpio_port_isr(uint8_t port) { + uint32_t base; + uint8_t int_status, power_up_int_status; + lpm_exit(); ENERGEST_ON(ENERGEST_TYPE_IRQ); - notify(REG(GPIO_A_BASE + GPIO_MIS), GPIO_A_NUM); + base = GPIO_PORT_TO_BASE(port); + int_status = GPIO_GET_MASKED_INT_STATUS(base); + power_up_int_status = GPIO_GET_POWER_UP_INT_STATUS(port); - GPIO_CLEAR_INTERRUPT(GPIO_A_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_A_NUM, 0xFF); + notify(int_status | power_up_int_status, port); + + GPIO_CLEAR_INTERRUPT(base, int_status); + GPIO_CLEAR_POWER_UP_INTERRUPT(port, power_up_int_status); ENERGEST_OFF(ENERGEST_TYPE_IRQ); } /*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port B */ -void -gpio_port_b_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_B_BASE + GPIO_MIS), GPIO_B_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_B_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_B_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -/*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port C */ -void -gpio_port_c_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_C_BASE + GPIO_MIS), GPIO_C_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_C_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_C_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -/*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port D */ -void -gpio_port_d_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_D_BASE + GPIO_MIS), GPIO_D_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_D_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_D_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); +#define GPIO_PORT_ISR(lowercase_port, uppercase_port) \ +void \ +gpio_port_##lowercase_port##_isr(void) \ +{ \ + gpio_port_isr(GPIO_##uppercase_port##_NUM); \ } +GPIO_PORT_ISR(a, A) +GPIO_PORT_ISR(b, B) +GPIO_PORT_ISR(c, C) +GPIO_PORT_ISR(d, D) /*---------------------------------------------------------------------------*/ void gpio_init() diff --git a/cpu/cc2538/dev/gpio.h b/cpu/cc2538/dev/gpio.h index 33980501b..e97ba2825 100644 --- a/cpu/cc2538/dev/gpio.h +++ b/cpu/cc2538/dev/gpio.h @@ -210,6 +210,31 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); #define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK) \ do { REG((PORT_BASE) + GPIO_IE) &= ~(PIN_MASK); } while(0) +/** \brief Get raw interrupt status of port with PORT_BASE. + * \param PORT_BASE GPIO Port register offset + * \return Bit-mask reflecting the raw interrupt status of all the port pins + * + * The bits set in the returned bit-mask reflect the status of the interrupts + * trigger conditions detected (raw, before interrupt masking), indicating that + * all the requirements are met, before they are finally allowed to trigger by + * the interrupt mask. The bits cleared indicate that corresponding input pins + * have not initiated an interrupt. + */ +#define GPIO_GET_RAW_INT_STATUS(PORT_BASE) \ + REG((PORT_BASE) + GPIO_RIS) + +/** \brief Get masked interrupt status of port with PORT_BASE. + * \param PORT_BASE GPIO Port register offset + * \return Bit-mask reflecting the masked interrupt status of all the port pins + * + * The bits set in the returned bit-mask reflect the status of input lines + * triggering an interrupt. The bits cleared indicate that either no interrupt + * has been generated, or the interrupt is masked. This is the state of the + * interrupt after interrupt masking. + */ +#define GPIO_GET_MASKED_INT_STATUS(PORT_BASE) \ + REG((PORT_BASE) + GPIO_MIS) + /** \brief Clear interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. * \param PORT_BASE GPIO Port register offset @@ -270,6 +295,14 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_PI_IEN) &= \ ~((PIN_MASK) << ((PORT) << 3)); } while(0) +/** \brief Get power-up interrupt status of port PORT. + * \param PORT GPIO Port (not port base address) + * \return Bit-mask reflecting the power-up interrupt status of all the port + * pins + */ +#define GPIO_GET_POWER_UP_INT_STATUS(PORT) \ + ((REG(GPIO_PORT_TO_BASE(PORT) + GPIO_IRQ_DETECT_ACK) >> ((PORT) << 3)) & 0xFF) + /** \brief Clear power-up interrupt triggering for pins with PIN_MASK of port * PORT. * \param PORT GPIO Port (not port base address)