Problem clearing pending interrupts

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Problem clearing pending interrupts

1,351 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by psatyshur on Sun Jan 12 10:22:06 MST 2014
I have a device that has several buttons. Each button is connected to a GPIO pin and an interrupt is used for each input to determine whether the user has pressed that button. The internal pullup for each pin is used to hold the pin high, and a high-to-low transition on the pin triggers the interrupt. To debounce the buttons, as well as limit the maximum speed they can be pressed, I set up a timer.

The plan was:
[list=1]
[*]User presses a button, this triggers an interrupt handler.
[*]The interrupt handler disables button interrupts.
[*]Interrupt handler calls code to deal with the interrupt.
[*]The interrupt starts a timer.
[*]After a certain amount of time, the timer causes an interrupt. This interrupt re-enables the button interrupts.
[/list]

However, no matter what I try, the button interrupt always fires when I re-enable interrupts. I have attached a simplified version of the relevant code below.
#define DEBOUNCE_TIMERLPC_TIMER16_0
#define DEBOUNCE_TIMER_IRQ_HANDLERTIMER16_0_IRQHandler
#define DEBOUNCE_TIMER_NVIC_NAMETIMER_16_0_IRQn

#define BUTTON_1_PORT0
#define BUTTON_1_PIN18
#define BUTTON_1_PININT_INDEX1
#define BUTTON_1_IRQ_HANDLERFLEX_INT1_IRQHandler/* IRQ function name */
#define BUTTON_1_NVIC_NAMEPIN_INT1_IRQn/* NVIC interrupt name */

void App_Button_Init(void)
{
//Initialize the timer for the debouncing, but don't start it
Chip_TIMER_Init(DEBOUNCE_TIMER);
Chip_TIMER_Reset(DEBOUNCE_TIMER);

DEBOUNCE_TIMER->PR = 1000;
DEBOUNCE_TIMER->MCR = (1<<1)|(1<<0);//Enable MR0 match interrupt, Reset TC on MR0 match
DEBOUNCE_TIMER->MR[0]= 0xFFFF;//MR0 match value

//Enable the IRQ for the timer
NVIC_EnableIRQ(DEBOUNCE_TIMER_NVIC_NAME);

//Set all button pins to GPIO input with pullup
Chip_IOCON_PinMuxSet(LPC_IOCON, BUTTON_1_PORT, BUTTON_1_PIN, (IOCON_FUNC0 | IOCON_MODE_PULLUP));
Chip_GPIO_SetPinDIRInput(LPC_GPIO, BUTTON_1_PORT, BUTTON_1_PIN);

Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_PINT);

//Setup GPIO interrupts for each button

/* Configure interrupt channel for the GPIO pin in SysCon block */
Chip_SYSCTL_SetPinInterrupt(BUTTON_1_PININT_INDEX, BUTTON_1_PORT, BUTTON_1_PIN);

/* Configure channel interrupt as edge sensitive and falling edge interrupt */
Chip_PININT_SetPinModeEdge(LPC_PININT, PININTCH(BUTTON_1_PININT_INDEX));
Chip_PININT_EnableIntLow(LPC_PININT, PININTCH(BUTTON_1_PININT_INDEX));

Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH(BUTTON_1_PININT_INDEX));

App_EnableButtons();

return;
}

void App_EnableButtons(void)
{
        NVIC_ClearPendingIRQ(BUTTON_1_NVIC_NAME);

Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH(BUTTON_1_PININT_INDEX));

NVIC_EnableIRQ(BUTTON_1_NVIC_NAME);

return;
}

void App_DisableButtons(void)
{
NVIC_DisableIRQ(BUTTON_1_NVIC_NAME);

NVIC_ClearPendingIRQ(BUTTON_1_NVIC_NAME);

Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH(BUTTON_1_PININT_INDEX));

return;
}

void BUTTON_1_IRQ_HANDLER(void)
{
App_DisableButtons();
        DEBOUNCE_TIMER->TCR = 0x01;
App_HandleButtonPress(BUTTON_1_PININT_INDEX);
Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH(BUTTON_1_PININT_INDEX));
return;
}

void DEBOUNCE_TIMER_IRQ_HANDLER(void)
{
//Turn off timer and re-enable buttons
DEBOUNCE_TIMER->TCR = 0x00;
Chip_TIMER_Reset(DEBOUNCE_TIMER);
DEBOUNCE_TIMER->IR = 0xFF;

App_EnableButtons();
}


As you can probably see, I applied liberal use of the Chip_PININT_ClearIntStatus() and NVIC_ClearPendingIRQ(), but it does not seem to matter. Is there some trick to clearing pending interrupts? Is there a better way to do what I am trying to do?
Labels (1)
0 Kudos
3 Replies

1,023 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MarcVonWindscooting on Fri Jan 17 11:29:23 MST 2014
Now that I've read your posts, I believe I have a similar problem on a LPC812 after waking up from power down using pin interrupts.
I'll check that soon. (LPC800 is similar to LPC1100 in more than a few things).
0 Kudos

1,023 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by psatyshur on Sun Jan 12 19:13:16 MST 2014
Thanks for the suggestion. It worked    I modified the EnableButtons() function like so:

void App_EnableButtons(void)
{
Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH(BUTTON_1_PININT_INDEX));        

NVIC_ClearPendingIRQ(BUTTON_1_NVIC_NAME);

NVIC_EnableIRQ(BUTTON_1_NVIC_NAME);

return;
}


And everything seems to work the way I want.
0 Kudos

1,023 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kfishy on Sun Jan 12 14:25:31 MST 2014
Have you tried clearing the interrupt status before clearing the interrupt pending bit in the NVIC? If the interrupt status is set when you clear the pending bit, the interrupt may become pended again.

Tony
0 Kudos