BERGSONNE

Clocks

Every project runs at a named clock level — low, medium, high or max — and core_init() brings the clock up to it. The default on every Core is medium, not the chip’s maximum. The clock is set declaratively — coregen works out the PLL, voltage range and flash wait states for the level and emits the bring-up — but the LL clock API (ll_rcc) is right there in C when you need to retune it yourself. Use the Core / HAL / LL toggle at the top of the sidebar to switch between the declarative path and the raw ll_rcc calls.

Overview

core_init() sets up SYSCLK — the clock that drives the CPU and most peripherals — at the project’s clock level, then derives the peripheral bus clocks from it. You don’t pick a frequency in your loop; it’s decided at build time from the clock setting in config.json and the Core’s tile definition, and SYSCLK_HZ carries it into your code.

A couple of clocks run independently of SYSCLK so they survive sleep and faults: the watchdog’s low-speed internal oscillator (LSI, about 32 kHz; 37 kHz nominal on the L0 — see System) and the clock the Core wakes on after a stop mode (see Power).

Clock levels

Each Core defines four levels in its tile definition. Pick one with "clock" in config.json; leave it out (or write "default") for medium. A level that doesn’t exist stops the build with the list of valid ones.

Corelowmedium (default)highmax
L0MSI 1.05 MHz, range 3 (range 2 with I2C)MSI 2.1 MHz, range 2HSI16 16 MHz, range 1HSI16 ×4 ÷2 = 32 MHz, range 1, 1 WS
L4MSI 16 MHz (same as medium: USB needs ≥ 10 MHz)MSI 16 MHzMSI 48 MHz, 2 WSHSI16 ×10 ÷2 = 80 MHz, 4 WS
W5HSI16 16 MHz, range 2, 1 WS (no BLE)HSE 32 MHz, range 1HSE PLL 64 MHz, 1 WSHSE PLL 100 MHz, 3 WS
H5HSI 16 MHz (not CSI 4 MHz: USB needs APB2 ≥ 12 MHz)HSI 64 MHzHSI PLL 128 MHzHSI PLL 248 MHz

The L0, L4 and W5 levels were corrected against their reference manuals on 25 September 2026 (voltage ranges, flash wait states, PLL limits). All four Cores have passed the tests/hw-clock-levels bench test (the L4 and W5 on 25 September, the L0 on 26 September), and the H5 levels were measured on 26 September (64.08, 128.17 and 248.35 MHz). BLE and Thread on the W5 need medium or higher (the radio needs voltage range 1).

Clock sources

SYSCLK is built from one of a few oscillators. Which ones a Core offers depends on its MCU — see the matrix below.

  • HSI — high-speed internal RC oscillator. The safe default boot source; no external parts, always present.
  • HSE — external crystal. Precision timing (and USB-grade clocks) on Cores that fit one.
  • MSI / MSIS — multi-speed internal oscillator. Low-power and frequency-scalable; the basis for low-power run and stop modes.
  • PLL — multiplies a source up to the high SYSCLK frequencies (e.g. the W5’s 100 MHz max).

Configuring the clock

For almost every project, the clock is set in data, not code. The Core’s tile definition describes its oscillators, and the project’s config.json clock setting selects the level (see Clock levels; "default" is medium). At build time coregen’s PLL solver works out the dividers, voltage range and flash wait states for that target and emits core_clock_init(), which core_init() runs. Nothing to call — there’s no Tier 2 core_clock_* wrapper.

Need a non-default clock?
A custom frequency, a different source, or a runtime change drops to the LL layer — switch to LL to see the ll_rcc calls.
USB brings its own clock
On USB-capable Cores, core_init() also brings up the dedicated 48 MHz clock (HSI48) the USB peripheral needs — you don’t configure it separately. Trimming the clock down for battery life is the Power guide’s territory.

Cross-architecture support

The core_* contract is the same everywhere, but the clock tree is genuinely MCU-specific — different Cores offer different oscillators. That’s the one place “clocks” really varies across the family:

SourceL0M0+L4M4W5M33H5M33
HSI (internal RC)●●●●
HSE (external crystal)··●·
MSI / MSIS (low-power)●●··
CSI (low-power internal)···●
PLL (high-speed)●●●●

WCH (RISC-V) and Nordic (nRF54) Cores are in development — same contract, their own clock trees. See the implementation status for the full picture.

API reference

No Tier 2 clock API
The clock is set declaratively (see Configuring). The only Core-layer function is core_clock_init(), which coregen generates per project and core_init() calls for you (it’s listed under Power, whose header declares it). Switch to LL for the ll_rcc reference.