Search code examples
cstm32

Why is RCC PLL not enabled on STM32G474RE


I am trying to configure the RCC clock of a STM32G474RE board with PLL using HSI16 as clock source and PLLM = 1, PLLN = 10, AHB = 1, APB1 = 1 and APB2 = 4 as the configuration. However when I run the code the PLLRDY flag is never set and I'm stuck in the infinite loop.

#include "main.h"

void SytemClockConfig(void){
    /*Enable HSI16*/
    RCC->CR |= RCC_CR_HSION;
    while(!(RCC->CR & RCC_CR_HSIRDY)){}
    
    /*Configure PWR and FLASH*/
    RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
    PWR->CR1 |= (0x01 & PWR_CR1_VOS_Msk);
    FLASH->ACR |= FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_2WS | FLASH_ACR_PRFTEN;
        
    /*Configure AHB and APB*/
    RCC->CFGR |= (0x00 & RCC_CFGR_HPRE_Msk);
    RCC->CFGR |= (0x00 & RCC_CFGR_PPRE1_Msk);
    RCC->CFGR |= (0x05 & RCC_CFGR_PPRE2_Msk);
        
    /*Config PLL*/
    RCC->PLLCFGR |= (0x02 & RCC_PLLCFGR_PLLSRC_Msk);
    RCC->PLLCFGR |= (0x00 & RCC_PLLCFGR_PLLM_Msk);
    RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLN_Msk);
    RCC->PLLCFGR |= (0x0A & RCC_PLLCFGR_PLLN_Msk);
    RCC->PLLCFGR |= (0x01 & RCC_PLLCFGR_PLLREN_Msk);
    RCC->PLLCFGR |= (0x00 & RCC_PLLCFGR_PLLR_Msk);

        
    /*Enable PLL*/
    RCC->CR |= (0x01 & RCC_CR_PLLON);
    while(!(RCC->CR & RCC_CR_PLLRDY)){}
        
    RCC->CFGR |= (0x05 & RCC_CFGR_SW_Msk);
    while((RCC->CFGR & RCC_CFGR_SWS) != (0x03 & RCC_CFGR_SWS_Msk)){}
} 

int main(void){
    SytemClockConfig();
    
}

Solution

  • You simply do not write the values you think you write. You need to learn how binary logical operations work. Basically, almost all operations are wrong. I will give you only some examples.

    • RCC->CR |= (0x01 & RCC_CR_PLLON); this operation does nothin'. PLLON bit is at position 24. You binary AND 1 and 1 << 24. The result is 0. Then you binary OR it to the RCC -> CR register. This operation does nothing. You need to RCC->CR |= RCC_CR_PLLON;

    • RCC->CFGR |= (0x00 & RCC_CFGR_HPRE_Msk); it is the same as RCC->CFGR |= 0; (It does not zero HPRE bits!!!)

    And many many more (almost all of them).

    I would suggest to practice binary logic operations before attempting any bare metal programming.

    If you want to:

    • set bit at position n - VAL |= (1U << n)
    • reset bit at the position n - VAL &= ~(1 << n)
    • toggle bit at the position n - VAL ^= (1 << n)

    If you want to put value 5 into PPRE2 bits in the register

    uint32_t tmp = RCC->CFGR;
    tmp &= ~RCC_CFGR_PPRE2_Msk;
    tmp |= 5UL << RCC_CFGR_PPRE2_Pos
    RCC->CFGR = tmp;
    

    I would suggest using temporary variables and assign value to the register.