Skip to main content
_andreas
Senior
September 2, 2022
Solved

PLL on B-U585I-IOT02A (STM32U585AI)

  • September 2, 2022
  • 1 reply
  • 1192 views

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

This topic has been closed for replies.
Best answer by _andreas

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 (?) */
 );

1 reply

_andreas
_andreasAuthorBest answer
Senior
September 2, 2022

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 (?) */
 );