'PLL Init function in STM32F429 to configure max frequency (180Mhz)

I want to configure PLL in STM32F429 to its max frequency (180Mhz) without using STMCube-generated configurations. I am using my own register definitions like this

#define RCC_CFGR                (*((volatile uint32 *)0x40023808))

and my own SET_BIT()/CLEAR_BIT() macros

My questions are:

1- Is this procedure correct?

2- How can I check if it is working?

3- May the MCU can not handle this speed (reading/writing in registers)?

#define PLL_M      16
#define PLL_N      360
#define PLL_P      2
#define PLL_Q      7


void PLL_init(void)
{
    /* System Init */
     /* HSI ON */
    SET_BIT(RCC_CR, HSION);

     /* Reset CFGR register */
    RCC_CFGR = 0x00000000 ;

    /* Reset PLLCFGR register */
    RCC_PLLCFGR  = 0x24003010;

    /* Reset HSEON, CSSON and PLLON bits */
    RCC_CR &= (uint32_t)0xFEF6FFFF;

    /************* SetSysClock ************/

    RCC_PLLCFGR  = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16)| (PLL_Q << 24);

    /* PLL clock Source HSI or HSE */
    CLEAR_BIT(RCC_PLLCFGR, PLLSRC);

    /* APB1 PWR Enable*/
    SET_BIT(RCC_APB1ENR, PWREN);
    /* Select regulator voltage output Scale 1 mode, System frequency up to 180 MHz */
    SET_BIT(PWR_CR, VOS0);
    SET_BIT(PWR_CR, VOS1);

    /* AHB div 1 */
    CLEAR_BIT(RCC_CFGR,HPRE3);
    CLEAR_BIT(RCC_CFGR,HPRE0);


    /* APB2 Div  =  2*/
    CLEAR_BIT(RCC_CFGR,PPRE20);
    CLEAR_BIT(RCC_CFGR,PPRE21);
    SET_BIT(RCC_CFGR, PPRE23);

    /* APB 1 Div = 8  */
    CLEAR_BIT(RCC_CFGR, PPRE10);
    SET_BIT(RCC_CFGR, PPRE11);
    SET_BIT(RCC_CFGR, PPRE12);


    /* SET PLL ON  */
    SET_BIT(RCC_CR, PLLON);

    /* Check PLL is ready */
    while(BIT_IS_CLEAR(RCC_CR,PLLRDY));

    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
    SET_BIT(PWR_CR, ODEN);
    while(BIT_IS_CLEAR(PWR_CSR,ODRDY));

    SET_BIT(PWR_CR, ODSWEN);
    while(BIT_IS_CLEAR(PWR_CSR,ODSWRDY));

    SET_BIT(FLASH_ACR, PRFTEN);
    SET_BIT(FLASH_ACR, ICEN);
    SET_BIT(FLASH_ACR, DCEN);
    FLASH_ACR |= FLASH_ACR_LATENCY_5WS;

    /* Select the main PLL as system clock source */
    CLEAR_BIT(RCC_CFGR, SW0);
    SET_BIT(RCC_CFGR, SW1);

    /* Wait till the main PLL is used as system clock source */
    while(!BIT_IS_CLEAR(RCC_CFGR,SWS0) && !BIT_IS_SET(RCC_CFGR,SWS1) ); /* Loop till is Set */
}



Solution 1:[1]

  1. I did exactly this thing on my STM32F746 - set 216MHz with registers. It looks very similar to mine. Not observing any obvious things. You wait for all ready flags and all. Overdrive and overdrive switching are there, flash wait states are there.
  2. How to check if it's working - timer is an easy idea. Timer that is clocked by a system clock with some prescaler and that outputs PWM to some pin. Given the configuration of the timer is set by you, you should know what output frequency to expect. You can set timer parameters in such a way that you expect timer-interrupt-toggle an LED every 1s.
  3. The MCU should handle it OK if all prescalers for AHB/APB are within limits, as well as Flash latency is set correctly. Which seems to be the case.

If you want to compare the logic with what I do with STM32F746 (which looks almost identical in terms of how you do it), you can check it in this rcc.c file of mine. It definitely works, I tested it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ilya