Skip to main content
Wolfgang Pupp
Associate III
August 18, 2021
Question

STM32H7 CubeMX RCC Init order bug causes hardfault

  • August 18, 2021
  • 2 replies
  • 1493 views

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).

This topic has been closed for replies.

2 replies

Tesla DeLorean
Guru
August 18, 2021

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 VenmoUp vote any posts that you find helpful, it shows what's working..
Wolfgang Pupp
Associate III
August 18, 2021

> 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();
	}
}