Clock tree: where clocks come from and how they are divided
HSE, PLL and prescalers. Follow how the system clock, bus clocks and timer clocks are determined.
Clock sources
| Source | Characteristics |
|---|---|
| HSI | Internal RC, for example 16 MHz. Accuracy around 1% |
| HSE | External crystal, 8 to 25 MHz. Accurate |
| LSI / LSE | 32 kHz. Watchdog, RTC |
| PLL | Multiplies one of the sources above to a higher frequency |
Example: 100 MHz on an STM32F411
HSE 8 MHz → ÷M(8) = 1 MHz → ×N(200) = 200 MHz → ÷P(2) = SYSCLK 100 MHz
After that it is divided by the AHB, APB1 and APB2 prescalers. APB1 allows at most 50 MHz, so it gets ÷2.
The timer clock trap
If the APB prescaler is not 1, the timer clock is twice the APB clock. Even with APB1 at 50 MHz, TIM2 runs at 100 MHz. This is a common reason for a PWM frequency calculation being off by a factor of 2.
Flash wait states
When you raise the clock, Flash cannot keep up, so you have to add wait states. Get the order wrong (raise the clock first, add wait states later) and you get a hard fault immediately. The clock configuration view in CubeMX does this calculation and ordering for you.
The path a clock takes
HSI (internal RC) ─┐
HSE (external crystal) ─┼─> PLL (multiply) ─> SYSCLK ─> AHB divider ─> HCLK ─┬─> APB1 divider ─> timers, UART, I2C
└─> APB2 divider ─> ADC, SPI, fast timers
When the chip powers up it starts on the internal oscillator (HSI). The startup code or an initialisation function turns on the external crystal, raises the frequency with the PLL, and then switches the system clock over to the PLL.
Choosing a clock source
| Source | Accuracy | Use |
|---|---|---|
| Internal RC (HSI) | About 1% (varies with temperature) | Fewer parts, fast start-up |
| External crystal (HSE) | Tens of ppm | USB, CAN, accurate UART |
| Low-speed crystal (LSE, 32.768 kHz) | Tens of ppm | Clock (RTC), low-power timers |
UART characters start to break once the speed difference between the two ends exceeds about 2%. If both ends use an internal RC, the errors add up and it gets risky. CAN and USB need much higher accuracy, so a crystal is practically mandatory.
Example: 72 MHz from an 8 MHz crystal
HSE 8 MHz × PLL 9 = 72 MHz (SYSCLK)
AHB ÷1 → HCLK 72 MHz
APB1 ÷2 → PCLK1 36 MHz (because of this bus's maximum frequency)
APB2 ÷1 → PCLK2 72 MHz
RoadmapSee where this note sits in MCU Firmware→The rule that doubles the timer clock
On many MCUs, if the APB divider is not 1, the timer clock on that bus is twice the bus clock. In the example above APB1 is 36 MHz, but the timers on APB1 run at 72 MHz. If your PWM frequency comes out at twice the calculated value, you missed this rule.
Peripherals only work with their clock on
To save power, every peripheral clock is off at the start.
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // only after this can you write its registers
If you write a register and read back 0, the clock is off.
Before raising the speed: Flash wait time
Flash is not as fast as the CPU. When you raise the clock, you have to add wait states for fetching instructions from Flash. The order matters.
- Increase the Flash wait time first.
- Then raise the clock.
Do it the other way round and the CPU executes a misread instruction and faults immediately. When lowering the speed, use the opposite order.
How to check what the clock really is
- MCO pin: a feature that outputs an internal clock on a pin. Measure it directly with an oscilloscope.
- 1-second LED blink: make one second from the system tick and compare with a stopwatch.
- One UART character: send
0x55('U') and measure the bit width to get the real baud rate.
Problems that come up in practice
- The crystal does not oscillate: the load capacitor values are wrong or the traces are long. Add a start-up timeout and keep running on the internal oscillator if it fails.
- The clock constant in the code differs from reality: if
HSE_VALUEsays 8 MHz and the board carries a 25 MHz crystal, every timing is off by about 3×. - Slow after waking from low-power mode: after wake-up the chip is back on the internal oscillator. You have to configure the clocks again.