Магические числа... Фи! Не читаемо, трудносопровождаемо, трудноотлаживаемо. // Enable HSE, disable PLL
RCC->CR = 0
| RCC_CR_HSEON
| RCC_CR_HSEBYP
;
// Wait until HSE ready
while (!(RCC->CR & RCC_CR_HSERDY))
;
uint_fast32_t PREDIV1_lsb = ((HSE_DIV - 1) & 1) * RCC_CFGR_PLLXTPRE_PREDIV1_Div2;
uint_fast32_t PLL_MUL_coeff = (PLL_MUL - 2) * RCC_CFGR_PLLMULL3;
RCC->CFGR = 0
| RCC_CFGR_MCO_NOCLOCK // No clocks on MCO pin
| PLL_MUL_coeff //
| RCC_CFGR_PLLSRC_PREDIV1 // MCE CLK/PREDIV1 used as PLL source
| PREDIV1_lsb //
| RCC_CFGR_ADCPRE_DIV8 // slowest ADC clock
| RCC_CFGR_PPRE2_DIV1 // high-speed APB (PCLK1) clocks / 1
| RCC_CFGR_PPRE1_DIV1 // low-speed APB (PCLK2) clocks / 1
| RCC_CFGR_HPRE_DIV1 // AHB (SYSCLK) clocks / 1
| RCC_CFGR_SW_HSI // use HSI as system clock
;
RCC->CFGR2 = HSE_DIV - 1; // PLL_CLKIN = HSE_CLK / 8
// Enable PLL
RCC->CR = 0
| RCC_CR_HSEON
| RCC_CR_HSEBYP
| RCC_CR_PLLON
;
// wait until PLL locks
while (!(RCC->CR & RCC_CR_PLLRDY))
;
// Set PLL clocks as system clocks
RCC->CFGR = 0
| RCC_CFGR_MCO_NOCLOCK // No clocks on MCO pin
| PLL_MUL_coeff //
| RCC_CFGR_PLLSRC_PREDIV1 // MCE CLK/PREDIV1 used as PLL source
| PREDIV1_lsb //
| RCC_CFGR_ADCPRE_DIV8 // slowest ADC clock
| RCC_CFGR_PPRE2_DIV1 // high-speed APB (PCLK1) clocks / 1
| RCC_CFGR_PPRE1_DIV1 // low-speed APB (PCLK2) clocks / 1
| RCC_CFGR_HPRE_DIV1 // AHB (SYSCLK) clocks / 1
| RCC_CFGR_SW_PLL // use PLL as system clock
;
// Wait until PLL be used as system clock source
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
;