So I'm baffled by this...
I'm working with an ARMv7-M microcontroller and GCC compiler, debugging some code where I'm trying to enable an interrupt. I'm trying to do the following: enable an interrupt so that on a value change for pin PA31, pin PA9 gets set to low, using the MCU's PIO controller. The interrupt handler is just called PIOA_Handler, it is declared in one of the device files as:
void PIOA_Handler ( void ) attribute ((interrupt));
And the guts of the function are in main.cpp:
void PIOA_Handler(void)
{
if ((*((Pio*)PIOA)).PIO_PDSR < PIO_PDSR_P31_Msk) {
((*((Pio*)PIOA)).PIO_CODR |= PIO_CODR_P9_Msk); // clear output on pin 9 if pin PA31 is logic low
}
I start by enabling global interrupts and setting PA9 to out, and enabling the change interrupt for pin PA31 on the peripheral side and also enabling the NVIC interrupt vector so the processor accepts and handles the interrupt:
gpio_set_pin_direction(PIN_PA9, GPIO_DIRECTION_OUT); // set PA9 to out and PA31 to in
sys->setPin(PIN_PA9, true); // enable PA9
((Pio *)PIOA)->PIO_IER |= PIO_IER_P31_Msk;
NVIC_EnableIRQ(PIOA_IRQn);
The actual problem that I'm having is this: for some reason, when I'm debugging without setting a breakpoint, rather than calling PIOA_Handler when there is a pin change, it just gets called continuously, over and over for the entire length of the debugging session.
If, however, I set a breakpoint on the line of code where I enable the PIO level change interrupt:
((Pio *)PIOA)->PIO_IER |= PIO_IER_P31_Msk;
this somehow doesn't happen and PIOA_Handler gets called as it should, when there really is a level change on PA31.
One more thing I've noticed is that if I set a breakpoint on the next line NVIC_EnableIRQ(PIOA_IRQn);
, and look at the NVIC Interrupt Set Pending Register (ISPR) in one of the debugger watch windows, there is a pending interrupt for PIOA_IRQn. But if I set a breakpoint on ((Pio *)PIOA)->PIO_IER |= PIO_IER_P31_Msk;
and step over to the NVIC_EnableIRQ line, there is no pending interrupt.
I've tried inserting NVIC_ClearPendingIRQ between the two lines, but it doesn't clear the pending IRQ. For whatever reason somehow the breakpoint clears it, but using an actual Clear Pending function does not do the trick. Why is this and how do I write code that doesn't need a breakpoint for the interrupt handler to be called properly?
Thanks in advance!