1

This question might be a bit broad, but I'm running into an apparently classic problem with Arduino interrupts, where the rising or falling edge flag is triggered prior to a rising or falling edge technically occurring before a pin is pulled high/low and the microcontroller "remembering" that event occurred, running the interrupt the moment it gets attached to a pin. In this case, I'm working with Sparkfun's Artemis module (using the Apollo3 microcontroller). The code in question can be seen below:

#define SLEEP_INTERRUPT   4

void setup
{
    pinMode(SLEEP_INTERRUPT, INPUT);
#ifdef DEBUG
  Serial.print("About to attach interrupt");
#endif
  attachInterrupt(digitalPinToInterrupt(SLEEP_INTERRUPT), sleepModeSwitch, FALLING);
#ifdef DEBUG
  Serial.print("Interrupt attached");
#endif
}

void sleepModeSwitch()
{
#ifdef DEBUG
  Serial.print("Interrupt triggered! button status: "); Serial.println(digitalRead(SLEEP_INTERRUPT));
#endif
  if(sleep_mode_status == false)
  {
    goToSleep();
  }
  else
  {
    wakeUp();
  }
}

void goToSleep()
{
  sleep_mode_status = true;
#ifdef DEBUG
  Serial.println("Going to sleep");
  delay(50);  //Wait for serial to finish
  Serial.end(); //Power down UART(s)
#endif
  // turn off the led.
  digitalWrite(LED_BUILTIN, LOW);

  // Stop the BLE advertising.
  BLE.stopAdvertise() ;

  powerControlADC(false);
  
  for(int x = 0; x < 50; x++)
  {
    if(x != 4)
    {
      am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE);
    }
  }
  //Power down Flash, SRAM, cache
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE); //Turn off CACHE
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_512K); //Turn off everything but lower 512k
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_64K_DTCM); //Turn off everything but lower 64k
  //am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); //Turn off all memory (doesn't recover)
  
  // // Enable interrupts to the core.
  am_hal_interrupt_master_enable();
  
  // //Enable the timer interrupt in the NVIC.
  // NVIC_EnableIRQ(STIMER_CMPR6_IRQn);

  //Go to Deep Sleep.
  am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}

void wakeUp()
{
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX);
  
  // Re-enable UART0 pins
  am_hal_gpio_pinconfig(48, g_AM_BSP_GPIO_COM_UART_TX);
  am_hal_gpio_pinconfig(49, g_AM_BSP_GPIO_COM_UART_RX);

  am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_UART0);

  initializeADC();

#ifdef DEBUG
  Serial.begin(115200);
  Serial.println("Waking up! Hello world!");
#endif
  deepSleepTimer = millis() ;
  sleep_mode_status = false;
}

Based on my research, the solution for this is to just clear the interrupt flag manually before attaching the interrupt to your desired pin. Unfortunately, so far the methods for doing so that I've found only work for AVR boards, and I'm not certain where to look to find more information about how to access an interrupt flag in a sketch for a 3rd-party Arduino core. Does anyone have a suggestion or two on where to start?

5
  • Not sure I understand the issue, but it sounds like you could declare a volatile bool, isReady=false, and in the top of the handler say something like if(!isReady)return;, and add isReady=true; after your attachInterrupt call. Or maybe just snuff the first call with if(!isReady){ isReady=true;return;} in the handler.
    – dandavis
    Oct 18, 2023 at 22:19
  • Can you rule out the following possible cause of your problem? github.com/sparkfun/Arduino_Apollo3/issues/416
    – 6v6gt
    Oct 19, 2023 at 5:31
  • @6v6gt Would a 10k pullup resistor negate this issue?
    – E.HP.S
    Oct 19, 2023 at 13:28
  • It does appear from that problem report, if it is relevant to your case, that an external pullup would solve it. If you are invoking attachInterrupt() in setup() only then you could also do a trick (workaround) with a global variable say endOfSetup and ignore any calls to the ISR where this was not set. Cleaning up, clearing flags etc., before using attachInterrupt() is very common so IMHO it is wrong that you have to go under the abstraction layer to do it.
    – 6v6gt
    Oct 19, 2023 at 21:33
  • @6v6gt I followed advice from elsewhere (and from dandavis) and made a software debounce with the millis() function to prevent the interrupt from getting too far if it's called too often. I also talked with someone on the Sparkfun forums about this and we might have fixed it. Seems it was a problem in the core's commonInterrupt.cpp file. Not certain, but I've at least stopped that premature interrupt from screwing up the device, even if I'm not certain I've stopped it from running at all. Still experimenting
    – E.HP.S
    Oct 20, 2023 at 13:26

1 Answer 1

1

the rising or falling edge flag is triggered prior to a rising or falling edge technically occurring before a pin is pulled high/low and the microcontroller "remembering" that event occurred, running the interrupt the moment it gets attached to a pin

There is no "technically" about it. This is what is supposed to happen. Once you configure the interrupt to happen (as you do in setup) then the processor will remember that the condition has happened, whether or not interrupts are enabled.

If you want the interrupt only to be processed after a certain point, then yes, you should clear the "interrupt has happened" flag in the MCU, before enabling interrupts.

Your question is pretty non-specific about exactly which processors you are talking about, but I would certainly clear any appropriate flags before attaching the interrupt.

I'm not certain where to look to find more information about how to access an interrupt flag in a sketch for a 3rd-party Arduino core

The datasheet of the device on this particular core?


Judging by the datasheet for the Apollo3 Blue SoC:

6.3.2.15 INTCLR Register

IO Master Interrupts: Clear

OFFSET: 0x00000228

INSTANCE 0 ADDRESS: 0x5000C228

Write a 1 to a bit in this register to clear the interrupt status associated with that bit.

However I don't have one of those processors around to test it.

2
  • Added a link to the device and a link to the datasheet for the microcontroller it contains. In this case, it's Sparkfun's Artemis module, containing Ambiq's Apollo3 Blue SoC. And you're right, I was asking this in a more general fashion, intending to learn in general where to learn how to clear these flags for when I'm working with another microcontroller I'm getting to grips with
    – E.HP.S
    Oct 19, 2023 at 13:25
  • @E.HP.S See amended answer.
    – Nick Gammon
    Oct 20, 2023 at 2:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.