cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_RCC_GetSysClockFrequency shows different frequency to STM32Cube clock config tool

Using the STM32Cube with a STM32F4, I set the SYSCLK to 96Mhz

Which generates this code

 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;

 RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;

 RCC_OscInitStruct.LSEState = RCC_LSE_ON;

 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

 RCC_OscInitStruct.PLL.PLLM = 4;

 RCC_OscInitStruct.PLL.PLLN = 96;

 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

 RCC_OscInitStruct.PLL.PLLQ = 4;

However, if I call HAL_RCC_GetSysClockFreq directly after SystemClock_Config() e.g.

 SystemClock_Config();

 clkF = HAL_RCC_GetSysClockFreq();

clkF is 72000000 i.e 72Mhz

I've checked that HSE_VALUE is correctly defined as 8000000

So I made a copy of HAL_RCC_GetSysClockFreq() and added some debugging, which produced these values

{

uint32_t pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;

uint32_t plln = (RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;

uint32_t pllvco = ((int64_t)HSE_VALUE * (int64_t)plln / (int64_t)pllm);

uint32_t pllp = ((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> RCC_PLLCFGR_PLLP_Pos) + 1U) *2U);

uint32_t sysclockfreq = pllvco/pllp;

USB_DEBUG_printf("HSE:%d pllm:%d plln:%d pllvco:%d pllp:%d SYSCLK:%d\n",HSE_VALUE,pllm,plln,pllvco,pllp,sysclockfreq);

}

HSE:8000000 pllm:8 plln:288 pllvco:288000000 pllp:4 SYSCLK:72000000

So PLLM is being read from the hardware as a different value to what has been requested, and PLLN value is something totally different.

With the result that the SYSCLK is either wrong, or being wrongly calculated by HAL_RCC_GetSysClockFreq

I've looked at the frequency of some of the PWM outputs that I'm using, and it does appear that the processor is running at 72Mhz not 96Mhz

Yet the Timer 14 millisecond tick interrupt does seem to be the correct frequency

Hence I'm confused about whats going on :(

0693W00000UFTFcQAP.png

5 REPLIES 5

Just to potentially answer my own question.

I think the call to SystemClock_Config(); may be failing to initialise the clock because the main application is being run by proprietary bootloader, which has probably already setup the MCU with those configuation settings

Is there any way I can reset the RCC ready to have a new RCC config applied ?

To continue to try to answer my own question.

I've tried calling

 HAL_RCC_DeInit();

before

 SystemClock_Config();

in main()

However, this doesn't seem to work.

The firmware seems to be running at a very low clock rate, as the PWM I'm using for the display backlight is running at about 1/10th the speed it normally does.

And USB is not working, so I can't use my normal debug method.

I currently don't have SWD connected to the device, so I'm probably going to need to debug by writing messages to the LCD display that the device has.

But I suspect the call to set the RCC is still failing, even though I've called

 HAL_RCC_DeInit();

Continuing...

I found sample code for a STM32G0 to switch clock inputs and I have modified the function that sets SYSCLK as LSI to use HSI (see below)

Calling this at the beginning of main() seems to resolve the problem of the HSE PLL config not being accepted.

And my debug code is now outputting the SYSCLK value I had expected

HSE:8000000 pllm:4 plln:96 pllvco:192000000 pllp:2 SYSCLK:96000000

So I have solved one mystery.

Perhaps by default the STMCube generated code should check if the SYCLK is already set to HSE before and set it to HSI, becuase I can't believe this is the only instance where people are using a bootloader which may not be using the same RCC OSC / PLL values as the main application.

static void SystemClockHSI_Config(void)

{

 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 /* -1- Select HSI as system clock source */

 RCC_ClkInitStruct.ClockType      = RCC_CLOCKTYPE_SYSCLK;

 RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_HSI;

 RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;

 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)

 {

   /* Initialization Error */

   Error_Handler();

 }

 ClockSourceStatus = 1;

}

It's not as if there's one perfect solution to this, and the code is already hugely bloated.

Changing the clocks is disruptive.

Frequently the boot loader is responsive for system bring up, including clocks, pins, bus interfaces, external memories. It isn't necessary for app code to repeat this or tear everything down. This can be especially disruptive if the code is running from external memory, be it SDRAM or QSPI, etc.

As the system architect you get to decide who contractually owns different portions of the bring up, and what state the system is in when you hand over control.

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

Unfortunately I'm stuck with using the bootloader that comes with the hardware, so I'll just need to work around the the problem.

But at least I have a work around.

However it has shown up some other configuation problems, specifically with the FSMC , that doesnt seem to drive the display if I reduce the clock rate :(

Anyway. One step forward....