cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G4 CubeMX SystemClock_Config() generation error ?

Nikita91
Lead II

I generate a LL code with STM32CubeMx 6.4 for STM32G491.

In SystemClock_Config() I get

  LL_RCC_SetSysClkSource (LL_RCC_SYS_CLKSOURCE_PLL) ;
  LL_RCC_SetAHBPrescaler (LL_RCC_SYSCLK_DIV_2) ;
  /* Wait till System clock is ready */
  while (LL_RCC_GetSysClkSource () != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {
  }

The AHB prescaler setting (line 2) is after the Sys clock source select (line1).

This is strange: in HAL functions these lines are inverted.

6 REPLIES 6
Bubbles
ST Employee

Hi @Nikita91​ ,

depending on the clock source and frequency actually both ways may be correct or incorrect. The difference is whether you are lowering or increasing the frequency. It's important to never exceed any top frequency and to always have enough Flash wait states.

To be sure, use CubeMX graphical clock configurator and try the intermediate steps to see if there is no intermediate step which may cause NMI/HardFault.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Nikita91
Lead II

As this is the 1st clock setting after reset, the clock jumps from 16 MHz to 168 MHz, so I am  increasing the frequency.

The generated code configure the PLL, then wait for PLL ready

Then set sys clock source to PLL => I suppose the system clock is now the 168 MHz PLL frequency.

Then the AHB prescaler is set to 2 => sys frequency is PLL/2

Is the system frequency at 168 MHz for a short time?.

Hi @Nikita91​ ,

yes, it is, but that should not be a problem. This G4 can work fine with this frequency on HCLK. But beware of the Flash latency timing. HCLK is the Flash clock and if you do not set a conservative Flash latency before switching to the 168MHz PLL source, you may end up in HardFault. It's sort of tricky, because I witnessed this Flash taking frequencies several times above supposed maximum when tested in room temperature with some device, and then producing seemingly inexplicable HardFaults when the same code was used in field.

I'd probably increase the clock this way:

1) set the flash latency as recommended for the final HCLK

2) set AHB prescaler

3) switch to the PLL

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Nikita91
Lead II

Thank you for these explanations.

Of course, increasing the WS of the Flash is the first thing to do.

But if then the G4 can go from HSI 16 MHz to PLL 168 MHz directly, I wonder why the code generated by CubeMX goes through an intermediate frequency for 1us, but wrongly (and the HAL does this too, but correctly).

The RM0440 V6 P98 and P193 does not say to do this.

Who can I trust?

Generally the RM should be primary source. Which ST code takes the intermediate step? I looked at some examples in the Cube package and didn't notice any such thing. Also in ES there no limitation regarding frequency change. I remember there were some limitations on the older devices but I'm not aware of any such constraint on G4.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Nikita91
Lead II

The subject is the code generated by CubeMX:

void SystemClock_Config(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4)
  {
  }
  LL_PWR_EnableRange1BoostMode();
  LL_RCC_HSE_Enable();
   /* Wait till HSE is ready */
  while(LL_RCC_HSE_IsReady() != 1)
  {
  }
 
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_2, 28, LL_RCC_PLLR_DIV_2);
  LL_RCC_PLL_EnableDomain_SYS();
  LL_RCC_PLL_Enable();
   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {
  }
 
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {
  }
 
  /* Insure 1µs transition state at intermediate medium speed clock based on DWT */
  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
  DWT->CYCCNT = 0;
  while(DWT->CYCCNT < 100);
  /* Set AHB prescaler*/
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
 
  LL_Init1msTick(168000000);
 
  LL_SetSystemCoreClock(168000000);
  LL_RCC_ConfigMCO(LL_RCC_MCO1SOURCE_SYSCLK, LL_RCC_MCO1_DIV_8);
}

This code has a transition state of 1µs, which is what confused me.

If there is no constraint I can therefore simplify the code like this:

void SystemClock_Config(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4)
  {
  }
  LL_PWR_EnableRange1BoostMode();
  LL_RCC_HSE_Enable();
   /* Wait till HSE is ready */
  while(LL_RCC_HSE_IsReady() != 1)
  {
  }
 
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_2, 28, LL_RCC_PLLR_DIV_2);
  LL_RCC_PLL_EnableDomain_SYS();
  LL_RCC_PLL_Enable();
   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {
  }
 
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {
  }
 
  /* Set APBx prescaler*/
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
 
  LL_Init1msTick(168000000);
 
  LL_SetSystemCoreClock(168000000);
  LL_RCC_ConfigMCO(LL_RCC_MCO1SOURCE_SYSCLK, LL_RCC_MCO1_DIV_8);
}