Skip to content

soc_esp32::cpu_clk

Raising the CPU clock from the 80 MHz boot default to 240 MHz.

The stock second-stage bootloader espflash writes leaves the ESP32 at 80 MHz and expects the application to raise the clock during its own init (see [crate::rtc::DEFAULT_CPU_HZ]). FlintOS did not, so everything — including the Wi-Fi blob, which Espressif builds and times against 240 MHz — ran at a third of speed. This closes that: it is FlintOS’s esp_clk_init.

A faithful port of esp-idf’s rtc_clk_cpu_freq_set_config

Section titled “A faithful port of esp-idf’s rtc_clk_cpu_freq_set_config”

Going 80 → 240 MHz is not one register write. The 80 MHz clock runs the CPU off a 320 MHz BBPLL; 240 MHz needs a 480 MHz BBPLL, and the PLL cannot be retuned while the CPU is running from it. So the sequence, taken from components/esp_hw_support/port/esp32/rtc_clk.c at v4.4, is: drop the CPU to the 40 MHz crystal, power the 320 MHz PLL down, bring the 480 MHz PLL up (analog REGI2C writes with the divisor constants for a 40 MHz crystal), then point the CPU at it divided by two. Every constant here is transcribed from that file; the values are the chip’s, not ours to choose.

The analog PLL writes go through the ROM’s rom_i2c_writeReg, and the µs delays through the ROM’s ets_delay_us (paced by g_ticks_per_us, which ets_update_cpu_frequency keeps in step with the CPU across the switch) — the same primitives esp-idf uses, called at their fixed addresses the way [crate::appcpu] calls the cache ROM routines.

The APB clock stays at 80 MHz on the ESP32 whatever the CPU runs at (see [crate::APB_HZ]), so the UART console and the timer groups are unaffected — only the CPU speeds up. The boot path measures the CPU frequency against the RTC slow clock after this runs, so it reports 240 MHz on its own.

unsafe fn set_240mhz()

Raise the CPU to 240 MHz.

Call once, early in boot, on the bootstrap core, before the frequency is measured and before any second core exists — it is not synchronised.

Reconfigures the clock tree and calls ROM routines. Must run single-core with interrupts effectively quiet, before the radio (the other BBPLL user) is brought up.