First, What Is It
- Clock: the "heartbeat" of the chip. Every block (CPU, UART, timers, Wi-Fi) works on a periodic signal — the faster the beat, the faster (and more power-hungry) the work.
- Clock tree: a distribution network that derives many peripheral clocks from a few source clocks (crystal / RC) via dividers and multipliers — like a power plant feeding substations and buildings.
- Boot sequence: the ordered steps from power-on to
main(): ROM boot code runs first, then the user firmware is loaded, the stack and clocks are initialized, and finally your program starts. - Why it matters: garbled UART output, dead peripherals, and abnormal low-power wake-ups are usually clock-related; boot flow and clock trees are also classic exam topics.
Breaking Down the Principle
1. Clock Sources
MCUs typically have several clock sources with different cost, accuracy, and power:
| Source | Accuracy | Features | Typical use |
|---|---|---|---|
| High-speed crystal (XTAL) | High | Needs external crystal, slower startup | System main clock, RF reference |
| Internal RC oscillator | Medium/low | No external parts, fast startup, drifts with temperature | Fast boot, low-power modes |
| Low-speed crystal (32.768 kHz) | High | Extremely low power | RTC, low-power timed wake-up |
| PLL | Depends on input | Multiplies a low frequency up | High main frequency |
In the Ai-Thinker-WB2 SDK, the BL602 uses a 40 MHz passive crystal (XTAL) and an internal RC32M as clock sources; the wl_ble_lp low-power example contains the clock-source switching logic.
2. Clock Distribution: Division and Gating
The high-frequency main clock cannot feed every peripheral directly:
- Division: lower the frequency for slow peripherals, e.g., a divided clock as the baud-rate base for UART or the counting base for timers.
- Gating: switch off the clock of unused peripherals — a key low-power technique. On the BL602, the clock/peripheral gating registers live in the SDK's
bl602_glb.h(e.g., theGLB_CGEN_S1AandGLB_CGEN_S2series); thewl_ble_lplow-power example toggles peripheral clocks through these registers, and the exact bit names are defined inbl602_glb.h.
3. Boot Sequence
In SDK examples, the beginning of main() is exactly this boot flow in miniature: board_init() → UART init (shell_init_with_task) → rfparam_init → create the app task → vTaskStartScheduler().
4. Reset Sources
A chip can reset for many reasons: power-on reset (POR), external reset pin (RST), watchdog reset (WDG), or software reset (e.g., bl_sys_reset_system()). Identifying the reset source is the first step when debugging "why did my program restart" — see the system control column (Software Reboot, Crash Debugging).
How the SDK Implements It
- Environment setup: SDK Introduction | Quick Start (Linux)
- Related pages: System Control Overview, Sleep Mode, Software Reboot
The clock-recovery code in the SDK low-power example shows the complete idea of "main frequency → divide down → gate peripheral clocks":
/* After low-power wake-up: drop the CPU to a low-power clock and keep only essential clocks */
static void set_low_clk_and_gate_clk(void)
{
/* Divide the system clock down to the low-power level */
/* Gating: keep only CPU/DMA/UART0/Flash etc., gate the rest */
/* BL602 clock/peripheral gating registers live in the SDK's bl602_glb.h
(e.g., the GLB_CGEN_S1A / GLB_CGEN_S2 series); exact bit names per bl602_glb.h */
}Common Exam & Interview Questions
Why do peripherals need their own clocks instead of using the CPU clock directly?
Different peripherals need different frequency and accuracy (e.g., UART needs a precise baud-rate base, timers need adjustable dividers), and clock gating is the key to low power — switching off unused clocks saves a lot of energy.
Why run ROM boot code before the user program?
ROM boot initializes the stack and basic clocks, then verifies and loads the user firmware from Flash, providing a uniform entry point — which is also why OTA upgrades can work after replacing the firmware.
How can clocks cause garbled UART output?
The baud rate is derived from a divided clock. If the clock source/divider changes without recomputing the baud rate, both ends sample at different rates and produce garbage — not restoring the clock after low-power wake-up is a common cause.
Why does RTC usually use a 32.768 kHz crystal?
32.768 kHz = 2^15 Hz, which divides exactly into a 1-second tick, and it consumes extremely little power — ideal for keeping time and timed wake-up when power is off.
What do PLL, divider, and clock gate each solve?
PLL multiplies to reach a higher main frequency; dividers step the frequency down to match peripherals; gates switch clocks on/off to save power. Together they form the clock tree.
Have questions?
For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

