lpcware

Problem clearing pending interrupts

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
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?

Outcomes