Page 1 of 1

MODM7AE70 Interrupt Disable

Posted: Thu Sep 21, 2023 3:28 am
by johnvan
I'm using a MODM7AE70 module and have one of the I/O pins set up to provide an interrupt whenever that pin is grounded. The interrupt works fine. I use EnableIrq() and DisableIrq() to disable the interrupt whenever I don't want it to occur. These also work fine but my problem is that the interrupt appears to be "latched". For example, I can disable the interrupt using DisableIrq() however if the pin happens to get grounded while the interrupt is disabled this appears to set a "pending" bit somewhere such that if the pin goes back high and I re-enable the interrupt using EnableIrq() I still get the interrupt.

What I'm looking for is a way to clear any pending interrupt so that I don't get sent to the ISR when it's re-enabled. I can see in the pin-irq.cpp source that there are pin registers manipulated (PIO_IER and PIO_IDR) when we Enable and Disable interrupts. Is there a "pending" register I could manipulate to keep the latched interrupt from happening when it's re-enabled?

Thanks,
John

Re: MODM7AE70 Interrupt Disable

Posted: Mon Sep 25, 2023 2:23 pm
by mlara
Hi John,

Please, try the following function to see if it resolves your issue.

You'll need to place the following source in \nburn\platform\MODM7AE70\source\pin_irq.cpp

Code: Select all

void ClearISR(PinIO pin)
{
    int idx = &(pin.pio) - PIOA;                // PIO controller index
    volatile uint32_t isr = pin.pio.PIO_ISR;    // Interrupt Status Register, clears on read
    uint32_t imr = pin.pio.PIO_IMR;             // Interrupt Mask Register

    // Since up to 32 pins are grouped into a PIO controller, interrupts for each pin in the given PIO must be handled upon reading the PIO_ISR reg
    if (isr & imr)  // check if any interrupts are enabled and if any interrupt events occurred
    {
        for (int i = 0; i < 32; i++)
        {
            // if the interrupt is enabled, an interrupt event occurred, an ISR function is registered, and
            // the interrupt pin is NOT the pin given as a parameter, then call the ISR function.
            if ((isr & imr & (1U << i) & ~pin.mask) && PIO_Vects[(idx * 32) + i]) { PIO_Vects[(idx * 32) + i](idx, i); }
        }
    }
}
You'll also need to place the following declaration in \nburn\arch\cortex-m7\cpu\SAME70\include\pin_irq.h

Code: Select all

#ifdef MODM7AE70
/**
 * @brief Clears the Interrupt Status Register (PIO_ISR) for a given pin.
 *
 * This function will clear the interrupt for a given pin by accessing the PIO_ISR
 * register, which is cleared upon reading. Since up to 32 pins are grouped into
 * a PIO controller and reading the PIO_ISR clears the interrupt for all pins in
 * a given PIO, interrupts for every pin that are grouped into the given pin's PIO
 * are handled by this function.
 *
 * @param pin   A PinIO object that is to be configured as an IRQ Pin.
 *
 * @returns     the contents of the status register (PIO_ISR) for a given pin.
 */
uint32_t ClearISR(PinIO pin);
#endif // end MODM7AE70
Alternatively, I can send you updated source files if you let me know which version of the NNDK you're using.

To use the function in your application, you'll want to call ClearISR() before re-enabling interrupts with a call to EnableIrq().

Re: MODM7AE70 Interrupt Disable

Posted: Wed Sep 27, 2023 1:50 am
by johnvan
Mike,

Thank you very much for your ClearISR() routine! It works perfectly. The only change I made was to the forward declaration in pin_irq.h. The actual routine returns void and the forward declaration called for it to return uint32_t. Instead of changing the Netburner source I simply incorporated it into my application. I'm currently using NNDK 3.38. I downloaded 3.39 but for some reason I'm getting a compiler error when I build it. I have not bothered to try and figure it out yet.

Thanks again for your help, I really appreciate it.
John