Go Down

Topic: ArduinoLowPower library for ZERO not working? (Read 201 times) previous topic - next topic

boggydew

Hi,

I am trying to use the idle() function from the ArduinoLowPower library.
Ref: https://www.arduino.cc/en/Reference/LowPowerIdle
Ref: https://www.arduinolibraries.info/libraries/arduino-low-power

The reference to idle() on the Arduino web site says the CPU should stop, but the following sketch continues to run for me, ie the TX_LED continues to flash.

Code: [Select]
#include "ArduinoLowPower.h"

void setup() {
  pinMode(26, OUTPUT);
}

void loop()
{
  LowPower.idle();
 
  digitalWrite(26, LOW);
  delay(500);
  digitalWrite(26, HIGH);
  delay(500);
}


Looking into the .cpp of the library the routine does as the datasheet describes:

16.6.2.8.1 IDLE Mode
Entering IDLE mode: The IDLE mode is entered by executing the WFI instruction.  Before entering theIDLE mode, the user must configure the IDLE mode configuration bit group and must write a zero
to the SCR.SLEEPDEEP bit.

Code: [Select]
void ArduinoLowPowerClass::idle() {
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
PM->SLEEP.reg = 2;
__DSB();
__WFI();
}


Why doesn't it work for me? Does it work for anyone else?

Thanks.

pert

I get the same results as you do. Unfortunately, I don't have an explanation for you. LowPower.sleep() works as expected for me.

boggydew

Thanks Pert,

At least now I know its not something peculiar to my setup.

Cheers

Jiggy-Ninja

Not sure how the terminology works for the Zero, but idle is probably the lightest sleep mode that just turns off the CPU and leaves all the peripherals running. Usually any interrupt will be enough to wake the CPU up and let it continue running. It's probably the timer interrupt that left running that 's waking you up.
Hackaday: https://hackaday.io/MarkRD
Advanced C++ Techniques: https://forum.arduino.cc/index.php?topic=493075.0

boggydew

#4
Mar 06, 2019, 06:31 am Last Edit: Mar 06, 2019, 06:48 am by boggydew
It's probably the timer interrupt that left running that 's waking you up.
I thought that myself but disabling global interrupts makes no diffo.
It may be a flag that's already set but I wouldn't know where to look to clear it.

Code: [Select]
void loop()
{
 noInterrupts();
 LowPower.idle();
 interrupts();
 
 digitalWrite(26, LOW);
 delay(500);
 digitalWrite(26, HIGH);
 delay(500);
}



boggydew

Me again, the problem was two fold. SysTick keeps going in idle mode, which generates an interrupt for millis(). Also having an active native USB connection causes interrupts as well.  Unmasking SysTick interrupt and disabling USB gets idle working.

Code: [Select]
USBDevice.detach();
  SysTick->CTRL  &= ~SysTick_CTRL_TICKINT_Msk;
  LowPower.idle();
  SysTick->CTRL  |= SysTick_CTRL_TICKINT_Msk;

vanderDecken

I did a bit of light reading in the Cortex M0 Devices Generic User Guide. It's the WFI (Wait For Interrupt) instruction in the idle function that's the culprit. Even with interrupts disabled with a noInterrupts() call, it wakes up from idle as soon as an interrupt is pending. The intention of idle() might be to be used in a tight loop, which only exits when a flag is set in an interrupt or similar mechanism.

Go Up