HSI, HSE, PLL ???

Post here first, or if you can't find a relevant section!
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

HSI, HSE, PLL ???

Post by STM32ardui »

Is there an good and understandable explanation, how clock system is working?


From reference manual RM0444 (STM32G0B1CBT6):

Code: Select all

3.3.4 FLASH read access latency

After power reset, the HCLK clock frequency is 16 MHz in Range 1 and 0 wait state (WS) is
configured in the FLASH_ACR register.
When wakeup from Standby, the HCLK clock frequency is 16 MHz in Range 1 and 0 wait
state (WS) is configured in the FLASH_ACR register.

Code: Select all

5.2 Clocks

The HSISYS is used as system clock source after startup from reset, with the division by 1
(producing HSI16 frequency).
So HSISYS = 16 MHz and SYSCLK = 16 MHz. :?:
But in generic_clock.c I see:

Code: Select all

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK
Is PLLCLK = PLLRCLK?



Inside generic_clock.c I find:

Code: Select all

  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
So PLLRCLK, PLLQCLK and PLLRCLK = 64 MHz (16 MHz / 1 * 8 / 2) ?
But how can SYSCLK be 16 MHz?

And what if I want to use HSE?
Crystal is 8 MHz - half of HSI . Would millis() work with half the speed?
by GonzoG » Sun Jul 21, 2024 2:28 pm
STM32ardui wrote: Sun Jul 21, 2024 2:16 pm ---
So I suppose, board is running now on HSE via PLL ...
Can someone more experienced like me confirm, that it is so simple to switch MCU from HSI to HSE directly from a sketch (without modifying headerfiles etc)?
It is that simple. Just add SystemClock_Config() and it will override default stm32duino settings - there is SystemClock_Config() for each board variant defined.

And you just figured out why many boards, even those cheap ones like blue/black pills have HSE oscillator - it's more precise then HSI.
Go to full post
ag123
Posts: 1906
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: HSI, HSE, PLL ???

Post by ag123 »

I think in the chapter Reset and clock control (RCC)
There is a chart for clock tree (figure 10)
that is an important chart to understand the whole complicated clocks system.
normally, HSI (e.g. 16 Mhz) is not further divided, it is simply used as SYSCLK.
I think g0 and c0 adopted the stm32f4, g4 style clock multipliers i.e. m, n, p, q, r pll multipliers
so that normally takes from HSE i.e. the system clock crystal e.g. 8 mhz
then you configure the M, N, P, Q, R multipliers for P, Q, R pll clock outputs e.g. from the clock tree SYSCLK can use R clock.
In that way you can set the SYSCLK (i.e. cpu clock, more correctly system clock) by changing the M, N, P, Q, R multipliers
hint, with external crystal HSE you can overclock (underclock) your chip if you really want to ;)

I've got an 'old' python script to explore the M, N, P, Q, R multipliers (mainly for f4 style PLL multipliers)
viewtopic.php?t=78
the idea here is to keep usb clocks at 48 mhz (usb needs 12mhz x 4) - so that usb works, if there is no such constraint, one can adapt the python script and one would possibly have far more permutations.
Last edited by ag123 on Sat Jul 20, 2024 6:00 pm, edited 1 time in total.
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: HSI, HSE, PLL ???

Post by STM32ardui »

From what I read in reference manual, at power up it should be like the green marked path:

ClockTree(1)a.jpg
ClockTree(1)a.jpg (67.31 KiB) Viewed 5746 times

But it doesn't correspond with the settings in generic.clock.c
ag123
Posts: 1906
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: HSI, HSE, PLL ???

Post by ag123 »

M, N, P, Q, R multipliers is normally used for HSE (i.e. external crystal e.g. 8 mhz)
i.e. for HSI, you can normally 'ignore' clock settings and assume 16 mhz
e.g. by 'right' just

Code: Select all

WEAK void SystemClock_Config(void){ //nothing };
from the codes
https://github.com/stm32duino/Arduino_C ... ic_clock.c
it seemed to be setting up for some sane values so that all the peripherals work appropriately with HSI

apparently stm32g0 can use HSI for PLL multipliers, I think some soc can't do that. So things may be different there.
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: HSI, HSE, PLL ???

Post by STM32ardui »

ag123 wrote: Sat Jul 20, 2024 6:02 pm from the codes
https://github.com/stm32duino/Arduino_C ... ic_clock.c
it seemed to be setting up for some sane values so that all the peripherals work appropriately with HSI
What's about this line:

Code: Select all

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
I would expect something like "HSISYS" as source, not PLLCLK.


When I look inside  stm32g0xx_hal_rcc.h  I find:

Code: Select all

#define IS_RCC_SYSCLKSOURCE(__SOURCE__) (((__SOURCE__) == RCC_SYSCLKSOURCE_HSI)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_HSE)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_LSE)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_LSI)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_PLLCLK))
So there is a macro RCC_SYSCLKSOURCE_HSI
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: HSI, HSE, PLL ???

Post by STM32ardui »

I started STM32CubeIDE. Without any configuration clock tree look like this:
STM32Cube-HSI.jpg
STM32Cube-HSI.jpg (26.54 KiB) Viewed 5731 times

IDE generates this SystemClock_Config():

Code: Select all

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  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)
  {
    Error_Handler();
  }
}
And SYSCLKSource is like expected RCC_SYSCLKSOURCE_HSI - like it should be.
Also PLL is off!


