2021-03-11 07:31 PM
I am using an RTC to wake up my MCU from shutdown mode. RTC is configured to use LSI clock, which runs during shutdown.
When I run my code from a debugger, it works fine. Goes to sleep, wakes up from shutdown when the RTC pings it awake. I can see the power usage on a power monitor. If I reset the MCU using the reset pin, the behavior is still as expected. (RTC wakeup working)
However, when I restart the MCU by removing power, it goes to sleep and never wakes up. Using the reset pin wakes it back up of course, but the RTC still does not wake it up. I can only assume that this is because the RTC is not getting initialized correctly, but I don't know what the difference is between when its started with a debugger and when it isn't.
LSI Init Code:
SET_BIT(RCC->CSR, RCC_CSR_LSION); //Enable the 32 kHz low speed internal (LSI) oscillator.
while(!READ_BIT(RCC->CSR, RCC_CSR_LSIRDY)) //Wait for the LSI oscillator to be ready.
{
asm("NOP");
}
This is the RTC clock setup code:
SET_BIT(PWR->CR1, PWR_CR1_DBP);
if ((uint32_t)(READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) != RCC_BDCR_RTCSEL_1) {
SET_BIT(RCC->BDCR, RCC_BDCR_BDRST); // reset the backup domain
CLEAR_BIT(RCC->BDCR, RCC_BDCR_BDRST);
MODIFY_REG(RCC->BDCR, RCC_BDCR_RTCSEL, RCC_BDCR_RTCSEL_1); // use LSI clock
}
SET_BIT(RCC->BDCR, RCC_BDCR_RTCEN); // enable RTC
And setup for RTC wakeup:
/* RTC interrupt Init */
NVIC_SetPriority(RTC_WKUP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(RTC_WKUP_IRQn);
WRITE_REG(RTC->WPR, RTC_WRITE_PROTECTION_ENABLE_1); // disable write protection for RTC registers
WRITE_REG(RTC->WPR, RTC_WRITE_PROTECTION_ENABLE_2);
// select wakeup alarm, enable wakeup interrupt, enable wakeup alarm, and select the slow 1 hz clock
SET_BIT(RTC->CR, RTC_CR_OSEL_1);
SET_BIT(RTC->CR, RTC_CR_WUTIE); //wakeup time interrupt enable
CLEAR_BIT(RTC->CR, RTC_CR_WUTE); //wakeup timer disable
while((RTC->ISR & RTC_ISR_WUTWF) == 0) {
asm("nop"); // wait until WUCKSEL write allowed
}
RTC->ISR &= ~RTC_ISR_WUTF; // clear wakeup flag
SET_BIT(RTC->CR, RTC_CR_WUCKSEL_2); // select 1 hz clock for wakeup clock
WRITE_REG(RTC->WUTR, PWR_WAKEUP_TIMER);
SET_BIT(RTC->CR, RTC_CR_WUTE); //wakeup timer enable