RTC fixup for STM32F7
Switch RTC to LSE clock if it is detected on start. It is not allowed to change source clock of RTC module on STM32. Source clock can be selected only once after reset of BKP module. If at first start LSE is failed FW will fallback to inaccurate LSI (internal RC). If Vbat is present RTC/BKP is not reset between restarts and RTC is never switched to more accurate LSE event if it is present. Implement fixup that will check for the LSE and switch RTC to LSE through BKP (RTC) module reset and new clock source selection.
This commit is contained in:
parent
c6b832a0bc
commit
d264f002cd
|
@ -5,6 +5,7 @@ HW_LAYER_PORT += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/stm32f7xx_hal_flash
|
|||
|
||||
HW_LAYER_PORT_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/mpu_util.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32_adc_v2.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/stm32f7xx_rtc.cpp \
|
||||
|
||||
# This MCU has a cache, align functions to a cache line for maximum cache efficiency
|
||||
USE_OPT += -falign-functions=16
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* @file stm32f7xx_rtc.cpp
|
||||
* @brief Real Time Clock STM32F7xx switched from LSE to LSI
|
||||
*
|
||||
* @date Jan 8, 2025
|
||||
* @author Andrey Gusakov
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#if HAL_USE_RTC
|
||||
|
||||
/* switch to LSE clock if ECU previously falledback to LSI clock.
|
||||
* This will preserve current time and set it back to RTC after reinit
|
||||
* On STM32 change of RTC source clock can be done only through reset of whole backup domain
|
||||
* This reset does no affect backup ram */
|
||||
void hal_lld_rtc_fixup(void)
|
||||
{
|
||||
#if (STM32_RTCSEL == STM32_RTCSEL_LSE)
|
||||
// we need some more time than defined in RUSEFI_STM32_LSE_WAIT_MAX
|
||||
// this is safe as we check that LSE is runnig before reseting BKP domain (stopping LSE)
|
||||
// After that we are starting LSE again and waiting for LSERDY.
|
||||
int timeout = 1000000000;
|
||||
if ((RCC->BDCR & STM32_RTCSEL_MASK) == STM32_RTCSEL) {
|
||||
// Backup domain is already driven by expected clock
|
||||
return;
|
||||
}
|
||||
if ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) {
|
||||
// LSE is failed to start
|
||||
efiPrintf("LSE in not ready");
|
||||
return;
|
||||
}
|
||||
|
||||
efiPrintf("Switching RTC to LSE clock");
|
||||
|
||||
// Get current time
|
||||
RTCDateTime timespec;
|
||||
rtcGetTime(&RTCD1, ×pec);
|
||||
|
||||
// Reset BKP domain
|
||||
// The BKPSRAM is not affected by this reset
|
||||
// This will also reset LSEON
|
||||
RCC->BDCR |= RCC_BDCR_BDRST;
|
||||
RCC->BDCR &= ~RCC_BDCR_BDRST;
|
||||
|
||||
#if defined(STM32_LSE_BYPASS)
|
||||
// LSE Bypass.
|
||||
RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP;
|
||||
#else
|
||||
// No LSE Bypass.
|
||||
RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON;
|
||||
#endif
|
||||
// Waits until LSE is stable or times out.
|
||||
while (((RCC->BDCR & RCC_BDCR_LSERDY) == 0) && (timeout--)) {
|
||||
//this is executed when RTOS is not ready
|
||||
//chThdSleepMilliseconds(1);
|
||||
}
|
||||
|
||||
// Lets check again
|
||||
if (RCC->BDCR & RCC_BDCR_LSERDY) {
|
||||
RCC->BDCR |= STM32_RTCSEL;
|
||||
} else {
|
||||
// LSE is failed to start
|
||||
efiPrintf("LSE in not ready after restart attemp");
|
||||
// Keep initing
|
||||
RCC->BDCR |= RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL;
|
||||
}
|
||||
|
||||
/* RTC clock enabled.*/
|
||||
RCC->BDCR |= RCC_BDCR_RTCEN;
|
||||
|
||||
// init RTC again
|
||||
rtcInit();
|
||||
// Set previously saved time
|
||||
rtcSetTime(&RTCD1, ×pec);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //HAL_USE_RTC
|
|
@ -27,8 +27,14 @@ extern "C" int _gettimeofday(timeval* tv, void* tzvp) {
|
|||
#endif // EFI_PROD_CODE
|
||||
|
||||
#if EFI_RTC
|
||||
|
||||
void PUBLIC_API_WEAK hal_lld_rtc_fixup(void) {
|
||||
/* nop */
|
||||
}
|
||||
|
||||
void initRtc() {
|
||||
efiPrintf("initRtc()");
|
||||
hal_lld_rtc_fixup();
|
||||
printDateTime(); // this would test RTC, see #311
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue