1
\$\begingroup\$

On an STM32L0C8 MCU, I have the watchdog enabled while executing. At certain points in execution, I would like the chip to go into low power sleep mode. When it goes into low-power sleep mode though, the watchdog timer remains activated and will reset the entire MCU after the timer goes to 0, making it seemingly impossible to use both the watchdog and low-power sleep mode at the same time.

My question is, how do I refresh the countdown timer while in low-power sleep mode or how do I disable the WDT to stop it from resetting the MCU?

I looked all around the reference manual linked below to figure out how to disable / refresh the timer but it seems like this isn't possible. On page 514 it says:

20.3.4 Behavior in Stop and Standby modes Once running, the IWDG cannot be stopped

(IWDG being the Independent Watchdog) but it doesn't say anything about low-power sleep mode. In multiple other areas it suggests the same thing, that the IWDG can't be stopped. Am I missing something? Are we not supposed to use the watchdog if we want to go into sleep mode? Is it possible to modify the watchdog countdown timers code to stop decrementing before entering sleep mode? Please let me know!

Reference Manual: http://www.st.com/content/ccc/resource/technical/document/reference_manual/21/bd/0f/bd/1c/88/40/f0/DM00108282.pdf/files/DM00108282.pdf/jcr:content/translations/en.DM00108282.pdf

\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

The watchdog is only stopped on system reset. This way you can't accidentally turn it off.

If you want to use sleep modes and watchdog, you will have to set the watchdog the slowest clock, and wake-up regularly to restart the watchdog.

This is valid for almost all microcontrollers on the market that have an independently clocked watchdog.

\$\endgroup\$
3
  • \$\begingroup\$ Wouldn't it kind of defeat the purpose to wake up regularly for restarting the countdown timer? In other words, wouldn't the power consumption caused by waking up and sleeping constantly more or less be the same as power consumption in normal running mode? \$\endgroup\$
    – Omnomnious
    May 26, 2017 at 17:27
  • 2
    \$\begingroup\$ @Omnomnious: No, of course not. It only takes a few tens of microseconds to wake up and kick the watchdog. The rest of the time, you are sleeping and saving power. If you really care about that last little trickle of power, then you shouldn't enable the watchdog in the first place. Make sure your application code is robust enough not to need it. \$\endgroup\$
    – Dave Tweed
    May 26, 2017 at 17:32
  • 1
    \$\begingroup\$ @Omnomnious Think about it from the purpose of the watchdog timer. To revive the processor if it crashes. So if it expires something has gone wrong. \$\endgroup\$ May 26, 2017 at 18:36
2
\$\begingroup\$

I know I'm a bit late with my answer but still.

1) On some MCU's (like L4-series) from ST you can actually stop Watchdog Timers in STOP or STANDBY mode - here, for example it's said it can by done by writing to FLASH_OPTR register.
That just means that ST acknowledges that you don't actually need Watchdog in stop mode :)

2) You can cheat and instead of going straight to the STOP or STANDBY mode, write a magic value to the flash or EEPROM and do software reset (NVIC_Reset()).
After reset, look for the magic value, erase it if it's present, don't start the watchdog and go to STOP or STANDBY.
If no magic value is present - proceed as you normally would.

I just checked it on my STM32L151 and it seems to work.

\$\endgroup\$
4
  • \$\begingroup\$ There's no need to use flash or eeprom for the reset-to-clear idea, you can use the RTC mailbox registers or put a word in high RAM and protect it from the memory region in the linker map given to the C startup code to clear, or check it before that startup code gets at it. \$\endgroup\$ Dec 15, 2018 at 17:26
  • \$\begingroup\$ Well, it was the first that came to my mind; i wasn't sure what else can survive software reset. Thanks for idea :) \$\endgroup\$
    – Amomum
    Dec 15, 2018 at 21:21
  • \$\begingroup\$ @ChrisStratton I just checked, RTC Backup Registers also seem to work. Dunno if you meant them when wrote about 'mailbox' registers. \$\endgroup\$
    – Amomum
    Dec 16, 2018 at 17:48
  • \$\begingroup\$ The SRAM is powered down during standby. The RTC backup registers can be used for this. \$\endgroup\$
    – Rodney
    May 11, 2021 at 12:43
1
\$\begingroup\$

As already said, the IWDG cannot be stopped and must be refreshed while in sleep mode.

An alternative is using the WWDG which (at least for the STM32F105) uses the PCLK1 clock which is stopped during stop-mode, so no need to refresh (at least that is the case for the STM32F105)

If you want to use sleep mode it might not be suitable solution for you but consider stop mode is not as hard to exit from using the EXTI

For example, on the STM32F105, you can wakeup stop mode on a canbus event. use set_exti_for_can_wakeup() before going to sleep and set_exti_back() after it, to wakeup from CAN2.

void set_exti_for_can_wakeup(void)
{
    // Map PB12 to EXTI12
    AFIO->EXTICR[3] &= ~AFIO_EXTICR4_EXTI12_Msk;
    AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI12_PB_Msk;

    // Configure EXTI12 to generate an interrupt on rising edge
    EXTI->IMR |= EXTI_IMR_MR12;
    EXTI->RTSR |= EXTI_RTSR_TR12;

    //Clear the flag bit to avoid wake-up if already set
    EXTI->PR |= EXTI_PR_PR12_Msk;
}

void set_exti_back(void)
{
    EXTI->PR |= EXTI_PR_PR12_Msk;
}

set WWDG window value and downcounter value to max to disable the window limit

One downside is WWDG short max countdown which is mostly between 50-500ms depending on the PCLK1 frequency (e.g. 18MHZ). If more time is needed, consider using the early wakeup interrupt for the refresh and use a software prescaler to control the actual timeout

here is an example for such a software prescaler. ps: note the early wake-up is fired at half the max countdown, so double the prescaler from its real max value

use the wdt_clear() instead of HAL_WWDG_Refresh() in your application

#define WDT_PRESCALER 100
static volatile uint32_t f_counter = WDT_PRESCALER;

void wdt_clear(void)
{
    f_counter = WDT_PRESCALER;
}

void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
    if (f_counter != 0) {
        f_counter--;
        HAL_WWDG_Refresh(hwwdg);
    }
} 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.