0
votes

I am facing a weird problem with the external interrupts of the LPC17xx series.

I have an external button set to external interrupt 1, falling edge with both an internal as an external pull-up resistor (p2.11):

PinCfg.Funcnum = 1;
PinCfg.OpenDrain = 0;
PinCfg.Pinmode = PINSEL_PINMODE_PULLUP;
PinCfg.Pinnum = 11;
PinCfg.Portnum = 2;
PINSEL_ConfigPin(&PinCfg);
GPIO_SetDir(2,((uint32_t)1<<11),0);

And:

EXTICfg.EXTI_Line = EXTI_EINT1;
EXTICfg.EXTI_Mode = EXTI_MODE_EDGE_SENSITIVE;
EXTICfg.EXTI_polarity = EXTI_POLARITY_LOW_ACTIVE_OR_FALLING_EDGE;
EXTI_Config(&EXTICfg);
EXTI_ClearEXTIFlag(EXTI_EINT1);

And:

NVIC_SetPriority(EINT1_IRQn,1);
NVIC_EnableIRQ(EINT1_IRQn);

This is a part of the ISR (including 200ms button debouncing timer):

void EINT1_IRQHandler(void)
{
    EXTI_ClearEXTIFlag(1);

    uint32_t tim1Cnt = LPC_TIM1->TC;

    if (tim1Cnt > ButtDebounceUs)
    {
        LPC_TIM1->TC = 0x00000000;

        // Do work here
    }
}

The "Do work here" section could take some time (e.g. more than 200ms in some cases). This is intended and no problem for the further execution of the program.

The problem is that when the ISR is entered first and I press the button a second time while the ISR is executing (this has to be done fast) a pending interrupt is set and causes the ISR to execute again if it has ended for the first time. This is normal behaviour I guess, since EXTI_ClearEXTIFlag(1) does not clear any pending interrupts in the NVIC. So I added NVIC_ClearPendingIRQ(EINT1_IRQn) to clear the new pending interrupts on several locations in the ISR code to be sure the pending interrupt(s) is/are cleared. Strangely enough this does not work at all.

Some my question is, how can I read the pending interrupts via JTAG/debugger (memory address?). And what is going on here? Can someone explain this behaviour and maybe has a clue how to fix it?

Thanks!

2
That's a strange looking ISR: there's code, a declaration and then more code. You say you added some operations, but don't show them and ask for code review? Shouldn't the reset of LPC_TIM1->TC occur after the 200ms of processing? BTW performing 200ms of processing in an ISR is usually a bad idea. This usually causes repercussions like increasing latencies elsewhere. You should consider implementing a tasklet.sawdust
why are you doing the work in the isr? you need to be in and out of the isr asap. set a flag or increment a counter, have the foreground task see the flag/counter and handle the button press.old_timer

2 Answers

1
votes

when the ISR is entered first and I press the button a second time [...]

This triggers the EINT1 Flag again, but after you cleared it first. Thats why

NVIC_ClearPendingIRQ(EINT1_IRQn) to clear the new pending interrupt

does not work, as EINT1 still signals the interrupt line. You need to call

EXTI_ClearEXTIFlag(1);

again after the "work" to clear this flag.

0
votes

I know that it is usually not a good idea to make such a long interrupt routine. But as I have stated in the question, this is intended. I need to make sure not other code in the main task is executed during the ISR.

But to come back to the question: someone else pointed out that it maybe is a good idea to move the EXTI_ClearEXTIFlag(1) to the end of the ISR. In this way no external interrupt can accur, nor any pending can be set during excecution of the ISR. This works, but I am still wondering why clearing the pending interrupt does not work. Maybe this only works for GPIO interrupts?