stm32/rtc: Validate the RTC prescaler on boot and change if incorrect.
Devices with RTC backup-batteries have been shown (very rarely) to have incorrect RTC prescaler values. Such incorrect values mean the RTC counts fast or slow, and will be wrong forever if the power/backup-battery is always present. This commit detects such a state at start up (hard reset) and corrects it by reconfiguring the RTC prescaler values. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
a0623a081c
commit
cc2a35b7b2
|
@ -48,6 +48,7 @@
|
||||||
#include "stm32f0xx_hal_usart.h"
|
#include "stm32f0xx_hal_usart.h"
|
||||||
#include "stm32f0xx_hal_wwdg.h"
|
#include "stm32f0xx_hal_wwdg.h"
|
||||||
#include "stm32f0xx_ll_adc.h"
|
#include "stm32f0xx_ll_adc.h"
|
||||||
|
#include "stm32f0xx_ll_rtc.h"
|
||||||
|
|
||||||
// Enable various HAL modules
|
// Enable various HAL modules
|
||||||
#define HAL_MODULE_ENABLED
|
#define HAL_MODULE_ENABLED
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "stm32f4xx_hal_uart.h"
|
#include "stm32f4xx_hal_uart.h"
|
||||||
#include "stm32f4xx_hal_usart.h"
|
#include "stm32f4xx_hal_usart.h"
|
||||||
#include "stm32f4xx_hal_wwdg.h"
|
#include "stm32f4xx_hal_wwdg.h"
|
||||||
|
#include "stm32f4xx_ll_rtc.h"
|
||||||
|
|
||||||
// Enable various HAL modules
|
// Enable various HAL modules
|
||||||
#define HAL_ADC_MODULE_ENABLED
|
#define HAL_ADC_MODULE_ENABLED
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "stm32f7xx_hal_uart.h"
|
#include "stm32f7xx_hal_uart.h"
|
||||||
#include "stm32f7xx_hal_usart.h"
|
#include "stm32f7xx_hal_usart.h"
|
||||||
#include "stm32f7xx_hal_wwdg.h"
|
#include "stm32f7xx_hal_wwdg.h"
|
||||||
|
#include "stm32f7xx_ll_rtc.h"
|
||||||
|
|
||||||
// Enable various HAL modules
|
// Enable various HAL modules
|
||||||
#define HAL_ADC_MODULE_ENABLED
|
#define HAL_ADC_MODULE_ENABLED
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "stm32h7xx_hal_usart.h"
|
#include "stm32h7xx_hal_usart.h"
|
||||||
#include "stm32h7xx_hal_wwdg.h"
|
#include "stm32h7xx_hal_wwdg.h"
|
||||||
#include "stm32h7xx_ll_adc.h"
|
#include "stm32h7xx_ll_adc.h"
|
||||||
|
#include "stm32h7xx_ll_rtc.h"
|
||||||
|
|
||||||
// Enable various HAL modules
|
// Enable various HAL modules
|
||||||
#define HAL_ADC_MODULE_ENABLED
|
#define HAL_ADC_MODULE_ENABLED
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "stm32l0xx_hal_usart.h"
|
#include "stm32l0xx_hal_usart.h"
|
||||||
#include "stm32l0xx_hal_wwdg.h"
|
#include "stm32l0xx_hal_wwdg.h"
|
||||||
#include "stm32l0xx_ll_adc.h"
|
#include "stm32l0xx_ll_adc.h"
|
||||||
|
#include "stm32l0xx_ll_rtc.h"
|
||||||
|
|
||||||
// Enable various HAL modules
|
// Enable various HAL modules
|
||||||
#define HAL_MODULE_ENABLED
|
#define HAL_MODULE_ENABLED
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "stm32l4xx_hal_usart.h"
|
#include "stm32l4xx_hal_usart.h"
|
||||||
#include "stm32l4xx_hal_wwdg.h"
|
#include "stm32l4xx_hal_wwdg.h"
|
||||||
#include "stm32l4xx_ll_adc.h"
|
#include "stm32l4xx_ll_adc.h"
|
||||||
|
#include "stm32l4xx_ll_rtc.h"
|
||||||
|
|
||||||
// Enable various HAL modules
|
// Enable various HAL modules
|
||||||
#define HAL_MODULE_ENABLED
|
#define HAL_MODULE_ENABLED
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "stm32wbxx_hal_uart.h"
|
#include "stm32wbxx_hal_uart.h"
|
||||||
#include "stm32wbxx_hal_usart.h"
|
#include "stm32wbxx_hal_usart.h"
|
||||||
#include "stm32wbxx_ll_adc.h"
|
#include "stm32wbxx_ll_adc.h"
|
||||||
|
#include "stm32wbxx_ll_rtc.h"
|
||||||
|
|
||||||
// Enable various HAL modules
|
// Enable various HAL modules
|
||||||
#define HAL_MODULE_ENABLED
|
#define HAL_MODULE_ENABLED
|
||||||
|
|
|
@ -114,20 +114,22 @@ void rtc_init_start(bool force_init) {
|
||||||
rtc_need_init_finalise = false;
|
rtc_need_init_finalise = false;
|
||||||
|
|
||||||
if (!force_init) {
|
if (!force_init) {
|
||||||
|
bool rtc_running = false;
|
||||||
uint32_t bdcr = RCC->BDCR;
|
uint32_t bdcr = RCC->BDCR;
|
||||||
if ((bdcr & (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL | RCC_BDCR_LSEON | RCC_BDCR_LSERDY))
|
if ((bdcr & (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL | RCC_BDCR_LSEON | RCC_BDCR_LSERDY))
|
||||||
== (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_0 | RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) {
|
== (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_0 | RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) {
|
||||||
// LSE is enabled & ready --> no need to (re-)init RTC
|
// LSE is enabled & ready --> no need to (re-)init RTC
|
||||||
|
rtc_running = true;
|
||||||
// remove Backup Domain write protection
|
// remove Backup Domain write protection
|
||||||
HAL_PWR_EnableBkUpAccess();
|
HAL_PWR_EnableBkUpAccess();
|
||||||
// Clear source Reset Flag
|
// Clear source Reset Flag
|
||||||
__HAL_RCC_CLEAR_RESET_FLAGS();
|
__HAL_RCC_CLEAR_RESET_FLAGS();
|
||||||
// provide some status information
|
// provide some status information
|
||||||
rtc_info |= 0x40000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8;
|
rtc_info |= 0x40000;
|
||||||
return;
|
|
||||||
} else if ((bdcr & (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL))
|
} else if ((bdcr & (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL))
|
||||||
== (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_1)) {
|
== (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_1)) {
|
||||||
// LSI configured as the RTC clock source --> no need to (re-)init RTC
|
// LSI configured as the RTC clock source --> no need to (re-)init RTC
|
||||||
|
rtc_running = true;
|
||||||
// remove Backup Domain write protection
|
// remove Backup Domain write protection
|
||||||
HAL_PWR_EnableBkUpAccess();
|
HAL_PWR_EnableBkUpAccess();
|
||||||
// Clear source Reset Flag
|
// Clear source Reset Flag
|
||||||
|
@ -135,7 +137,39 @@ void rtc_init_start(bool force_init) {
|
||||||
// Turn the LSI on (it may need this even if the RTC is running)
|
// Turn the LSI on (it may need this even if the RTC is running)
|
||||||
RCC->CSR |= RCC_CSR_LSION;
|
RCC->CSR |= RCC_CSR_LSION;
|
||||||
// provide some status information
|
// provide some status information
|
||||||
rtc_info |= 0x80000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8;
|
rtc_info |= 0x80000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtc_running) {
|
||||||
|
// Provide information about the registers that indicated the RTC is running.
|
||||||
|
rtc_info |= (RCC->BDCR & 7) | (RCC->CSR & 3) << 8;
|
||||||
|
|
||||||
|
// Check that the sync and async prescaler values are correct. If the RTC
|
||||||
|
// gets into a state where they are wrong then it will run slow or fast and
|
||||||
|
// never be corrected. In such a situation, attempt to reconfigure the values
|
||||||
|
// without changing the data/time.
|
||||||
|
if (LL_RTC_GetSynchPrescaler(RTC) != RTC_SYNCH_PREDIV
|
||||||
|
|| LL_RTC_GetAsynchPrescaler(RTC) != RTC_ASYNCH_PREDIV) {
|
||||||
|
// Values are wrong, attempt to enter RTC init mode and change them.
|
||||||
|
LL_RTC_DisableWriteProtection(RTC);
|
||||||
|
LL_RTC_EnableInitMode(RTC);
|
||||||
|
uint32_t ticks_ms = HAL_GetTick();
|
||||||
|
while (HAL_GetTick() - ticks_ms < RTC_TIMEOUT_VALUE) {
|
||||||
|
if (LL_RTC_IsActiveFlag_INIT(RTC)) {
|
||||||
|
// Reconfigure the RTC prescaler register PRER.
|
||||||
|
LL_RTC_SetSynchPrescaler(RTC, RTC_SYNCH_PREDIV);
|
||||||
|
LL_RTC_SetAsynchPrescaler(RTC, RTC_ASYNCH_PREDIV);
|
||||||
|
LL_RTC_DisableInitMode(RTC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LL_RTC_EnableWriteProtection(RTC);
|
||||||
|
|
||||||
|
// Provide information that the prescaler was changed.
|
||||||
|
rtc_info |= 0x100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The RTC is up and running, so return without any further configuration.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue