diff options
-rw-r--r-- | chip/stm32/clock-stm32f0.c | 26 | ||||
-rw-r--r-- | chip/stm32/clock-stm32f4.c | 4 | ||||
-rw-r--r-- | chip/stm32/registers.h | 16 | ||||
-rw-r--r-- | chip/stm32/system.c | 32 | ||||
-rw-r--r-- | include/config.h | 3 |
5 files changed, 55 insertions, 26 deletions
diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c index b7eb68ca07..fe1ccd4aa4 100644 --- a/chip/stm32/clock-stm32f0.c +++ b/chip/stm32/clock-stm32f0.c @@ -59,26 +59,27 @@ static int dsleep_recovery_margin_us = 1000000; #endif /* CONFIG_LOW_POWER_IDLE */ /* - * RTC clock frequency (connected to LSI clock) + * RTC clock frequency (By default connected to LSI clock) * - * TODO(crosbug.com/p/12281): Calibrate LSI frequency on a per-chip basis. The - * LSI on any given chip can be between 30 kHz to 60 kHz. Without calibration, - * LSI frequency may be off by as much as 50%. Fortunately, we don't do any - * high-precision delays based solely on LSI. - */ -/* - * Set synchronous clock freq to LSI/2 (20kHz) to maximize subsecond - * resolution. Set asynchronous clock to 1 Hz. + * The LSI on any given chip can be between 30 kHz to 60 kHz. + * Without calibration, LSI frequency may be off by as much as 50%. + * + * Set synchronous clock freq to (RTC clock source / 2) to maximize + * subsecond resolution. Set asynchronous clock to 1 Hz. */ -#define RTC_FREQ (40000 / 2) /* Hz */ + +#ifdef CONFIG_STM32_CLOCK_LSE +#define RTC_FREQ (32768 / (RTC_PREDIV_A + 1)) /* Hz */ +#else /* LSI clock, 40kHz-ish */ +#define RTC_FREQ (40000 / (RTC_PREDIV_A + 1)) /* Hz */ +#endif #define RTC_PREDIV_S (RTC_FREQ - 1) #define RTC_PREDIV_A 1 #define US_PER_RTC_TICK (1000000 / RTC_FREQ) - int32_t rtcss_to_us(uint32_t rtcss) { - return ((RTC_PREDIV_S - rtcss) * US_PER_RTC_TICK); + return ((RTC_PREDIV_S - (rtcss & 0x7fff)) * US_PER_RTC_TICK); } uint32_t us_to_rtcss(int32_t us) @@ -86,7 +87,6 @@ uint32_t us_to_rtcss(int32_t us) return (RTC_PREDIV_S - (us / US_PER_RTC_TICK)); } - void config_hispeed_clock(void) { #ifdef CHIP_FAMILY_STM32F3 diff --git a/chip/stm32/clock-stm32f4.c b/chip/stm32/clock-stm32f4.c index eacb3d59e0..ed4ffe6848 100644 --- a/chip/stm32/clock-stm32f4.c +++ b/chip/stm32/clock-stm32f4.c @@ -166,13 +166,13 @@ void config_hispeed_clock(void) /* Setup RTC Clock input */ STM32_RCC_BDCR |= STM32_RCC_BDCR_BDRST; #ifdef CONFIG_STM32_CLOCK_HSE_HZ - STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BCDR_RTCSEL(BDCR_SRC_HSE); + STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_HSE); #else /* Ensure that LSI is ON */ wait_for_ready(&(STM32_RCC_CSR), STM32_RCC_CSR_LSION, STM32_RCC_CSR_LSIRDY); - STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BCDR_RTCSEL(BDCR_SRC_LSI); + STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_LSI); #endif } diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index bfe5b7321c..491718f631 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -1109,11 +1109,6 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x64) #define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x70) -#define STM32_RCC_BDCR_BDRST (1 << 16) -#define STM32_RCC_BDCR_RTCEN (1 << 15) -#define BCDR_RTCSEL(source) (((source) & 0x3) << 8) -#define BDCR_SRC_HSE 0x3 -#define BDCR_SRC_LSI 0x2 #define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x74) #define STM32_RCC_CSR_LSION (1 << 0) #define STM32_RCC_CSR_LSIRDY (1 << 1) @@ -1141,6 +1136,17 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #error Unsupported chip variant #endif +/* RTC domain control register */ +#define STM32_RCC_BDCR_BDRST (1 << 16) +#define STM32_RCC_BDCR_RTCEN (1 << 15) +#define STM32_RCC_BDCR_LSERDY (1 << 1) +#define STM32_RCC_BDCR_LSEON (1 << 0) +#define BDCR_RTCSEL_MASK ((0x3) << 8) +#define BDCR_RTCSEL(source) (((source) << 8) & BDCR_RTCSEL_MASK) +#define BDCR_SRC_LSE 0x1 +#define BDCR_SRC_LSI 0x2 +#define BDCR_SRC_HSE 0x3 + /* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ #define STM32_RCC_PB1_TIM2 (1 << 0) #define STM32_RCC_PB1_TIM3 (1 << 1) diff --git a/chip/stm32/system.c b/chip/stm32/system.c index d0c69101ef..884a5d9ed2 100644 --- a/chip/stm32/system.c +++ b/chip/stm32/system.c @@ -18,6 +18,18 @@ #include "version.h" #include "watchdog.h" +#ifdef CONFIG_STM32_CLOCK_LSE +#define BDCR_SRC BDCR_SRC_LSE +#define BDCR_RDY STM32_RCC_BDCR_LSERDY +#else +#define BDCR_SRC BDCR_SRC_LSI +#define BDCR_RDY 0 +#endif +#define BDCR_ENABLE_VALUE (STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC) | \ + BDCR_RDY) +#define BDCR_ENABLE_MASK (BDCR_ENABLE_VALUE | BDCR_RTCSEL_MASK | \ + STM32_RCC_BDCR_BDRST) + enum bkpdata_index { BKPDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */ BKPDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */ @@ -249,18 +261,26 @@ void system_pre_init(void) /* re-configure RTC if needed */ #ifdef CHIP_FAMILY_STM32L if ((STM32_RCC_CSR & 0x00C30000) != 0x00420000) { - /* the RTC settings are bad, we need to reset it */ + /* The RTC settings are bad, we need to reset it */ STM32_RCC_CSR |= 0x00800000; /* Enable RTC and use LSI as clock source */ STM32_RCC_CSR = (STM32_RCC_CSR & ~0x00C30000) | 0x00420000; } #elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \ defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32F4) - if ((STM32_RCC_BDCR & 0x00018300) != 0x00008200) { - /* the RTC settings are bad, we need to reset it */ - STM32_RCC_BDCR |= 0x00010000; - /* Enable RTC and use LSI as clock source */ - STM32_RCC_BDCR = (STM32_RCC_BDCR & ~0x00018300) | 0x00008200; + if ((STM32_RCC_BDCR & BDCR_ENABLE_MASK) != BDCR_ENABLE_VALUE) { + /* The RTC settings are bad, we need to reset it */ + STM32_RCC_BDCR |= STM32_RCC_BDCR_BDRST; + STM32_RCC_BDCR = STM32_RCC_BDCR & ~BDCR_ENABLE_MASK; +#ifdef CONFIG_STM32_CLOCK_LSE + /* Turn on LSE */ + STM32_RCC_BDCR |= STM32_RCC_BDCR_LSEON; + /* Wait for LSE to be ready */ + while (!(STM32_RCC_BDCR & STM32_RCC_BDCR_LSERDY)) + ; +#endif + /* Select clock source and enable RTC */ + STM32_RCC_BDCR |= BDCR_RTCSEL(BDCR_SRC) | STM32_RCC_BDCR_RTCEN; } #else #error "Unsupported chip family" diff --git a/include/config.h b/include/config.h index 86dacbe74f..f60766d165 100644 --- a/include/config.h +++ b/include/config.h @@ -668,6 +668,9 @@ /* Indicate if a clock source is connected to stm32f4's "HSE" specific input */ #undef CONFIG_STM32_CLOCK_HSE_HZ +/* Indicate if a clock source is connected to "LSE" specific input */ +#undef CONFIG_STM32_CLOCK_LSE + /* * Chip config for clock source * define = external crystal oscillator / undef = internal clock source |