cancel
Showing results for 
Search instead for 
Did you mean: 

Can't get max frequency out of STM32H7

CLeo.1
Senior II

Hi everyone,

I am having a hard time trying to get the max clock frequency out of the STM32H753ZIT6U.

This is the revision V model and is capable of hitting 480MHz unlike its Y revision.

This is my code to get to 480MHz:

LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
	LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
	LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);
	SYSCFG_PWRCR_REG |= (0x01 << 0);
	while(LL_PWR_IsActiveFlag_VOS() == 0);
 
	FLASH_ACR_REG &= ~(0x3F << 0);
	FLASH_ACR_REG |=  (0x3F << 0);
 
	LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
	LL_RCC_PLL1_SetM(4);
	LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
	LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
	LL_RCC_PLL1P_Enable();
	LL_RCC_PLL1_SetP(1);
	LL_RCC_PLL1_SetN(30);
	LL_RCC_PLL1_Enable();
	while(LL_RCC_PLL1_IsReady() == 0);
 
	LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
	LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
	LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
	LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
	LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
	LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
	LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);

After all this its hitting 240MHz proven via the oscillscope and polling a USART Rx that suppose to timeouts on 1 second, but It timesout actually on 2 seconds.

I have no idea whats wrong here as I double checked my numbers for the PLL as it should achieve 480MHz

Using HSI Clock = 64MHz thus,

64MHz / 4 (M) = 16MHz * 30 (N) = 480MHz / 1 (P)

Any ideas?

1 ACCEPTED SOLUTION

Accepted Solutions
CLeo.1
Senior II

Thank you guys for the input, I found the issue, it was just my assumption that it executes its instructions within one clock cycle, I have now moved the software delay implementation into hardware and all seems fine.

View solution in original post

9 REPLIES 9
christop
ST Employee

For STM32H753, LL_RCC_PLL11_SetP() can only accept values between 2 and 128:

/**

 * @brief Set PLL1 P Coefficient

 * @note  This API shall be called only when PLL1 is disabled.

 * @rmtoll PLL1DIVR    P1     LL_RCC_PLL1_SetP

 * @param P parameter can be a value between 2 (or 1*) and 128 (ODD division factor not supported)

 *

 * (*) : For stm32h72xxx and stm32h73xxx family lines.

 */

__STATIC_INLINE void LL_RCC_PLL1_SetP(uint32_t P)

{

 MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_P1, (P - 1UL) << RCC_PLL1DIVR_P1_Pos);

}

To achieve 480MHz, you need to set PLL1 P = 2 and PLL1 N = 60:

  1. LL_RCC_PLL1_SetP(2);
  2. LL_RCC_PLL1_SetN(60);
CLeo.1
Senior II

@christop​  Yup, tried that, no bueno still seeing the same results

LCE
Principal

Don't you have to set voltage scaling to VOS0 to get fulll 480 MHz?

For RCC setup I would use CubeMX at least to check all settings.

Yes sir I do, however throughout the reference manual its mentioned that to get to VOS0 its simply getting the Voltage Scale to 1 and enabling the ODEN bit with in SYSCFG, to my understanding.

Actually interesting, when manually writing into the D3CR regiester I see the contents within the resgister change oppose to using the LL API variant of it then when switching to PLL1_P clock the MCU crashes

Ah, thanks! Another difference to the H735 that I am working on currently.

christop
ST Employee

@CLeo.1​ You can try with the below clock configuration generated with STM32CubeMX 6.8.0, it uses LL driver API from STM32CubeH7 v1.11.0. I have output the PLL1P clock/10 on MCO2 and I can see 48Mhz signal on MCO2 (PC9).

void SystemClock_Config(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_4)
  {
  }
  LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
  LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
  while (LL_PWR_IsActiveFlag_VOS() == 0)
  {
  }
  LL_RCC_HSI_Enable();
 
   /* Wait till HSI is ready */
  while(LL_RCC_HSI_IsReady() != 1)
  {
 
  }
  LL_RCC_HSI_SetCalibTrimming(64);
  LL_RCC_HSI_SetDivider(LL_RCC_HSI_DIV1);
  LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
  LL_RCC_PLL1P_Enable();
  LL_RCC_PLL1Q_Enable();
  LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
  LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
  LL_RCC_PLL1_SetM(4);
  LL_RCC_PLL1_SetN(60);
  LL_RCC_PLL1_SetP(2);
  LL_RCC_PLL1_SetQ(2);
  LL_RCC_PLL1_SetR(2);
  LL_RCC_PLL1_Enable();
 
   /* Wait till PLL is ready */
  while(LL_RCC_PLL1_IsReady() != 1)
  {
  }
 
   /* Intermediate AHB prescaler 2 when target frequency clock is higher than 80 MHz */
   LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
 
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
 
   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1)
  {
 
  }
  LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
  LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
  LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
  LL_SetSystemCoreClock(480000000);
 
   /* Update the time base */
  if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
  {
    Error_Handler();
  }
  LL_RCC_ConfigMCO(LL_RCC_MCO1SOURCE_HSI, LL_RCC_MCO1_DIV_1);
  LL_RCC_ConfigMCO(LL_RCC_MCO2SOURCE_PLL1PCLK, LL_RCC_MCO2_DIV_10);
}

(edited to have the source code as code snippet)

Pavel A.
Evangelist III

.

CLeo.1
Senior II

Thank you guys for the input, I found the issue, it was just my assumption that it executes its instructions within one clock cycle, I have now moved the software delay implementation into hardware and all seems fine.