cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 CubeMX RCC Init order bug causes hardfault

Wolfgang Pupp
Associate III

Edit: I managed to narrow this down and create a reproducible, minimal example.

Posted as bug-report here: https://community.st.com/s/question/0D53W000011uLtPSAU/stm32h7-cubemx-critical-codegeneration-bug-rccll

In my opinion the CubeMX generated clock initialization is in the wrong order and this seems to potentially cause hardfaults.

Consider following example configuration:

0693W00000DpgrBQAR.pngThis should be valid according to CubeMX and my understanding. BUT:

In the initilaization code, CubeMX *first* picks the PLL as system clock and only afterwards sets the prescalers.

Generated code (SystemClock_Config):

[...]
   /* 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);
   LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_2);
   LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
   LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
   LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2); // here is where I get a hardfault
   LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
   LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
 
   LL_SetSystemCoreClock(275000000);
   [...]

IF I change the order and only call LL_RCC_SetSysClkSource AFTER all the APB prescalers are set, then everything works (=> no more hardfault).

I'm not sure that my understanding is correct.

Could someone more knowledgeable please confirm that this ordering-issue is indeed causing the hardfaults?

µC: STM32H730VBH

CUBEMX: v6.3.0

Edit:

I'm pretty sure this is a problem exactly as described. AFAICT the problem can be hidden by instruction prefetching, but when single stepping (on instruction level), this hardfaults directly after SetSysClkSource (presumably because the default prescaler values are too low at that point).

2 REPLIES 2

I'd be setting the bus and flash prefetch before switching to a faster clock. The cart should never go in front of the horse...

Is this the first time the clocks are configured, or a second? ie loader or SystemInit() code set previously?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Wolfgang Pupp
Associate III

> Is this the first time the clocks are configured, or a second? ie loader or SystemInit() code set previously?

Second time; the autogenerated SystemClock_Config in question is called from main, after SystemInit and all the other startup stuff.

The SystemInit forces HSI on and uses that together with conservative wait-state config AFAICT (also autogenerated).

> I'd be setting the bus and flash prefetch before switching to a faster clock.

This happens earlier in the function. Complete SystemClock_Config (generated) below:

void SystemClock_Config(void)
{
	LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
	while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) {}
	LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
	LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2);
	LL_RCC_HSE_Enable();
 
	/* Wait till HSE is ready */
	while (LL_RCC_HSE_IsReady() != 1) {}
	LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
	LL_RCC_PLL1P_Enable();
	LL_RCC_PLL1R_Enable();
	LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4);
	LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
	LL_RCC_PLL1_SetM(4);
	LL_RCC_PLL1_SetN(275);
	LL_RCC_PLL1_SetP(1);
	LL_RCC_PLL1_SetQ(8);
	LL_RCC_PLL1_SetR(8);
	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);
	LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_2);
	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(275000000);
 
	/* Update the time base */
	if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) {
		Error_Handler();
	}
}