Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolves #112 Restart sleep if WDT not what awakened CPU. #113

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 101 additions & 57 deletions LowPower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ do { \
#endif
#endif

// variable global to this file.
volatile static bool wdtFinished;

/*******************************************************************************
* Name: idle
* Description: Putting ATmega328P/168 into idle state. Please make sure you
Expand Down Expand Up @@ -194,13 +197,17 @@ void LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2,
if (usart0 == USART0_OFF) power_usart0_disable();
if (twi == TWI_OFF) power_twi_disable();

// 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);
}

lowPowerBodOn(SLEEP_MODE_IDLE);
do { // Do this at least once even if SLEEP_FOREVER
lowPowerBodOn(SLEEP_MODE_IDLE);
} while (!wdtFinished);

if (adc == ADC_OFF)
{
Expand All @@ -210,9 +217,9 @@ void LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2,

if (timer2 == TIMER2_OFF)
{
// Restore previous setting
TCCR2B = clockSource;
// Restore previous setting
TCCR2B = clockSource;

power_timer2_enable();
}

Expand Down Expand Up @@ -304,13 +311,17 @@ void LowPowerClass::idle(period_t period, adc_t adc,
if (twi == TWI_OFF) power_twi_disable();
if (usb == USB_OFF) power_usb_disable();

// 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);
}

lowPowerBodOn(SLEEP_MODE_IDLE);
do { // Do this at least once even if SLEEP_FOREVER
lowPowerBodOn(SLEEP_MODE_IDLE);
} while (!wdtFinished);

if (adc == ADC_OFF)
{
Expand Down Expand Up @@ -418,13 +429,17 @@ void LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2,
if (usart0 == USART0_OFF) power_usart0_disable();
if (twi == TWI_OFF) power_twi_disable();

// 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);
}

lowPowerBodOn(SLEEP_MODE_IDLE);
do { // Do this at least once even if SLEEP_FOREVER
lowPowerBodOn(SLEEP_MODE_IDLE);
} while (!wdtFinished);

if (adc == ADC_OFF)
{
Expand Down Expand Up @@ -567,13 +582,17 @@ void LowPowerClass::idle(period_t period, adc_t adc, timer5_t timer5,
if (usart0 == USART0_OFF) power_usart0_disable();
if (twi == TWI_OFF) power_twi_disable();

// 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);
}

lowPowerBodOn(SLEEP_MODE_IDLE);
do { // Do this at least once even if SLEEP_FOREVER
lowPowerBodOn(SLEEP_MODE_IDLE);
} while (!wdtFinished);

if (adc == ADC_OFF)
{
Expand Down Expand Up @@ -711,13 +730,17 @@ void LowPowerClass::idle(period_t period, adc_t adc, timer5_t timer5,
if (usart0 == USART0_OFF) power_usart0_disable();
if (twi == TWI_OFF) power_twi_disable();

// 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);
}

lowPowerBodOn(SLEEP_MODE_IDLE);
do { // Do this at least once even if SLEEP_FOREVER
lowPowerBodOn(SLEEP_MODE_IDLE);
} while (!wdtFinished);

if (adc == ADC_OFF)
{
Expand Down Expand Up @@ -799,13 +822,17 @@ void LowPowerClass::adcNoiseReduction(period_t period, adc_t adc,

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);
}

lowPowerBodOn(SLEEP_MODE_ADC);
do { // Do this at least once even if SLEEP_FOREVER
lowPowerBodOn(SLEEP_MODE_ADC);
} while (!wdtFinished);

if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);

Expand Down Expand Up @@ -855,23 +882,28 @@ 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);
}
if (bod == BOD_OFF)
{
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
lowPowerBodOff(SLEEP_MODE_PWR_DOWN);
#else

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);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
}
}
} while (!wdtFinished);

if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
}
Expand Down Expand Up @@ -940,24 +972,28 @@ void LowPowerClass::powerSave(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);
}

if (bod == BOD_OFF)
{
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
lowPowerBodOff(SLEEP_MODE_PWR_SAVE);
#else
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_SAVE);
#else
lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
}
}
} while (!wdtFinished);

if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);

Expand Down Expand Up @@ -1004,24 +1040,28 @@ void LowPowerClass::powerStandby(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);
}

if (bod == BOD_OFF)
{
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
lowPowerBodOff(SLEEP_MODE_STANDBY);
#else
do { // Do this at least once even if SLEEP_FOREVER
if (bod == BOD_OFF)
{
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
lowPowerBodOff(SLEEP_MODE_STANDBY);
#else
lowPowerBodOn(SLEEP_MODE_STANDBY);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_STANDBY);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_STANDBY);
}
}
} while (!wdtFinished);

if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
}
Expand Down Expand Up @@ -1083,28 +1123,31 @@ void LowPowerClass::powerExtStandby(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);
}


#if defined (__AVR_ATmega88__) || defined (__AVR_ATmega168__) // SLEEP_MODE_EXT_STANDBY not implemented on Atmega88 / Atmega168
#else
if (bod == BOD_OFF)
{
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
lowPowerBodOff(SLEEP_MODE_EXT_STANDBY);
#else
do { // Do this at least once even if SLEEP_FOREVER
#if defined (__AVR_ATmega88__) || defined (__AVR_ATmega168__) // SLEEP_MODE_EXT_STANDBY not implemented on Atmega88 / Atmega168
#else
if (bod == BOD_OFF)
{
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
lowPowerBodOff(SLEEP_MODE_EXT_STANDBY);
#else
lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
}
#endif
}
#endif
} while (!wdtFinished);

if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);

Expand All @@ -1128,6 +1171,7 @@ ISR (WDT_vect)
{
// WDIE & WDIF is cleared in hardware upon entering this ISR
wdt_disable();
wdtFinished = true;
}

#elif defined (__arm__)
Expand Down