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.
| Core | low | medium (default) | high | max |
|---|---|---|---|---|
| L0 | MSI 1.05 MHz, range 3 (range 2 with I2C) | MSI 2.1 MHz, range 2 | HSI16 16 MHz, range 1 | HSI16 ×4 ÷2 = 32 MHz, range 1, 1 WS |
| L4 | MSI 16 MHz (same as medium: USB needs ≥ 10 MHz) | MSI 16 MHz | MSI 48 MHz, 2 WS | HSI16 ×10 ÷2 = 80 MHz, 4 WS |
| W5 | HSI16 16 MHz, range 2, 1 WS (no BLE) | HSE 32 MHz, range 1 | HSE PLL 64 MHz, 1 WS | HSE PLL 100 MHz, 3 WS |
| H5 | CSI 4 MHz | HSI 64 MHz, runs at 32 today (see below) | HSI PLL 128 MHz, runs at about 64 today | HSI PLL 248 MHz, runs at about 124 today |
The L0, L4 and W5 levels were corrected against their reference manuals on 25 September 2026 (voltage ranges, flash wait states, PLL limits); the L4 and W5 passed the tests/hw-clock-levels bench test at every level, and the L0 is awaiting its bench pass. BLE on the W5 needs medium or higher (the radio needs voltage range 1).
SYSCLK_HZ — delays, baud rates, PWM, I2C speed — is off by the same factor of two. The fix, with flash wait states that follow voltage scaling, is scheduled for the H5 session; until then treat the H5’s high and max figures as targets, not measurements.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.
ll_rcc calls.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:
| Source | L0M0+ | L4M4 | W5M33 | H5M33 |
|---|---|---|---|---|
| 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
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.
