0

Summary: An ISR necessarily causes its own trigger pin to toggle randomly multiple times. These toggles (during the ISR) should be ignored, but aren't, and result in another interrupt to be set as pending and get executed afterwards.


I have a serial bit-bang device that I read via an interrupt. Device has a data pin and a "clock" pin. Data pin is HIGH by default. When the device is ready to be read, it pulls this data pin LOW. After this falling edge, each pulse on the "clock" pin shifts one bit out to the data pin.

An interrupt triggers on the falling edge of the data pin, and ISR bangs 24 bits of data out of the same data pin. Therefore, additional random falling edges on the data pin causes another interrupt to be set as pending. Which triggers immediately after the actual ISR has returned, resulting two consecutive interrupts being run per one "real" interrupt.

I have tried multiple ways to disable interrupts and/or clear pending interrupts, none of which seem to have any effect whatsoever. I suspect that this is because manipulating interrupt related registers is not allowed/or ignored in an ISR.

The device is Atmel ATSAMD21. (ARM Cortex M0+). Code is built under Atmel Studio with optimisation level -Og.I am okay with using ASF and/or SAM libraries/definitions, ARM CMSIS or baremetal register manipulation. Whichever happens to work.

Here is what I tried so far:

void interrupt_cb ( void )
{
    // Trying to disable interrupts
    // Executed at the beginning of the ISR
    NVIC_DisableIRQ(EIC_IRQn);
    ext_irq_disable( <pin> );
    __disable_irq();

    // body
    // < code that results in same pin   >
    // < that the interrupt is triggered >
    // < to be toggled randomly.         >

    // Trying to clear pending interrupts
    // Executed just before the ISR returns.
    NVIC_ClearPendingIRQ( EIC_IRQn );
    NVIC->ICPR[0] |= 4; //probably same as the above
    EIC->INTENCLR.bit.EXTINT2 = 1;
}


Or a combination of these commands.

aulven
  • 521
  • 3
  • 14
  • Everything you've tried is inside the CortexM core/NVIC. I don't know about this particular part but in many microcontrollers there is an interrupt register in the peripheral whose bits latch before the signal gets to the core. You may need to clear it there first first, then the one in the core. – Tom V Jan 30 '23 at 16:24
  • @TomV I cannot seem to find any mentions of such register in the datasheet. It provides set, clear and flag registers, as well as seemingly unrelated config, nmi-related and event registers. Any idea what such a register is called in other devices, so that maybe I can find the equivalent in this device? – aulven Jan 30 '23 at 17:03
  • In addition to *disabling* the external interrupt, you also need to *clear* the interrupt condition that invoked the isr in the first place (by writing to INTFLAG). – Jeremy Mar 29 '23 at 10:24

0 Answers0