1. Topic

STM32 clock tree: HSI/HSE, PLL, SYSCLK, HCLK, APB1/APB2, kernel clocks, prescalers and actual peripheral frequencies. Main idea: without knowing a peripheral clock, you cannot understand its actual behavior.

2. Why this matters in a project

The clock tree affects UART/RS-485 baud rate, CAN/FDCAN bit timing, ADC sampling time, TIM/PWM period, input capture timestamps, HIL timing and watchdog timeout.

3. Theory

Clock tree:

text
HSI/HSE/PLL -> SYSCLK -> AHB -> HCLK -> APB1/APB2 -> PCLKx -> peripherals

Clock sources:

  • HSI is an internal RC oscillator: convenient, but less accurate.
  • HSE is an external crystal/clock, preferred for CAN/USB/accurate UART timing.
  • LSI/LSE are low-frequency sources used for watchdogs and RTC.

Timer formulas:

text
timer_counter_freq = TIMxCLK / (PSC + 1)
update_freq = timer_counter_freq / (ARR + 1)

A common STM32 trap: when the APB prescaler > 1, TIMxCLK is often 2 * PCLKx. Consult the reference manual for the exact series. UART baud rate is derived from a peripheral/kernel clock. CAN/FDCAN needs the clock, prescaler, time quanta, sample point and SJW. ADC behavior depends on its kernel clock, sampling time and source impedance. CubeMX is a useful calculator rather than a source of requirements. Document the requirements and final clock frequencies.

4. Common mistakes

  1. Assuming SYSCLK equals every peripheral frequency.
  2. Forgetting __HAL_RCC_xxx_CLK_ENABLE().
  3. Setting HSE_VALUE incorrectly.
  4. Ignoring Flash latency and voltage scaling.
  5. Using HAL_GetTick() for precise measurements.
  6. Failing to document TIMxCLK/UARTCLK/ADCCLK/FDCANCLK.

5. Practical task

Create STM32_CLOCK_TREE_POLICY.md:

markdown
# STM32 clock tree policy
Required:
- MCU exact part number
- HSE/HSI frequency
- PLL configuration
- SYSCLK, HCLK, PCLK1/PCLK2
- TIMxCLK for every timer
- UART kernel clock
- ADC kernel clock
- CAN/FDCAN kernel clock
- SysTick, RTC, watchdog source

Add a runtime clock command:

c
printf("SystemCoreClock=%lu\r\n", SystemCoreClock);
printf("HCLK=%lu\r\n", HAL_RCC_GetHCLKFreq());
printf("PCLK1=%lu\r\n", HAL_RCC_GetPCLK1Freq());
printf("PCLK2=%lu\r\n", HAL_RCC_GetPCLK2Freq());

6. Further reading and experiments

STM32 HAL RCC documentation, the selected series reference manual, CubeMX Clock Configuration and STM32 TIM documentation.

PCLK is 40 MHz and the APB prescaler > 1. Can you assert TIMxCLK = 80 MHz without the reference manual?

Exercise

For documented TIMxCLK = 80 MHz, PSC = 79 and ARR = 999. Find the counter and update frequencies. What happens if PSC is accidentally 80?

Self-check criteria: Show the +1 divisors, units and the result of the incorrect PSC.

Show the supplied answer

counter = 80000000/(79+1) = 1000000 Hz; update = 1000000/(999+1) = 1000 Hz. With PSC=80, update = 80000000/(81×1000) ≈ 987.654 Hz. Use PSC+1 and ARR+1.