Merge pull request #1031 from bthebaudeau/cc2538-gpio-irqs
cc2538: gpio: Improve and fix IRQ management
This commit is contained in:
commit
2059be3a43
2 changed files with 57 additions and 52 deletions
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue