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?
1 Answer 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.
-
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 withE.HP.S– E.HP.S2023年10月19日 13:25:12 +00:00Commented Oct 19, 2023 at 13:25
-
@E.HP.S See amended answer.2023年10月20日 02:43:11 +00:00Commented Oct 20, 2023 at 2:43
if(!isReady)return;
, and addisReady=true;
after your attachInterrupt call. Or maybe just snuff the first call withif(!isReady){ isReady=true;return;}
in the handler.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.