Interrupts remain after detach

Hi!

I have an ISR which will set a flag (which is later handled in the main body).
Inside the ISR, I detach the interrupt pin that triggered it. However, the code in the main body runs twice...
The code I have is here:

(Pullups enabled on pin 2, with a button attached to ground)

//ISR:
void homeISR(){
  ISRFlags|=1;
  detachInterrupt(digitalPinToInterrupt(2));
}

//Loop
void loop(){
  [...]
  //Somewhere over the rainbow, "attachInterrupt(digitalPinToInterrupt(2),&homeISR,FALLING);" is called
  if(ISRFlags&1){
    noInterrupts();
    goHome();
    ISRFlags&=~1;//Originally, I was doing "ISRFlags^=1" which should work faster, but I wanted to go with something more reliable
    interrupts();
  }
  [...]
}

If the button is pressed while the ISR is disabled, it will be left pending, triggering the ISR whenever it is attached again (even when the condition is no longer met). It is not called instantly (this is known because the TFT I'm using flickers whenever "goHome()" is called, and it doesn't flicker when pressing the button...)

Why are you calling the goHome() function while interrupts are disabled?
Why are you disabling the interrupts at all?

Wouldn't ISRFlags = 0; be a lot simpler and more obvious than ISRFlags&=~1;

You need to post the complete program.

Maybe it would be a good idea to clear the interrupt flag in the appropriate atmega register immediately after your detachInterrupt()

...R

The disable interrupts thing was just to try and test if that would somehow (magically) fix it. I probably should’ve removed it before posting :stuck_out_tongue:
I used the ISRFlags&=~1; because I might want to use ISRFlags to store more flags than just the one (looking into the future). I used a byte because I’m trying to save dynamic memory space and 8 bools would use 8 bytes, as opposed to the single byte (sacrificing speed and simplicity for size).

My code is long (12 files, 30-100 lines each). Most of it has no relation to the problem at hand.

As for messing with registers, I could try it. I do not know how those particular registers work, but I’ll look into it!

You may be seeing the multiple triggers from a queued interrupt due to switch bounce in the few microseconds (based on the interrupt latency) before you detach the interrupt.

Add some hardware debouncing to the button switch, or try a software lock out to debounce the ISR.

void homeISR()
{
  const unsigned long lock_out = 20;
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  if (interrupt_time - last_interrupt_time >= lock_out)
  {
    ISRFlags |= 1;
  }
  last_interrupt_time = interrupt_time;
 
}

Why do you need interrupts to read a switch pressed by a human. You could be using polling with robust software debouncing looking for a stable input signal.

I need an interrupt because this is the switch that wakes the AVR from SLEEP_MODE_PWR_DOWN.
For simplicity, even when the AVR is not in sleep mode, I use the same interrupt to handle my code (which, in some cases, can take a while before reaching loop again, adding the possibility for dropped input).

Because my code can take a while, I do not think this switch is bouncing. Even if it did, the same flag would just be set multiple times, having no effect because the flag is only occasionally cleared.

Fuzzyzilla:
My code is long (12 files, 30-100 lines each). Most of it has no relation to the problem at hand.

It can be a good idea (for you, and certainly for us) to write a short program that illustrates the problem.

Because my code can take a while, I do not think this switch is bouncing.

That would make sense if you are NOT using an interrupt - but it does not make sense with an interrupt because it responds regardless of the rest of the code.

...R