arch/arm/src/lpc54xx: Fix some GPIO interrupt configuration errors. Add logic to acknowledge rising/falling edge events. config/lpcxpresso-lpc545628: Add an intermediate interrupt handler to support acknowledgement of rising and falling edge interrupts.
This commit is contained in:
parent
5a12079e53
commit
de4fc5864f
@ -148,10 +148,10 @@
|
||||
#define GPIO_IS_INTR(ps) (((uint32_t)(ps) & GPIO_INTR_MASK) == GPIO_INTR_CODE)
|
||||
|
||||
#define GPIO_TRIG_MASK (0x18 << GPIO_FUNC_SHIFT) /* 111xx */
|
||||
#define GPIO_TRIG_LEVEL_CODE (0x08 << GPIO_FUNC_SHIFT) /* 010xx */
|
||||
#define GPIO_TRIG_EDGE_CODE (0x0c << GPIO_FUNC_SHIFT) /* 011xx */
|
||||
#define GPIO_IS_INTLEVEL(ps) (((uint32_t)(ps) & GPIO_TRIG_MASK) == GPIO_TRIG_LEVEL_CODE)
|
||||
#define GPIO_TRIG_EDGE_CODE (0x08 << GPIO_FUNC_SHIFT) /* 010xx */
|
||||
#define GPIO_TRIG_LEVEL_CODE (0x0c << GPIO_FUNC_SHIFT) /* 011xx */
|
||||
#define GPIO_IS_INTEDGE(ps) (((uint32_t)(ps) & GPIO_TRIG_MASK) == GPIO_TRIG_EDGE_CODE)
|
||||
#define GPIO_IS_INTLEVEL(ps) (((uint32_t)(ps) & GPIO_TRIG_MASK) == GPIO_TRIG_LEVEL_CODE)
|
||||
|
||||
#define GPIO_ALT_MASK (0x18 << GPIO_FUNC_SHIFT) /* 11xxx */
|
||||
#define GPIO_ALT_CODE (0x10 << GPIO_FUNC_SHIFT) /* 10xxx */
|
||||
@ -308,6 +308,20 @@ int lpc54_gpio_interrupt(lpc54_pinset_t pinset);
|
||||
int lpc54_gpio_irqno(lpc54_pinset_t pinset);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: lpc54_gpio_ackedge
|
||||
*
|
||||
* Description:
|
||||
* Acknowledge edge interrupts by clearing the associated bits in the rising and
|
||||
* falling registers. This acknowledgemment is, of course, not needed for level
|
||||
* interupts.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_LPC54_GPIOIRQ
|
||||
int lpc54_gpio_ackedge(int irq);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: lpc54_gpio_write
|
||||
*
|
||||
|
@ -243,7 +243,7 @@ int lpc54_gpio_interrupt(lpc54_pinset_t pinset)
|
||||
/* Write to CIENR to disable rising-edge or level interrupts */
|
||||
|
||||
case GPIO_INTFE: /* GPIO interrupt falling edge */
|
||||
putreg32(mask, LPC54_PINT_SIENR);
|
||||
putreg32(mask, LPC54_PINT_CIENR);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -260,7 +260,7 @@ int lpc54_gpio_interrupt(lpc54_pinset_t pinset)
|
||||
case GPIO_INTFE: /* GPIO interrupt falling edge */
|
||||
case GPIO_INTBOTH: /* GPIO interrupt both edges */
|
||||
case GPIO_INTHIGH: /* GPIO interrupt high level */
|
||||
putreg32(mask, LPC54_PINT_SIENR);
|
||||
putreg32(mask, LPC54_PINT_SIENF);
|
||||
break;
|
||||
|
||||
/* Write to CIENF to disable falling-edge or enable active-low level
|
||||
@ -269,7 +269,7 @@ int lpc54_gpio_interrupt(lpc54_pinset_t pinset)
|
||||
|
||||
case GPIO_INTRE: /* GPIO interrupt rising edge */
|
||||
case GPIO_INTLOW: /* GPIO interrupt low level */
|
||||
putreg32(mask, LPC54_PINT_SIENR);
|
||||
putreg32(mask, LPC54_PINT_CIENF);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -317,4 +317,46 @@ int lpc54_gpio_irqno(lpc54_pinset_t pinset)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: lpc54_gpio_ackedge
|
||||
*
|
||||
* Description:
|
||||
* Acknowledge edge interrupts by clearing the associated bits in the rising and
|
||||
* falling registers. This acknowledgemment is, of course, not needed for level
|
||||
* interupts.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
int lpc54_gpio_ackedge(int irq)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t mask;
|
||||
unsigned int pinint;
|
||||
|
||||
/* Map the IRQ number to a pin interrupt number */
|
||||
|
||||
if (irq >= LPC54_IRQ_PININT0 && irq <= LPC54_IRQ_PININT3)
|
||||
{
|
||||
pinint = irq - LPC54_IRQ_PININT0;
|
||||
}
|
||||
else if (irq >= LPC54_IRQ_PININT4 && irq <= LPC54_IRQ_PININT7)
|
||||
{
|
||||
pinint = irq - LPC54_IRQ_PININT4 + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Acknowledge the pin interrupt */
|
||||
|
||||
mask = (1 << pinint);
|
||||
regval = getreg32(LPC54_PINT_RISE) & mask;
|
||||
putreg32(regval, LPC54_PINT_RISE);
|
||||
|
||||
regval = getreg32(LPC54_PINT_FALL) & mask;
|
||||
putreg32(regval, LPC54_PINT_FALL);
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_LPC54_GPIOIRQ */
|
||||
|
@ -51,8 +51,12 @@ STATUS
|
||||
The I2C driver appears to be functional but is not yet well-tested.
|
||||
2017-12-16: Added support for LPC54xx GPIO interrupts; added button
|
||||
support (with interrupts) to the NSH configuration. The button
|
||||
test is partially functional but appears to miss a lot of button-
|
||||
related events. More testing is needed.
|
||||
test appears to functional functional. There are noticeable delays
|
||||
in receiving the button events, especially when the button is
|
||||
released. But if you do not press the buttons too quickly all events
|
||||
are processed. This, I suspect, is a consequence of the strong glitch
|
||||
filtering that is enbled in the pin configuration. Snappier
|
||||
response my be obtainble with filtering off.
|
||||
|
||||
Configurations
|
||||
==============
|
||||
@ -226,3 +230,26 @@ Configurations
|
||||
4. Support for the on-board USER button is included as well as the
|
||||
button test program at apps/examples/buttons. This test is useful
|
||||
for verifying the functionality of GPIO interrupts.
|
||||
|
||||
NuttShell (NSH) NuttX-7.23
|
||||
nsh> buttons
|
||||
buttons_main: Starting the button_daemon
|
||||
buttons_main: button_daemon started
|
||||
button_daemon: Running
|
||||
button_daemon: Opening /dev/buttons
|
||||
button_daemon: Supported BUTTONs 0x01
|
||||
nsh> Sample = 1
|
||||
Sample = 0
|
||||
Sample = 1
|
||||
Sample = 0
|
||||
Sample = 1
|
||||
Sample = 0
|
||||
Sample = 1
|
||||
etc.
|
||||
|
||||
There are noticeable delays in receiving the button events,
|
||||
especially when the button is released. But if you do not press the
|
||||
buttons too quickly all events are processed. This, I suspect, is a
|
||||
consequence of the strong glitch filtering that is enbled in the pin
|
||||
configuration. Snappier response my be obtainble with filtering off
|
||||
if desired.
|
||||
|
@ -55,6 +55,46 @@
|
||||
|
||||
#ifdef CONFIG_ARCH_BUTTONS
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_LPC54_GPIOIRQ) && defined(CONFIG_ARCH_IRQBUTTONS)
|
||||
static uint8_t g_button_irq;
|
||||
static xcpt_t g_button_handler;
|
||||
static void *g_button_arg;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_button_interrupt
|
||||
*
|
||||
* Description:
|
||||
* This function intermediates the interrupt provided to the application
|
||||
* logic that attached the interrupt. This is necessary to properly
|
||||
* clear the pending button interrupts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int board_button_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
/* Acknowledge the button interrupt */
|
||||
|
||||
(void)lpc54_gpio_ackedge(irq);
|
||||
|
||||
/* Transfer control to the attached interrupt handler */
|
||||
|
||||
if (g_button_handler != NULL)
|
||||
{
|
||||
return g_button_handler(irq, context, arg);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -72,7 +112,22 @@
|
||||
|
||||
void board_button_initialize(void)
|
||||
{
|
||||
(void)lpc54_gpio_config(GPIO_BUTTON_USER);
|
||||
int ret;
|
||||
|
||||
/* Configure the button GPIO interrupt */
|
||||
|
||||
ret = lpc54_gpio_config(GPIO_BUTTON_USER);
|
||||
if (ret >= 0)
|
||||
{
|
||||
#if defined(CONFIG_LPC54_GPIOIRQ) && defined(CONFIG_ARCH_IRQBUTTONS)
|
||||
/* Get the IRQ that is associated with the PIN interrupt and attach the
|
||||
* intermediate button interrupt handler to that interrupt.
|
||||
*/
|
||||
|
||||
g_button_irq = lpc54_gpio_irqno(GPIO_BUTTON_USER);
|
||||
(void)irq_attach(g_button_irq, board_button_interrupt, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -115,35 +170,26 @@ int board_button_irq(int id, xcpt_t irqhandler, FAR void *arg)
|
||||
|
||||
if (id == BUTTON_USER)
|
||||
{
|
||||
int irq;
|
||||
|
||||
/* Get the IRQ number assigned to the port/pin when it was condfigured. */
|
||||
|
||||
irq = lpc54_gpio_irqno(GPIO_BUTTON_USER);
|
||||
if (irq < 0)
|
||||
{
|
||||
return irq;
|
||||
}
|
||||
|
||||
/* Are we attaching or detaching? */
|
||||
|
||||
if (irqhandler != NULL)
|
||||
{
|
||||
/* Yes.. Attach and enable the interrupt */
|
||||
|
||||
ret = irq_attach(irq, irqhandler, arg);
|
||||
if (ret >= 0)
|
||||
{
|
||||
up_enable_irq(irq);
|
||||
}
|
||||
g_button_handler = irqhandler;
|
||||
g_button_arg = arg;
|
||||
up_enable_irq(g_button_irq);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No.. Disable and detach the interrupt */
|
||||
|
||||
up_disable_irq(irq);
|
||||
ret = irq_detach(irq);
|
||||
up_disable_irq(g_button_irq);
|
||||
g_button_handler = NULL;
|
||||
g_button_arg = NULL;
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user