I am trying to switch the cyctem clock source on the stm32l433 MCU from the MSI (set by default) to PLL. My code for setting up the PLL & switching the sysclk source is this:
/* Set latency to 4ws to support up to 80MHz */
SET_LATENCY(FLASH_ACR_LATENCY_4WS);
while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_4WS)
;
/* Disable PLL, enable HSI16 & HSI48 */
RCC->CR = (RCC->CR & ~RCC_CR_PLLON) | RCC_CR_HSION;
if (!(RCC->CRRCR & RCC_CRRCR_HSI48ON))
RCC->CRRCR |= RCC_CRRCR_HSI48ON;
/* Wait for PLL, HSI16 & 48 */
while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY) || !(RCC->CR & RCC_CR_HSIRDY) || (RCC->CR & RCC_CR_PLLRDY))
;
/* Setup PLL */
RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLREN | RCC_PLLCFGR_PLLR |
RCC_PLLCFGR_PLLQEN | RCC_PLLCFGR_PLLQ |
RCC_PLLCFGR_PLLPEN | RCC_PLLCFGR_PLLPDIV | RCC_PLLCFGR_PLLP |
RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLM);
RCC->PLLCFGR |= (78 << RCC_PLLCFGR_PLLN_Pos) | (0b11 << RCC_PLLCFGR_PLLM_Pos); /* Set up PLL multiplier to 78/4 */
RCC->PLLCFGR |= 0b01 << RCC_PLLCFGR_PLLR_Pos; /* Set PLL division to 4 */
/* Enable PLL & wait for it */
RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN;
RCC->CR |= RCC_CR_PLLON;
while (RCC->CR & RCC_CR_PLLRDY)
;
/* Setup system prescalers */
RCC->CFGR &= ~RCC_CFGR_HPRE; /* Set AHB prescaler to no division */
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PPRE1) | RCC_CFGR_PPRE1_DIV4; /* Set APB1 prescaler to 4 */
RCC->CFGR &= ~RCC_CFGR_PPRE2; /* Set APB2 prescaler to no division */
/* Set PLL as sysclk source & wait for it */
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
;
Everything runs fine until I try to set PLL as the sysclk source. After I set SW bits to PLL, i need to read the SWS bits to make sure that the hardware has applied the change, and when the program reaches the while loop to wait for the SWS bits, it hangs and never exits the loop.
Am I doing something wrong or in the wrong order? Is there any other register I need to set before changing sysclk source?
I have tried switching to HSI16 instead of PLL and that clock source does work and the MCU exits the while loop almost immediately. I have checked that both my PLLN and PLLM values are in the acceptable range and thet the VCOin and VCOout are in the acceptable frequency range too.