Skip to content

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:

SourceAccuracyFeaturesTypical use
High-speed crystal (XTAL)HighNeeds external crystal, slower startupSystem main clock, RF reference
Internal RC oscillatorMedium/lowNo external parts, fast startup, drifts with temperatureFast boot, low-power modes
Low-speed crystal (32.768 kHz)HighExtremely low powerRTC, low-power timed wake-up
PLLDepends on inputMultiplies a low frequency upHigh main frequency

In the Bouffalo SDK you can see matching APIs: app_set_clock_source(CLOCK_SOURCE_PASSIVE) selects an external passive crystal (used by the wl_ble_lp low-power example), and the set_clock_source 1/2/3 command switches between RC / passive crystal / active crystal.

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. In the SDK's low-power example, registers like GLB_CGEN_* are such switches (e.g., GLB_CGEN_S1A_UART0 gates UART0).

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

The clock-recovery code in the SDK low-power example shows the complete idea of "main frequency → divide down → gate peripheral clocks":

c
/* After low-power wake-up: drop CPU to ~80 MHz and keep only essential clocks */
static void set_cpu_bclk_80M_and_gate_clk(void)
{
    GLB_Set_MCU_System_CLK_Div(0, 3);   /* Divide the system clock */
    CPU_Set_MTimer_CLK(ENABLE, BL_MTIMER_SOURCE_CLOCK_MCU_CLK, /* recalibrate timer clock */);

    /* Gating: keep only CPU/DMA/UART0/Flash etc., gate the rest */
    /* e.g., GLB_CGEN_S1A_UART0 = 1 keeps UART0, GLB_CGEN_S2_WIFI = 1 keeps Wi-Fi */
}

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

Released under the MIT License. Build Time 2026-09-11 14:52:23