diff --git a/boards/common/esp32/include/board_common.h b/boards/common/esp32/include/board_common.h index 61dca258da..3db6072fd1 100644 --- a/boards/common/esp32/include/board_common.h +++ b/boards/common/esp32/include/board_common.h @@ -36,6 +36,23 @@ extern "C" { #endif +/** + * @name External clock crystal frequency (MHz) + * + * Most boards use a 40MHz crystal, including all those based on Espressif's + * WROOM-32 and WROVER-32 modules. Those that don't, like the SparkFun ESP32 + * Thing (26MHz), must define ESP32_XTAL_FREQ appropriately in their board + * configuration. + * + * An obvious side effect of a mismatch is that the UART won't sync and the + * development terminal will show garbage instead of log output. + * @{ + */ +#ifndef ESP32_XTAL_FREQ +#define ESP32_XTAL_FREQ (40) +#endif +/** @} */ + /** * @name LED configuration (three predefined LEDs at maximum) * diff --git a/cpu/esp32/include/sdk_conf.h b/cpu/esp32/include/sdk_conf.h index 4f5ad4f1eb..79260b3315 100644 --- a/cpu/esp32/include/sdk_conf.h +++ b/cpu/esp32/include/sdk_conf.h @@ -66,6 +66,16 @@ extern "C" { #define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 80 #endif +/** + * ESP32 specific configuration + * + * Main clock crystal frequency (MHz). Zero means to auto-configure. + * This is configured at the board level, defaulting to 40. + */ +#ifndef CONFIG_ESP32_XTAL_FREQ +#define CONFIG_ESP32_XTAL_FREQ ESP32_XTAL_FREQ +#endif + #define CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES 100 #define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 diff --git a/cpu/esp32/startup.c b/cpu/esp32/startup.c index c1a34e16d5..b073a56d27 100644 --- a/cpu/esp32/startup.c +++ b/cpu/esp32/startup.c @@ -14,6 +14,7 @@ * @brief Implementation of the CPU initialization * * @author Gunar Schorcht + * @author Jens Alfke * @} */ @@ -88,6 +89,7 @@ extern void esp_panic_wdt_stop (void); extern void spi_ram_init(void); extern void spi_ram_heap_init(void); extern uint32_t hwrand (void); +extern void bootloader_clock_configure(void); /* forward declarations */ static void system_init(void); @@ -194,6 +196,12 @@ static void IRAM system_clk_init (void) rtc_config_t rtc_cfg = RTC_CONFIG_DEFAULT(); rtc_init_module(rtc_cfg); + /* configure main crystal frequency if necessary */ + if (CONFIG_ESP32_XTAL_FREQ != RTC_XTAL_FREQ_AUTO + && CONFIG_ESP32_XTAL_FREQ != rtc_clk_xtal_freq_get()) { + bootloader_clock_configure(); + } + /* set FAST_CLK to internal low power clock of 8 MHz */ rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M); diff --git a/cpu/esp32/vendor/esp-idf/esp_funcs.c b/cpu/esp32/vendor/esp-idf/esp_funcs.c index fbc5dd3a93..9f929d0756 100644 --- a/cpu/esp32/vendor/esp-idf/esp_funcs.c +++ b/cpu/esp32/vendor/esp-idf/esp_funcs.c @@ -545,3 +545,48 @@ void sc_ack_send_stop(void) NOT_SUPPORTED(); } #endif + +/* + * source: /path/to/esp-idf/components/bootloader_support/src/bootloader_clock.c + */ +void bootloader_clock_configure(void) +{ + // ROM bootloader may have put a lot of text into UART0 FIFO. + // Wait for it to be printed. + // This is not needed on power on reset, when ROM bootloader is running at + // 40 MHz. But in case of TG WDT reset, CPU may still be running at >80 MHZ, + // and will be done with the bootloader much earlier than UART FIFO is empty. + uart_tx_wait_idle(0); + + /* Set CPU to 80MHz. Keep other clocks unmodified. */ + rtc_cpu_freq_t cpu_freq = RTC_CPU_FREQ_80M; +#ifndef RIOT_VERSION + /* On ESP32 rev 0, switching to 80MHz if clock was previously set to + * 240 MHz may cause the chip to lock up (see section 3.5 of the errata + * document). For rev. 0, switch to 240 instead if it was chosen in + * menuconfig. + */ + uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG); + if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 && + CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240) { + cpu_freq = RTC_CPU_FREQ_240M; + } +#endif + + rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); + clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ; + clk_cfg.cpu_freq = cpu_freq; + clk_cfg.slow_freq = rtc_clk_slow_freq_get(); + clk_cfg.fast_freq = rtc_clk_fast_freq_get(); + rtc_clk_init(clk_cfg); + /* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable + * it here. Usually it needs some time to start up, so we amortize at least + * part of the start up time by enabling 32k XTAL early. + * App startup code will wait until the oscillator has started up. + */ +#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL + if (!rtc_clk_32k_enabled()) { + rtc_clk_32k_bootstrap(CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES); + } +#endif +}