Open MojaveTom opened 3 years ago
When I implemented these suggestions, I realized two things:
LowPower.cpp
// variable global to this file.
volatile static bool wdtFinished;
...
void LowPowerClass::powerDown(period_t period, adc_t adc, bod_t bod)
{
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
// set wdtFinished true if SLEEP_FOREVER so single test will terminate sleep
wdtFinished = period == SLEEP_FOREVER; // assigned before IE to prevent race
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
do { // Do this at least once even if SLEEP_FOREVER
if (bod == BOD_OFF)
{
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
lowPowerBodOff(SLEEP_MODE_PWR_DOWN);
#else
lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
}
} while (!wdtFinished);
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
}
...
ISR (WDT_vect)
{
// WDIE & WDIF is cleared in hardware upon entering this ISR
wdt_disable();
wdtFinished = true;
}
The other functions would have similar modifications.
This suggestion is similar to issue #111 in that a flag is to be set when the watch dog timer interrupt service routine is executed, but it this case, it is used to re-sleep the CPU if it is awakened by some other interrupt to ensure that the power saving function does not exit before the WDT interrupt happens. As I see it, the problem is that when the CPU wakes up in powerDown it doesn't know which interrupt awakened it, so it just assumes that it was the WDT. Since the interrupt service routine for the WDT is in that same module, it is easy to add a flag that is set when the WDT interrupt is entered, and cleared when the powerDown function first sleeps the CPU. The CPU is just put back to sleep if it is awakened and the wdtFinished flag is still false. When the wdtFinished flag is true, the powerDown function exits as usual.
With this modification, the time in the powerDown function is not short circuited by an unexpected interrupt.
The powerSave, powerStandby, and powerExtStandby functions could be modified in a similar manner.