I'm tuning stm32l100
for a STANDBY mode. The MCU should woke up 2 times per second. For this I use RTC wakeup timer. But after how MCU has entered to the STANDBY mode it immediately wakes up.
If instead the STANDBY mode I use a simple sleep-mode (__WFI) all works fine.
My code is here
After the MCU is starting
a. saves flags CSR_SBF and CSR_WUF, after that clears them.
if (PWR->CSR & PWR_CSR_SBF_BIT) {
// ...
}
if (PWR->CSR & PWR_CSR_WUF_BIT) {
// ...
}
PWR->CR |= PWR_CR_CSBF_BIT|PWR_CR_CWUF_BIT;
//while (PWR->CSR & PWR_CSR_SBF_BIT);
while (PWR->CSR & PWR_CSR_WUF_BIT);
I noted that CSR_SBF never clears. If I uncomment string with while
then MCU stall on it place. I don't understand why.
b. saves reset source flags, after that clears them.
volatile uint32_t csr;
csr = RCC->CSR;
// .... saving
// clear flags
RCC->CSR |= RCC_CSR_RMVF_BIT;
After how MCU woke up from the STANDBY all reset source flags are cleared. It seems how reset sources are absent but code execute from 0x0.
Tuning RTC wakeup-timer
void rtc_set_wakeup_mode(const uint32_t wakeup_counter)
{
RTC_WRITE_PROTECT_DISABLE();
RTC->CR &= ~RTC_CR_WUTE_BIT;
while (!(RTC->ISR & RTC_ISR_WUTWF_BIT));
RTC->WUTR = wakeup_counter;
RTC->CR &= 0xfffffff7;
RTC->CR |= RTC_WAKEUPCLOCK_RTCCLK_DIV2;
__HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
__HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();
RTC->CR |= RTC_CR_WUTIE_BIT|RTC_CR_WUTE_BIT;
RTC_WRITE_PROTECT_ENABLE();
}
Enter in the STANDBY mode
void pwdm_enter_standby_mode(void)
{
PWR->CR |= PWR_CR_PDDS_BIT;
SCB->SCR |= SCB_SCR_SLEEPDEEP_BIT;
__WFI();
}
So, finally I got it.
It was my own fail with startup initialization. The key was in this:
I noted that CSR_SBF never clears. If I uncomment string with while then MCU stall on it place. I don't understand why.
I placed the code working with wakeup/standby flags at the begining of main
. But this code didn't do this operation __HAL_RCC_PWR_CLK_ENABLE();
because that operation will executed in a oscill initialization routine. So, the PWR->CSR
was in undefined state and the PWR_CSR_WUF
flag is never clearing.