From 91673d8e72b8c5348012be64fd4f97c14d36909c Mon Sep 17 00:00:00 2001 From: Guillaume Meunier Date: Sat, 17 Aug 2019 18:56:01 +0200 Subject: [PATCH] cpu/stm32_common/periph/rtc: fix issue #8746 --- cpu/stm32_common/periph/rtc.c | 45 ++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/cpu/stm32_common/periph/rtc.c b/cpu/stm32_common/periph/rtc.c index 78c8fe546ea73..dfdc6f586d3de 100644 --- a/cpu/stm32_common/periph/rtc.c +++ b/cpu/stm32_common/periph/rtc.c @@ -181,16 +181,25 @@ static inline void rtc_unlock(void) /* unlock RTC */ RTC->WPR = WPK1; RTC->WPR = WPK2; +} + +static inline void rtc_enter_init_mode(void) +{ /* enter RTC init mode */ RTC->ISR |= RTC_ISR_INIT; while (!(RTC->ISR & RTC_ISR_INITF)) {} } -static inline void rtc_lock(void) +static inline void rtc_exit_init_mode(void) { /* exit RTC init mode */ RTC->ISR &= ~RTC_ISR_INIT; while (RTC->ISR & RTC_ISR_INITF) {} +} + + +static inline void rtc_lock(void) +{ /* lock RTC device */ RTC->WPR = 0xff; /* disable backup clock domain */ @@ -212,25 +221,28 @@ void rtc_init(void) #endif stmclk_dbp_lock(); - /* enable low frequency clock */ - stmclk_enable_lfclk(); + if (!(RTC->ISR & RTC_ISR_INITS)) + { + /* enable low frequency clock */ + stmclk_enable_lfclk(); - /* select input clock and enable the RTC */ - stmclk_dbp_unlock(); - EN_REG &= ~(CLKSEL_MASK); + /* select input clock and enable the RTC */ + stmclk_dbp_unlock(); + EN_REG &= ~(CLKSEL_MASK); #if CLOCK_LSE - EN_REG |= (CLKSEL_LSE | EN_BIT); + EN_REG |= (CLKSEL_LSE | EN_BIT); #else - EN_REG |= (CLKSEL_LSI | EN_BIT); + EN_REG |= (CLKSEL_LSI | EN_BIT); #endif - rtc_unlock(); - /* reset configuration */ - RTC->CR = 0; - RTC->ISR = RTC_ISR_INIT; - /* configure prescaler (RTC PRER) */ - RTC->PRER = (PRE_SYNC | (PRE_ASYNC << 16)); - rtc_lock(); + rtc_unlock(); + /* reset configuration */ + RTC->CR = 0; + RTC->ISR = RTC_ISR_INIT; + /* configure prescaler (RTC PRER) */ + RTC->PRER = (PRE_SYNC | (PRE_ASYNC << 16)); + rtc_lock(); + } /* configure the EXTI channel, as RTC interrupts are routed through it. * Needs to be configured to trigger on rising edges. */ @@ -248,13 +260,14 @@ int rtc_set_time(struct tm *time) rtc_tm_normalize(time); rtc_unlock(); - + rtc_enter_init_mode(); RTC->DR = (val2bcd((time->tm_year % 100), RTC_DR_YU_Pos, DR_Y_MASK) | val2bcd(time->tm_mon + 1, RTC_DR_MU_Pos, DR_M_MASK) | val2bcd(time->tm_mday, RTC_DR_DU_Pos, DR_D_MASK)); RTC->TR = (val2bcd(time->tm_hour, RTC_TR_HU_Pos, TR_H_MASK) | val2bcd(time->tm_min, RTC_TR_MNU_Pos, TR_M_MASK) | val2bcd(time->tm_sec, RTC_TR_SU_Pos, TR_S_MASK)); + rtc_exit_init_mode(); rtc_lock(); while (!(RTC->ISR & RTC_ISR_RSF)) {}