cancel
Showing results for 
Search instead for 
Did you mean: 

PLL on B-U585I-IOT02A (STM32U585AI)

_andreas
Senior

0693W00000SuOAnQAN.pngI'm using MSIS at 24 MHz for everything, like this:

    SET_BIT(RCC->CR, RCC_CR_MSISON);
    while (0 == (RCC->CR & RCC_CR_MSISRDY));
    SET_BIT(RCC->ICSCR1, RCC_ICSCR1_MSIRGSEL);
    MODIFY_REG(RCC->ICSCR1, RCC_ICSCR1_MSISRANGE, RCC_ICSCR1_MSISRANGE_0);
 
    // enable 32kHz clock crystal
    SET_BIT(PWR->DBPR, PWR_DBPR_DBP); // enable write access to backup domain
    MODIFY_REG(RCC->BDCR, RCC_BDCR_LSEDRV, RCC_BDCR_LSEDRV_0); // medium-low drive power
    SET_BIT(RCC->BDCR, RCC_BDCR_LSESYSEN); // enable propagation to other peripherals (like LPTIM4)
    SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); // LL_RCC_LSE_Enable
    while (0 == READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY)); // wait until ready
 
    // use it to trim the MSIS oscillator
    MODIFY_REG(RCC->CR, RCC_CR_MSIPLLSEL, RCC_CR_MSIPLLSEL);
    SET_BIT(RCC->CR, RCC_CR_MSIPLLEN);
 
    // set MSIS as system clock
    MODIFY_REG(RCC->CFGR1, RCC_CFGR1_SW, 0);
    while (0 != READ_BIT(RCC->CFGR1, RCC_CFGR1_SWS)); /* Wait until system clock switched to MSIS */
 
    SystemCoreClock = 24000000UL;
    SET_BIT(PWR->CR3, PWR_CR3_FSTEN); // fast startup of regulator
    MODIFY_REG(RCC->CFGR1, RCC_CFGR1_STOPWUCK, 0); /* use MSIS to wakeup from stop mode */
    CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLFAST);
    CLEAR_BIT(FLASH->ACR, FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_Msk);

Then I configure the PLL like this:

    SET_BIT(RCC->AHB2ENR1, RCC_AHB2ENR1_GPIOAEN);
    SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_PWREN);
    /* make sure PLL1 is off */
    CLEAR_BIT(RCC->CR, RCC_CR_PLL1ON);
    MODIFY_REG(RCC->PLL1CFGR,
 
               RCC_PLL1CFGR_PLL1SRC | RCC_PLL1CFGR_PLL1RGE |
               RCC_PLL1CFGR_PLL1FRACEN | RCC_PLL1CFGR_PLL1M |
               RCC_PLL1CFGR_PLL1PEN | RCC_PLL1CFGR_PLL1QEN | RCC_PLL1CFGR_PLL1REN,
 
               RCC_PLL1CFGR_PLL1SRC_0 /* MSI PLL */ |
               RCC_PLL1CFGR_PLL1RGE   /* MSI input range between 8 and 16 MHz */ |
               RCC_PLL1CFGR_PLL1M_0   /* divide 24 MHz by 2 (prescaler before VCO, M) */ |
               RCC_PLL1CFGR_PLL1REN   /* enable output of PLL1R */
              );
 
    CLEAR_REG(RCC->PLL1FRACR); /* ensure a defined (but as far unused) fractional divider */
    
    MODIFY_REG(RCC->PLL1DIVR,
 
               RCC_PLL1DIVR_PLL1N | RCC_PLL1DIVR_PLL1R, /* clear what we need */
 
               (11 << RCC_PLL1DIVR_PLL1N_Pos) /* VCO is this many times higher than its input frequency */ |
               (0 << RCC_PLL1DIVR_PLL1R_Pos)  /* post divider: value + 1 (?) */
              );

Then I setup the MCO like this:

 /**
    * MCO GPIO Configuration
    * CN13, Pin 2: PWM/D9
    * PA8   ------> MCO
    */
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE8, (2 << GPIO_MODER_MODE8_Pos)); // set mode to alternate function
    CLEAR_BIT(GPIOA->OTYPER, GPIO_OTYPER_OT8); // set output type to push pull
    CLEAR_BIT(GPIOA->PUPDR, GPIO_PUPDR_PUPD8); // no pullup
    MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED8, (3 << GPIO_OSPEEDR_OSPEED8_Pos)); // set high speed for pins
    MODIFY_REG(GPIOA->AFR[1], GPIO_AFRH_AFSEL8, (0 << GPIO_AFRH_AFSEL8_Pos)); // select alternate function 0 (MCO) on pin
    /*
     * 0x00000000U                                                   MCO output disabled, no clock on MCO
     * RCC_CFGR1_MCOSEL_0                                            SYSCLK selection as MCO1 source
     * RCC_CFGR1_MCOSEL_1                                            MSIS selection as MCO1 source
     * (RCC_CFGR1_MCOSEL_0 | RCC_CFGR1_MCOSEL_1)                     HSI selection as MCO1 source
     * RCC_CFGR1_MCOSEL_2                                            HSE selection as MCO1 source
     * (RCC_CFGR1_MCOSEL_0 | RCC_CFGR1_MCOSEL_2)                     Main PLL selection as MCO1 source
     * (RCC_CFGR1_MCOSEL_1 | RCC_CFGR1_MCOSEL_2)                     LSI selection as MCO1 source
     * (RCC_CFGR1_MCOSEL_0 | RCC_CFGR1_MCOSEL_1| RCC_CFGR1_MCOSEL_2) LSE selection as MCO1 source
     * RCC_CFGR1_MCOSEL_3                                            HSI48 selection as MCO1 source
     * (RCC_CFGR1_MCOSEL_0 | RCC_CFGR1_MCOSEL_3)                     MSIK selection as MCO1 source
     */
    MODIFY_REG(RCC->CFGR1, (RCC_CFGR1_MCOSEL | RCC_CFGR1_MCOPRE), (RCC_CFGR1_MCOSEL_0 | RCC_CFGR1_MCOSEL_2) | (3 << RCC_CFGR1_MCOPRE_Pos));

Just to check, this is what my scope gives me on MCO (PA/CN13-D9), when using SYSCLK on it. It gives nearly perfect 3MHz (24MHz/8). But the PLL1R is at 18 MHz, which means that the VCO has a frequency of 144 MHz, instead of the 132 MHz that I've configured (24MHz/2*11). What am I missing?0693W00000SuO9GQAV.png

1 ACCEPTED SOLUTION

Accepted Solutions
_andreas
Senior

Argh, found it N of 11 implies a divider of 12

 MODIFY_REG(RCC->PLL1DIVR,
 
               RCC_PLL1DIVR_PLL1N | RCC_PLL1DIVR_PLL1R, /* clear what we need */
 
               (11 << RCC_PLL1DIVR_PLL1N_Pos) /* VCO is this many times + 1 higher than its input frequency */ |
               (0 << RCC_PLL1DIVR_PLL1R_Pos)  /* post divider: value + 1 (?) */
              );

View solution in original post

1 REPLY 1
_andreas
Senior

Argh, found it N of 11 implies a divider of 12

 MODIFY_REG(RCC->PLL1DIVR,
 
               RCC_PLL1DIVR_PLL1N | RCC_PLL1DIVR_PLL1R, /* clear what we need */
 
               (11 << RCC_PLL1DIVR_PLL1N_Pos) /* VCO is this many times + 1 higher than its input frequency */ |
               (0 << RCC_PLL1DIVR_PLL1R_Pos)  /* post divider: value + 1 (?) */
              );