New project, this time I enabled HSE with crystal.
I had to use divider by 2 for PLL M, so I can get 16 MHz SYSCLK. STM32CubeIDe accept it, but it is a violation, because fVCO = 64 ... 344 MHz. Only 1 for PLL M and 4 for PLL R should be vaild.
STM32Cube-HSE.jpg
STM32Cube-HSE.jpg (55.25 KiB) Viewed 5731 times

And now IDE generates a different config-file with SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK and PLL on.

Code: Select all

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

So I believe, that generic_clock.c is wrong ...
ag123
Posts: 1906
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: HSI, HSE, PLL ???

Post by ag123 »

STM32ardui wrote: Sat Jul 20, 2024 6:13 pm What's about this line:

Code: Select all

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
I would expect something like "HSISYS" as source, not PLLCLK.


When I look inside  stm32g0xx_hal_rcc.h  I find:

Code: Select all

#define IS_RCC_SYSCLKSOURCE(__SOURCE__) (((__SOURCE__) == RCC_SYSCLKSOURCE_HSI)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_HSE)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_LSE)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_LSI)  || \
                                         ((__SOURCE__) == RCC_SYSCLKSOURCE_PLLCLK))
So there is a macro RCC_SYSCLKSOURCE_HSI

I'd think PLLCLK may after all be correct if after all it takes HSI 16 Mhz does that PLL and gives 48 Mhz
https://www.st.com/en/microcontrollers- ... 0b1mb.html
but that this is RC oscillator which means that it won't be as stable as do a crystal, crystals are deemed to have much higher Q and can't be pulled off oscillation frequency easily

but as seen in the clock tree diagram, there is also a HSI48 rc oscillator that gives straight 48 mhz
g0b1 clock tree
g0b1 clock tree
g0b1clocktree.png (34.61 KiB) Viewed 5654 times
however, that it seemed HSI48 can't directly feed SYSCLK, rather that only goes to USB
Last edited by ag123 on Sun Jul 21, 2024 1:52 pm, edited 1 time in total.
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: HSI, HSE, PLL ???

Post by STM32ardui »

ag123 wrote: Sun Jul 21, 2024 1:29 pm I'd think PLLCLK may after all be correct if after all it takes HSI 16 Mhz does that PLL and gives 48 Mhz
Of course it can work.
64 MHz, not 48 Mhz!
PLL input divider 1, mulitplicator 8 and output divider 2 makes 16 *8 / 2 = 64 MHz.

But I don't expect 64 MHz, when reference manual tells me, after startup MCU is running with 16 MHz and PLL is off.
Do you understand now my confusion?

ag123 wrote: Sun Jul 21, 2024 1:29 pm but as seen in the clock tree diagram, there is also a HSI48 rc oscillator that gives straight 48 mhz
It is for USB, there is no connection to selector for SYSCLK.

BTW: Is there something like getSYSCLK(), so I can printout the value of SYSCLK?
ag123
Posts: 1906
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: HSI, HSE, PLL ???

Post by ag123 »

if

Code: Select all

void SystemClock_Config(void) { //nothing };
is empty, I'd think HSI simply runs at 16 Mhz, otherwise no code will run.

out of curiosity stm32f401 clock tree for comparison
https://www.st.com/resource/en/referenc ... ronics.pdf
f401clocktree
f401clocktree
f401clocktree.png (30.47 KiB) Viewed 5649 times
so it'd seemed f401 can also take HSI and feed PLL and then SYSCLK
stm32f4 apparently has a '2nd' pll,

for SYSCLK I'm not too sure about that other than finding a way to measure it
There is something in the debug subsystem DWT something, that may help with an attempt to measure it.
Last edited by ag123 on Sun Jul 21, 2024 2:18 pm, edited 2 times in total.
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: HSI, HSE, PLL ???

Post by STM32ardui »

Is it really so simple ???

Just a normal blink sketch:

Code: Select all

#define LED   PC6           // LED ist gegen GND geschaltet
uint32_t      t = 0;
uint32_t      i = 1;

void setup() {
  pinMode(LED, OUTPUT);     

  Serial.begin(9600);
  delay(1000);
  Serial.printf("\n\n----- Blinktest auf STM32G0B1CBT6 -----\n");
}

void loop() {
  if (millis() - t > 29999) {
    t = millis();
    digitalWrite(LED, HIGH);
    delay(200);
    digitalWrite(LED, LOW);
    Serial.printf("I = %d \n",i);
    i++;
  }
}
Comparing to the timestamps ArduinoIDE adds, I can see, that HSI on my board is too fast. In 10 minutes there is a difference of 800 ms.

Code: Select all

14:40:31.740 -> I = 1 
14:50:30.967 -> I = 21

Now I place this function before setup():

Code: Select all

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  //Configure the main internal regulator output voltage
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  // Initializes the RCC Oscillators according to the specified parameters
  // in the RCC_OscInitTypeDef structure.
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  // Initializes the CPU, AHB and APB buses clocks
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
I don't call it from setup(), I only add it to the sketch.
Now the drift is much smaler:

Code: Select all

15:07:09.142 -> I = 1 
15:17:09.152 -> I = 21
15:27:09.140 -> I = 41 
15:37:09.136 -> I = 61
So I suppose, board is running now on HSE via PLL ...
Can someone more experienced like me confirm, that it is so simple to switch MCU from HSI to HSE directly from a sketch (without modifying headerfiles etc)?
Post Reply

Return to “General discussion”