Interrupts() and WFI();

Dear All,

What is the use of disabling and enabling the interrupts in:

  noInterrupts();
    if (!(sodaq_wdt_flag || minuteFlag)) 
	{
        interrupts();

        __WFI(); // SAMD sleep
    }
    interrupts();

Thanks,

Axel

That conditional statement tests two volatile flags, both of which are modified by asynchronous interrupt service routines. The code is designed to only enter sleep mode if neither is set. There is the possibility that one or both of those are modified during or after that conditional check but before entering sleep mode. This may cause issues.

The interrupts are disabled during the testing of those flags. Additionally, I believe there is a guarantee of the next instruction being executed after the interrupts are enabled.

Any interrupts which are generated after the interrupts are disabled but before the board enters sleep, will remain pending until the board enters sleep mode at which point the interrupts will be re-enabled and the board will wake-up.

This specific code effectively stops interrupts from modifying those flags and leaves them pending until the board enters sleep mode.

Hi Gabriel,

This makes perfectly sense. Thanks for explaining.

One more related question:

Is there any functional difference between putting the _WFI() before the Things to be done or afterwards?

Like:

void loop()
{
	if (IRQ1_flag)
	{
		IRQ1_flag = false;

		// Do something
	}

	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
	__WFI();
}

or

void loop()
{
	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
	__WFI();

	if (IRQ1_flag)
	{
		IRQ1_flag = false;

		// Do something
	}

}

It might make a difference during the first pass of loop(), as to whether the something is executed before entering sleep, or not.

If you look at the file main.cpp in the Arduino SAMD core, you will see that the main loop just calls loop() continuously. The call to serialEventRun() does not seem to be implemented on the SAMD platform. On the AVR platform this handles the calls to the SerialEvent() methods. These are weakly bound and are called synchronously after loop() if there has been activity on the associated UART.