stm32/powerctrlboot: Fix clock and PLL selection for HSI48 on F0 MCUs.

Before this patch the UART baudrate on F0 MCUs was wrong because the
stm32lib SystemCoreClockUpdate sets SystemCoreClock to 8MHz instead of
48MHz if HSI48 is routed directly to SYSCLK.

The workaround is to use HSI48 -> PREDIV (/2) -> PLL (*2) -> SYSCLK.

Fixes issue #5049.
This commit is contained in:
Chris Mason 2019-09-21 18:20:12 +10:00 committed by Damien George
parent 3328b7d71f
commit f16e4be3fa

View File

@ -38,11 +38,15 @@ void SystemClock_Config(void) {
#if MICROPY_HW_CLK_USE_HSI48 #if MICROPY_HW_CLK_USE_HSI48
// Use the 48MHz internal oscillator // Use the 48MHz internal oscillator
// HAL does not support RCC CFGR SW=3 (HSI48 direct to SYSCLK)
// so use HSI48 -> PREDIV(divide by 2) -> PLL (mult by 2) -> SYSCLK.
RCC->CR2 |= RCC_CR2_HSI48ON; RCC->CR2 |= RCC_CR2_HSI48ON;
while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) { while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) {
// Wait for HSI48 to be ready
} }
const uint32_t sysclk_src = 3; RCC->CFGR = 0 << RCC_CFGR_PLLMUL_Pos | 3 << RCC_CFGR_PLLSRC_Pos; // PLL mult by 2, src = HSI48/PREDIV
RCC->CFGR2 = 1; // Input clock divided by 2
#else #else
// Use HSE and the PLL to get a 48MHz SYSCLK // Use HSE and the PLL to get a 48MHz SYSCLK
@ -56,14 +60,15 @@ void SystemClock_Config(void) {
} }
RCC->CFGR = ((48000000 / HSE_VALUE) - 2) << RCC_CFGR_PLLMUL_Pos | 2 << RCC_CFGR_PLLSRC_Pos; RCC->CFGR = ((48000000 / HSE_VALUE) - 2) << RCC_CFGR_PLLMUL_Pos | 2 << RCC_CFGR_PLLSRC_Pos;
RCC->CFGR2 = 0; // Input clock not divided RCC->CFGR2 = 0; // Input clock not divided
#endif
RCC->CR |= RCC_CR_PLLON; // Turn PLL on RCC->CR |= RCC_CR_PLLON; // Turn PLL on
while ((RCC->CR & RCC_CR_PLLRDY) == 0) { while ((RCC->CR & RCC_CR_PLLRDY) == 0) {
// Wait for PLL to lock // Wait for PLL to lock
} }
const uint32_t sysclk_src = 2; const uint32_t sysclk_src = 2;
#endif
// Select SYSCLK source // Select SYSCLK source
RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos;
while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) {