From 24d6dcb829122005a25893c2faea76b786ff7482 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 13 Mar 2024 16:58:13 +0800 Subject: [PATCH] feat(esp32c5mp): add system related components --- .../src/bootloader_flash_config_esp32c5.c | 22 + .../src/bootloader_clock_init.c | 12 +- .../src/bootloader_console.c | 10 + .../bootloader_support/src/bootloader_init.c | 2 +- .../bootloader_support/src/bootloader_mem.c | 6 +- .../src/bootloader_random_esp32c5.c | 4 +- .../src/bootloader_utility.c | 6 + .../src/esp32c5/bootloader_esp32c5.c | 6 + .../bootloader_support/src/flash_encrypt.c | 2 +- .../port/esp32c5/CMakeLists.txt | 13 +- .../esp_hw_support/port/esp32c5/Kconfig.rtc | 7 +- .../esp_hw_support/port/esp32c5/chip_info.c | 3 +- .../port/esp32c5/cpu_region_protect.c | 189 +++++++- .../port/esp32c5/esp_clk_tree.c | 4 +- .../esp_hw_support/port/esp32c5/pmu_param.c | 8 +- .../esp_hw_support/port/esp32c5/rtc_clk.c | 134 +++++- .../port/esp32c5/rtc_clk_init.c | 6 +- .../esp_hw_support/port/esp32c5/rtc_time.c | 2 - components/esp_hw_support/sleep_clock.c | 4 +- components/esp_system/Kconfig | 4 +- components/esp_system/fpga_overrides_clk.c | 2 + components/esp_system/ld/esp32c5/mp/.gitkeep | 0 .../esp_system/ld/esp32c5/mp/memory.ld.in | 139 ++++++ .../esp_system/ld/esp32c5/mp/sections.ld.in | 442 ++++++++++++++++++ components/esp_system/port/soc/esp32c5/clk.c | 54 ++- .../port/soc/esp32c5/system_internal.c | 25 + .../riscv/include/freertos/portmacro.h | 17 +- 27 files changed, 1067 insertions(+), 56 deletions(-) delete mode 100644 components/esp_system/ld/esp32c5/mp/.gitkeep diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c index a87d800dfc..46e909ace6 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c @@ -11,7 +11,14 @@ #include "esp_log.h" #include "esp_rom_gpio.h" #include "esp32c5/rom/spi_flash.h" +#include "esp32c5/rom/efuse.h" #include "soc/gpio_periph.h" +#include "soc/io_mux_reg.h" +// TODO: IDF-9197 +#if CONFIG_IDF_TARGET_ESP32C5_MP_VERSION +#include "esp_rom_efuse.h" +#include "soc/efuse_reg.h" +#endif #include "soc/spi_reg.h" #include "soc/spi_mem_reg.h" #include "soc/soc_caps.h" @@ -24,6 +31,7 @@ #include "hal/mmu_ll.h" #include "hal/cache_hal.h" #include "hal/cache_ll.h" +#include "hal/clk_tree_ll.h" void bootloader_flash_update_id() { @@ -199,6 +207,20 @@ static void bootloader_spi_flash_resume(void) esp_err_t bootloader_init_spi_flash(void) { +// TODO: IDF-9197 +#if CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + // On ESP32C5, MSPI source clock's default HS divider leads to 120MHz, which is unusable before calibration + // Therefore, before switching SOC_ROOT_CLK to HS, we need to set MSPI source clock HS divider to make it run at + // 80MHz after the switch. PLL = 480MHz, so divider is 6. + clk_ll_mspi_fast_set_hs_divider(6); +#elif CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION + /* TODO: [ESP32C5] IDF-8649 temporary use xtal clock source, + need to change back SPLL(480M) and set divider to 6 to use the 80M MSPI, + and we need to check flash freq before restart as well */ + clk_ll_mspi_fast_set_divider(1); + clk_ll_mspi_fast_set_src(MSPI_CLK_SRC_XTAL); +#endif + bootloader_init_flash_configure(); bootloader_spi_flash_resume(); bootloader_flash_unlock(); diff --git a/components/bootloader_support/src/bootloader_clock_init.c b/components/bootloader_support/src/bootloader_clock_init.c index c42d885c2e..4f70c87ee7 100644 --- a/components/bootloader_support/src/bootloader_clock_init.c +++ b/components/bootloader_support/src/bootloader_clock_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -66,7 +66,7 @@ __attribute__((weak)) void bootloader_clock_configure(void) } #endif -#if CONFIG_IDF_TARGET_ESP32C6 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-5781 Some of esp32c6 SOC_RTC_FAST_CLK_SRC_XTAL_D2 rtc_fast clock has timing issue // Force to use SOC_RTC_FAST_CLK_SRC_RC_FAST since 2nd stage bootloader clk_cfg.fast_clk_src = SOC_RTC_FAST_CLK_SRC_RC_FAST; @@ -81,14 +81,6 @@ __attribute__((weak)) void bootloader_clock_configure(void) rtc_clk_init(clk_cfg); } -#if CONFIG_IDF_TARGET_ESP32C5 - /* TODO: [ESP32C5] IDF-8649 temporary use xtal clock source, - need to change back SPLL(480M) and set divider to 6 to use the 80M MSPI, - and we need to check flash freq before restart as well */ - clk_ll_mspi_fast_set_divider(1); - clk_ll_mspi_fast_set_src(MSPI_CLK_SRC_XTAL); -#endif - /* 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. diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c index da047055a9..14b9546f3f 100644 --- a/components/bootloader_support/src/bootloader_console.c +++ b/components/bootloader_support/src/bootloader_console.c @@ -25,6 +25,9 @@ #include "esp_rom_uart.h" #include "esp_rom_sys.h" #include "esp_rom_caps.h" +#if CONFIG_IDF_TARGET_ESP32C5 +#include "soc/pcr_reg.h" +#endif #ifdef CONFIG_ESP_CONSOLE_NONE void bootloader_console_init(void) @@ -85,6 +88,13 @@ void bootloader_console_init(void) #if ESP_ROM_UART_CLK_IS_XTAL clock_hz = (uint32_t)rtc_clk_xtal_freq_get() * MHZ; // From esp32-s3 on, UART clk source is selected to XTAL in ROM #endif +#if CONFIG_IDF_TARGET_ESP32C5_MP_VERSION +#if CONFIG_IDF_ENV_FPGA + clock_hz = CONFIG_XTAL_FREQ * MHZ; +#else + clock_hz = REG_GET_FIELD(PCR_SYSCLK_CONF_REG, PCR_CLK_XTAL_FREQ) * MHZ; +#endif // CONFIG_IDF_ENV_FPGA +#endif // CONFIG_IDF_TARGET_ESP32C5_MP_VERSION esp_rom_uart_set_clock_baudrate(uart_num, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); } #endif // CONFIG_ESP_CONSOLE_UART diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 796417016f..49a096e66c 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/bootloader_support/src/bootloader_mem.c b/components/bootloader_support/src/bootloader_mem.c index 222f870318..e329d30405 100644 --- a/components/bootloader_support/src/bootloader_mem.c +++ b/components/bootloader_support/src/bootloader_mem.c @@ -16,7 +16,7 @@ #include "hal/apm_hal.h" #endif -#if CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8615 Remove the workaround when APM supported on C5! +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION // TODO: IDF-8615 Remove the workaround when APM supported on C5! #include "soc/hp_apm_reg.h" #include "soc/lp_apm_reg.h" #include "soc/lp_apm0_reg.h" @@ -36,7 +36,7 @@ void bootloader_init_mem(void) apm_hal_apm_ctrl_filter_enable_all(false); #endif -#if CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8615 Remove the workaround when APM supported on C5! +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION // TODO: IDF-8615 Remove the workaround when APM supported on C5! // disable apm filter REG_WRITE(LP_APM_FUNC_CTRL_REG, 0); REG_WRITE(LP_APM0_FUNC_CTRL_REG, 0); @@ -45,6 +45,6 @@ void bootloader_init_mem(void) #ifdef CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE // protect memory region - esp_cpu_configure_region_protection(); + esp_cpu_configure_region_protection(); // TODO: [ESP32C5] IDF-8833 PSRAM support write #endif } diff --git a/components/bootloader_support/src/bootloader_random_esp32c5.c b/components/bootloader_support/src/bootloader_random_esp32c5.c index 22dff32368..a009afd308 100644 --- a/components/bootloader_support/src/bootloader_random_esp32c5.c +++ b/components/bootloader_support/src/bootloader_random_esp32c5.c @@ -12,12 +12,12 @@ void bootloader_random_enable(void) { - // TODO: [ESP32C5] IDF-8626 +// TODO: [ESP32C5] IDF-8626, IDF-9197 ESP_EARLY_LOGW("bootloader_random", "bootloader_random_enable() has not been implemented on C5 yet"); } void bootloader_random_disable(void) { - // TODO: [ESP32C5] IDF-8626 +// TODO: [ESP32C5] IDF-8626, IDF-9197 ESP_EARLY_LOGW("bootloader_random", "bootloader_random_disable() has not been implemented on C5 yet"); } diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 7aad0fa5b5..7dc5593e79 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -645,6 +645,12 @@ static void load_image(const esp_image_metadata_t *image_data) #endif // CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER if (!flash_encryption_enabled) { +#if CONFIG_IDF_TARGET_ESP32C5 + // TODO: [ESP32C5] IDF-8622 find a more proper place for these codes + REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH); + REG_SET_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); + REG_CLR_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); +#endif err = esp_flash_encrypt_contents(); if (err != ESP_OK) { ESP_LOGE(TAG, "Encryption flash contents failed (%d)", err); diff --git a/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c b/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c index 94ad7a3f01..1b82b0312f 100644 --- a/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c +++ b/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c @@ -13,6 +13,7 @@ #include "esp_rom_uart.h" #include "esp_rom_sys.h" #include "esp_rom_spiflash.h" +#include "soc/soc_caps.h" #include "soc/gpio_sig_map.h" #include "soc/io_mux_reg.h" #include "soc/assist_debug_reg.h" @@ -41,7 +42,9 @@ #include "soc/lp_wdt_reg.h" #include "hal/efuse_hal.h" #include "hal/lpwdt_ll.h" +#if SOC_MODEM_CLOCK_SUPPORTED #include "modem/modem_lpcon_reg.h" +#endif static const char *TAG = "boot.esp32c5"; @@ -85,12 +88,15 @@ static void bootloader_super_wdt_auto_feed(void) static inline void bootloader_hardware_init(void) { /* Enable analog i2c master clock */ +#if SOC_MODEM_CLOCK_SUPPORTED SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN); SET_PERI_REG_MASK(MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M); +#endif } static inline void bootloader_ana_reset_config(void) { +// TODO: IDF-9197 // TODO: [ESP32C5] IDF-8650 //Enable super WDT reset. // bootloader_ana_super_wdt_reset_config(true); diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 27f10317cb..2994ac1b35 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_hw_support/port/esp32c5/CMakeLists.txt b/components/esp_hw_support/port/esp32c5/CMakeLists.txt index ca13f73723..39fe4c5d06 100644 --- a/components/esp_hw_support/port/esp32c5/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c5/CMakeLists.txt @@ -6,17 +6,18 @@ set(srcs "rtc_clk_init.c" "chip_info.c" ) -# TODO: [ESP32C5] IDF-8667 -if(IDF_TARGET STREQUAL "esp32c5") - list(REMOVE_ITEM srcs "pmu_init.c" - "pmu_param.c") -endif() - if(NOT BOOTLOADER_BUILD) list(APPEND srcs "sar_periph_ctrl.c" "esp_crypto_lock.c") endif() +# TODO: [ESP32C5] IDF-8667 +if(IDF_TARGET STREQUAL "esp32c5") + list(REMOVE_ITEM srcs "pmu_init.c" + "pmu_param.c" + "sar_periph_ctrl.c") +endif() + add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") diff --git a/components/esp_hw_support/port/esp32c5/Kconfig.rtc b/components/esp_hw_support/port/esp32c5/Kconfig.rtc index fb911adf30..bb758061ec 100644 --- a/components/esp_hw_support/port/esp32c5/Kconfig.rtc +++ b/components/esp_hw_support/port/esp32c5/Kconfig.rtc @@ -1,9 +1,14 @@ choice RTC_CLK_SRC prompt "RTC clock source" - default RTC_CLK_SRC_INT_RC32K + # TODO: IDF-9197 + default RTC_CLK_SRC_INT_RC if IDF_TARGET_ESP32C5_MP_VERSION + default RTC_CLK_SRC_INT_RC32K if IDF_TARGET_ESP32C5_BETA3_VERSION help Choose which clock is used as RTC clock source. + config RTC_CLK_SRC_INT_RC + depends on IDF_TARGET_ESP32C5_MP_VERSION + bool "Internal 136kHz RC oscillator" config RTC_CLK_SRC_EXT_CRYS bool "External 32kHz crystal" select ESP_SYSTEM_RTC_EXT_XTAL diff --git a/components/esp_hw_support/port/esp32c5/chip_info.c b/components/esp_hw_support/port/esp32c5/chip_info.c index 04b7ba1113..b0e02bae66 100644 --- a/components/esp_hw_support/port/esp32c5/chip_info.c +++ b/components/esp_hw_support/port/esp32c5/chip_info.c @@ -6,6 +6,7 @@ #include #include "esp_chip_info.h" +#include "soc/soc_caps.h" #include "hal/efuse_hal.h" void esp_chip_info(esp_chip_info_t *out_info) @@ -14,5 +15,5 @@ void esp_chip_info(esp_chip_info_t *out_info) out_info->model = CHIP_ESP32C5; out_info->revision = efuse_hal_chip_revision(); out_info->cores = 1; - out_info->features = CHIP_FEATURE_WIFI_BGN | CHIP_FEATURE_BLE; + out_info->features = CHIP_FEATURE_WIFI_BGN | CHIP_FEATURE_BLE | CHIP_FEATURE_IEEE802154; } diff --git a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c index 807cc90abf..17397207fa 100644 --- a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c @@ -24,7 +24,194 @@ #define CONDITIONAL_RWX RWX #endif +// TODO: IDF-9197 +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION void esp_cpu_configure_region_protection(void) { -// TODO: [ESP32C5] IDF-8833 + // TODO: [ESP32C5] IDF-8833 } + +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION +static void esp_cpu_configure_invalid_regions(void) +{ + const unsigned PMA_NONE = PMA_L | PMA_EN; + __attribute__((unused)) const unsigned PMA_RW = PMA_L | PMA_EN | PMA_R | PMA_W; + __attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X; + __attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X; + + // 1. Gap at bottom of address space + PMA_ENTRY_SET_TOR(0, SOC_DEBUG_LOW, PMA_TOR | PMA_NONE); + + // 2. Gap between debug region & IROM + PMA_ENTRY_SET_TOR(1, SOC_DEBUG_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE); + + // 3. Gap between ROM & RAM + PMA_ENTRY_SET_TOR(3, SOC_DROM_MASK_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(4, SOC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 4. Gap between DRAM and I_Cache + PMA_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE); + + // 5. Gap between D_Cache & LP_RAM + PMA_ENTRY_SET_TOR(7, SOC_DROM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(8, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 6. Gap between LP memory & peripheral addresses + PMA_ENTRY_SET_TOR(9, SOC_RTC_IRAM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(10, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE); + + // 7. End of address space + PMA_ENTRY_SET_TOR(11, SOC_PERIPHERAL_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(12, UINT32_MAX, PMA_TOR | PMA_NONE); +} + +void esp_cpu_configure_region_protection(void) +{ + // ROM has configured the MSPI region with RX permission, we should add W attribute for psram + PMA_ENTRY_SET_NAPOT(0, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X); + return; + /* Notes on implementation: + * + * 1) Note: ESP32-C6 CPU doesn't support overlapping PMP regions + * + * 2) ESP32-C6 supports 16 PMA regions so we use this feature to block all the invalid address ranges + * + * 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range) + * entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries + * which can be used to provide more granular access + * + * 4) Entries are grouped in order with some static asserts to try and verify everything is + * correct. + */ + + /* There are 4 configuration scenarios for SRAM + * + * 1. Bootloader build: + * - We cannot set the lock bit as we need to reconfigure it again for the application. + * We configure PMP to cover entire valid IRAM and DRAM range. + * + * 2. Application build with CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT enabled + * - We split the SRAM into IRAM and DRAM such that IRAM region cannot be written to + * and DRAM region cannot be executed. We use _iram_end and _data_start markers to set the boundaries. + * We also lock these entries so the R/W/X permissions are enforced even for machine mode + * + * 3. Application build with CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT disabled + * - The IRAM-DRAM split is not enabled so we just need to ensure that access to only valid address ranges are successful + * so for that we set PMP to cover entire valid IRAM and DRAM region. + * We also lock these entries so the R/W/X permissions are enforced even for machine mode + * + * 4. CPU is in OCD debug mode + * - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM. + * We set PMP to cover entire valid IRAM and DRAM region. + * We also lock these entries so the R/W/X permissions are enforced even for machine mode + */ + const unsigned NONE = PMP_L; + const unsigned R = PMP_L | PMP_R; + const unsigned RW = PMP_L | PMP_R | PMP_W; + const unsigned RX = PMP_L | PMP_R | PMP_X; + const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X; + + // + // Configure all the invalid address regions using PMA + // + esp_cpu_configure_invalid_regions(); + + // + // Configure all the valid address regions using PMP + // + + // 1. Debug region + const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_DEBUG_LOW, SOC_DEBUG_HIGH); + PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RWX); + _Static_assert(SOC_DEBUG_LOW < SOC_DEBUG_HIGH, "Invalid CPU debug region"); + + // 2.1 I-ROM + PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); + PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX); + _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I-ROM region"); + + // 2.2 D-ROM + PMP_ENTRY_SET(3, SOC_DROM_MASK_LOW, NONE); + PMP_ENTRY_SET(4, SOC_DROM_MASK_HIGH, PMP_TOR | R); + _Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region"); + + if (esp_cpu_dbgr_is_attached()) { + // Anti-FI check that cpu is really in ocd mode + ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached()); + + // 5. IRAM and DRAM + // const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH); + // PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | RWX); + // _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); + PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX); + _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); + } else { +#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD + extern int _iram_end; + // 5. IRAM and DRAM + /* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits + * Bootloader might have given extra permissions and those won't be cleared + */ + PMP_ENTRY_CFG_RESET(5); + PMP_ENTRY_CFG_RESET(6); + PMP_ENTRY_CFG_RESET(7); + PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(6, (int)&_iram_end, PMP_TOR | RX); + PMP_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW); +#else + // 5. IRAM and DRAM + // const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH); + // PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | CONDITIONAL_RWX); + // _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); + PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX); + _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); +#endif + } + + // 4. I_Cache (flash) + const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH); + PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | RX); + _Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I_Cache region"); + + // 5. D_Cache (flash) + const uint32_t pmpaddr9 = PMPADDR_NAPOT(SOC_DROM_LOW, SOC_DROM_HIGH); + PMP_ENTRY_SET(9, pmpaddr9, PMP_NAPOT | R); + _Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid D_Cache region"); + + // 6. LP memory +#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD + extern int _rtc_text_end; + /* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits + * Bootloader might have given extra permissions and those won't be cleared + */ + PMP_ENTRY_CFG_RESET(10); + PMP_ENTRY_CFG_RESET(11); + PMP_ENTRY_CFG_RESET(12); + PMP_ENTRY_CFG_RESET(13); + PMP_ENTRY_SET(10, SOC_RTC_IRAM_LOW, NONE); +#if CONFIG_ULP_COPROC_RESERVE_MEM + // First part of LP mem is reserved for coprocessor + PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW + CONFIG_ULP_COPROC_RESERVE_MEM, PMP_TOR | RW); +#else // CONFIG_ULP_COPROC_RESERVE_MEM + // Repeat same previous entry, to ensure next entry has correct base address (TOR) + PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE); +#endif // !CONFIG_ULP_COPROC_RESERVE_MEM + PMP_ENTRY_SET(12, (int)&_rtc_text_end, PMP_TOR | RX); + PMP_ENTRY_SET(13, SOC_RTC_IRAM_HIGH, PMP_TOR | RW); +#else + const uint32_t pmpaddr10 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH); + PMP_ENTRY_SET(10, pmpaddr10, PMP_NAPOT | CONDITIONAL_RWX); + _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region"); +#endif + + + // 7. Peripheral addresses + const uint32_t pmpaddr14 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH); + PMP_ENTRY_SET(14, pmpaddr14, PMP_NAPOT | RW); + _Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region"); +} +#endif // CONFIG_IDF_TARGET_ESP32C5_MP_VERSION diff --git a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c index f578ee3b15..0d34304800 100644 --- a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c @@ -19,7 +19,7 @@ static const char *TAG = "esp_clk_tree"; esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { - // TODO: [ESP32C5] IDF-8642 + // TODO: [ESP32C5] IDF-8642 check again for MP version ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); ESP_RETURN_ON_FALSE(precision < ESP_CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); @@ -38,9 +38,11 @@ uint32_t *freq_value) case SOC_MOD_CLK_PLL_F240M: clk_src_freq = CLK_LL_PLL_240M_FREQ_MHZ * MHZ; break; +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION case SOC_MOD_CLK_RTC_FAST: clk_src_freq = 20 * MHZ; break; +#endif case SOC_MOD_CLK_SPLL: clk_src_freq = CLK_LL_PLL_480M_FREQ_MHZ * MHZ; break; diff --git a/components/esp_hw_support/port/esp32c5/pmu_param.c b/components/esp_hw_support/port/esp32c5/pmu_param.c index 3a8d6aacf1..8d1ef19b7b 100644 --- a/components/esp_hw_support/port/esp32c5/pmu_param.c +++ b/components/esp_hw_support/port/esp32c5/pmu_param.c @@ -367,6 +367,12 @@ const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pm # define PMU_SLOW_CLK_USE_EXT_XTAL (0) #endif +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION +#define PMU_LP_DEFAULT_XPD_RC32K (1) +#else +#define PMU_LP_DEFAULT_XPD_RC32K (0) +#endif + #define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \ .dig_power = { \ .mem_dslp = 0, \ @@ -374,7 +380,7 @@ const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pm }, \ .clk_power = { \ .xpd_xtal32k = PMU_SLOW_CLK_USE_EXT_XTAL, \ - .xpd_rc32k = 1, \ + .xpd_rc32k = PMU_LP_DEFAULT_XPD_RC32K, \ .xpd_fosc = 1, \ .pd_osc = 0 \ } \ diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk.c b/components/esp_hw_support/port/esp32c5/rtc_clk.c index ca9266eae4..c44ccb9b31 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c5/rtc_clk.c @@ -12,6 +12,7 @@ #include "sdkconfig.h" #include "esp32c5/rom/rtc.h" #include "soc/rtc.h" +#include "soc/soc_caps.h" #include "esp_private/rtc_clk.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" @@ -21,11 +22,13 @@ #include "soc/lp_aon_reg.h" #include "esp_private/sleep_event.h" +#if SOC_MODEM_CLOCK_SUPPORTED #ifdef BOOTLOADER_BUILD #include "hal/modem_lpcon_ll.h" #else #include "esp_private/esp_modem_clock.h" #endif +#endif static const char *TAG = "rtc_clk"; @@ -114,7 +117,9 @@ soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) uint32_t rtc_clk_slow_freq_get_hz(void) { switch (rtc_clk_slow_src_get()) { - // case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX; +#if CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX; +#endif case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX; case SOC_RTC_SLOW_CLK_SRC_RC32K: return SOC_CLK_RC32K_FREQ_APPROX; case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: return SOC_CLK_OSC_SLOW_FREQ_APPROX; @@ -146,6 +151,7 @@ static void rtc_clk_bbpll_enable(void) static void rtc_clk_enable_i2c_ana_master_clock(bool enable) { +#if SOC_MODEM_CLOCK_SUPPORTED #ifdef BOOTLOADER_BUILD modem_lpcon_ll_enable_i2c_master_clock(&MODEM_LPCON, enable); #else @@ -155,6 +161,7 @@ static void rtc_clk_enable_i2c_ana_master_clock(bool enable) modem_clock_module_disable(PERIPH_ANA_I2C_MASTER_MODULE); } #endif +#endif } static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq) @@ -168,7 +175,9 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq) clk_ll_bbpll_set_config(pll_freq, xtal_freq); /* WAIT CALIBRATION DONE */ while(!regi2c_ctrl_ll_bbpll_calibration_is_done()); +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION esp_rom_delay_us(10); // wait for true stop // TODO: check this +#endif /* BBPLL CALIBRATION STOP */ regi2c_ctrl_ll_bbpll_calibration_stop(); rtc_clk_enable_i2c_ana_master_clock(false); @@ -182,6 +191,7 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq) */ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION /* Configure clk mspi fast to XTAL*/ clk_ll_mspi_fast_set_src(MSPI_CLK_SRC_XTAL); clk_ll_mspi_fast_set_divider(1); @@ -190,11 +200,17 @@ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) clk_ll_ahb_set_divider(div); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); clk_ll_bus_update(); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + clk_ll_ahb_set_ls_divider(div); + clk_ll_cpu_set_ls_divider(div); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); +#endif esp_rom_set_cpu_ticks_per_us(cpu_freq); } static void rtc_clk_cpu_freq_to_8m(void) { +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION /* Configure clk mspi fast to XTAL*/ clk_ll_mspi_fast_set_src(MSPI_CLK_SRC_XTAL); clk_ll_mspi_fast_set_divider(1); @@ -203,6 +219,11 @@ static void rtc_clk_cpu_freq_to_8m(void) clk_ll_ahb_set_divider(1); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); clk_ll_bus_update(); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + clk_ll_ahb_set_ls_divider(1); + clk_ll_cpu_set_ls_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); +#endif esp_rom_set_cpu_ticks_per_us(20); } @@ -213,6 +234,7 @@ static void rtc_clk_cpu_freq_to_8m(void) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION rtc_cpu_freq_config_t cfg; rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &cfg); // Set AHB always be 40MHz @@ -225,6 +247,11 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) /* Configure clk mspi fast to 80m*/ clk_ll_mspi_fast_set_divider(6); clk_ll_mspi_fast_set_src(MSPI_CLK_SRC_SPLL); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + clk_ll_cpu_set_hs_divider(CLK_LL_PLL_480M_FREQ_MHZ / cpu_freq_mhz); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); + esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); +#endif } bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config) @@ -235,7 +262,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou uint32_t real_freq_mhz; uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); -#if (CONFIG_XTAL_FREQ == 48) +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION && (CONFIG_XTAL_FREQ == 48) // To maintain APB_MAX (40MHz) while lowering CPU frequency when using a 48MHz XTAL, have to let CPU frequnecy be // 40MHz with PLL_F160M or PLL_F240M clock source. This is a special case, has to handle separately. if (freq_mhz == 40) { @@ -255,6 +282,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou source_freq_mhz = xtal_freq; source = SOC_CPU_CLK_SRC_XTAL; +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION } else if (freq_mhz == 240) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL_F240M; @@ -265,6 +293,23 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou source = SOC_CPU_CLK_SRC_PLL_F160M; source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ; divider = CLK_LL_PLL_160M_FREQ_MHZ / freq_mhz; +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + } else if (freq_mhz == 80) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; + divider = 6; + } else if (freq_mhz == 120) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; + divider = 4; + } else if (freq_mhz == 160) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; + divider = 3; +#endif } else { // unsupported frequency return false; @@ -285,6 +330,7 @@ __attribute__((weak)) void rtc_clk_set_cpu_switch_to_pll(int event_id) void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION if (config->source == SOC_CPU_CLK_SRC_XTAL) { /* Configure clk mspi fast to 80m*/ rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); @@ -308,35 +354,68 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) rtc_clk_bbpll_disable(); } } +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + if (config->source == SOC_CPU_CLK_SRC_XTAL) { + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll + rtc_clk_bbpll_disable(); + } + } else if (config->source == SOC_CPU_CLK_SRC_PLL) { + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) { + rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START); + rtc_clk_bbpll_enable(); + rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); + } + rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); + rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP); + } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { + rtc_clk_cpu_freq_to_8m(); + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll + rtc_clk_bbpll_disable(); + } + } +#endif } void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) { soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; - uint32_t div; // div = freq of SOC_ROOT_CLK / freq of CPU_CLK uint32_t freq_mhz; +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION + uint32_t div = clk_ll_cpu_get_divider(); // div = freq of SOC_ROOT_CLK / freq of CPU_CLK +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + uint32_t div = clk_ll_cpu_get_ls_divider(); // div = freq of SOC_ROOT_CLK / freq of CPU_CLK + uint32_t hs_div = clk_ll_cpu_get_hs_divider(); +#else + uint32_t div = 0; +#endif switch (source) { case SOC_CPU_CLK_SRC_XTAL: { - div = clk_ll_cpu_get_divider(); source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; break; } +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION case SOC_CPU_CLK_SRC_PLL_F160M: { - div = clk_ll_cpu_get_divider(); source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ; freq_mhz = source_freq_mhz / div; break; } case SOC_CPU_CLK_SRC_PLL_F240M: { - div = clk_ll_cpu_get_divider(); source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ; freq_mhz = source_freq_mhz / div; break; +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + case SOC_CPU_CLK_SRC_PLL: { + source_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + freq_mhz = source_freq_mhz / hs_div; + break; +#endif } case SOC_CPU_CLK_SRC_RC_FAST: - div = clk_ll_cpu_get_divider(); source_freq_mhz = 20; freq_mhz = source_freq_mhz / div; break; @@ -356,8 +435,14 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) { if (config->source == SOC_CPU_CLK_SRC_XTAL) { rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - } else if (((config->source == SOC_CPU_CLK_SRC_PLL_F160M) || (config->source == SOC_CPU_CLK_SRC_PLL_F240M)) && - s_cur_pll_freq == config->source_freq_mhz) { + } else if ( +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION + ((config->source == SOC_CPU_CLK_SRC_PLL_F160M) || (config->source == SOC_CPU_CLK_SRC_PLL_F240M)) && +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + config->source == SOC_CPU_CLK_SRC_PLL && +#endif + s_cur_pll_freq == config->source_freq_mhz + ) { rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); @@ -391,7 +476,16 @@ void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz) soc_xtal_freq_t rtc_clk_xtal_freq_get(void) { +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION return CONFIG_XTAL_FREQ; +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); + if (xtal_freq_mhz == 0) { + ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); + return RTC_XTAL_FREQ_40M; + } + return (soc_xtal_freq_t)xtal_freq_mhz; +#endif } void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq) @@ -405,6 +499,7 @@ static uint32_t rtc_clk_ahb_freq_get(void) uint32_t soc_root_freq_mhz; uint32_t divider; switch (source) { +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION case SOC_CPU_CLK_SRC_XTAL: soc_root_freq_mhz = rtc_clk_xtal_freq_get(); divider = clk_ll_ahb_get_divider(); @@ -421,6 +516,20 @@ static uint32_t rtc_clk_ahb_freq_get(void) soc_root_freq_mhz = 20; divider = clk_ll_ahb_get_divider(); break; +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + case SOC_CPU_CLK_SRC_XTAL: + soc_root_freq_mhz = rtc_clk_xtal_freq_get(); + divider = clk_ll_ahb_get_ls_divider(); + break; + case SOC_CPU_CLK_SRC_PLL: + soc_root_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + divider = clk_ll_ahb_get_hs_divider(); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + soc_root_freq_mhz = 20; + divider = clk_ll_ahb_get_ls_divider(); + break; +#endif default: // Unknown SOC_ROOT clock source soc_root_freq_mhz = 0; @@ -452,3 +561,10 @@ bool rtc_dig_8m_enabled(void) { return clk_ll_rc_fast_digi_is_enabled(); } + +#if CONFIG_IDF_TARGET_ESP32C5_MP_VERSION +/* Name used in libphy.a:phy_chip_v7.o + * TODO: update the library to use rtc_clk_xtal_freq_get + */ +rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get"))); +#endif diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk_init.c b/components/esp_hw_support/port/esp32c5/rtc_clk_init.c index b65f8e250e..dfbce0b2ce 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32c5/rtc_clk_init.c @@ -12,6 +12,7 @@ #include "esp32c5/rom/rtc.h" #include "esp32c5/rom/uart.h" #include "soc/rtc.h" +#include "soc/soc_caps.h" #include "esp_cpu.h" #include "regi2c_ctrl.h" #include "soc/lp_clkrst_reg.h" @@ -21,8 +22,10 @@ #include "esp_rom_uart.h" #include "esp_private/esp_pmu.h" #include "hal/clk_tree_ll.h" +#if SOC_MODEM_CLOCK_SUPPORTED #include "hal/modem_syscon_ll.h" #include "hal/modem_lpcon_ll.h" +#endif #include "pmu_param.h" static const char *TAG = "rtc_clk_init"; @@ -44,17 +47,18 @@ static void rtc_clk_modem_clock_domain_active_state_icg_map_preinit(void) /* Configure modem ICG code in PMU_ACTIVE state */ pmu_ll_hp_set_icg_modem(&PMU, PMU_MODE_HP_ACTIVE, PMU_HP_ICG_MODEM_CODE_ACTIVE); +#if SOC_MODEM_CLOCK_SUPPORTED /* Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in PMU_ACTIVE state */ modem_syscon_ll_set_modem_apb_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); modem_lpcon_ll_set_i2c_master_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); modem_lpcon_ll_set_lp_apb_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); +#endif /* Software trigger force update modem ICG code and ICG switch */ pmu_ll_imm_update_dig_icg_modem_code(&PMU, true); pmu_ll_imm_update_dig_icg_switch(&PMU, true); } - void rtc_clk_init(rtc_clk_config_t cfg) { rtc_cpu_freq_config_t old_config, new_config; diff --git a/components/esp_hw_support/port/esp32c5/rtc_time.c b/components/esp_hw_support/port/esp32c5/rtc_time.c index 0306546152..acf1b19fcd 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_time.c +++ b/components/esp_hw_support/port/esp32c5/rtc_time.c @@ -211,7 +211,6 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) { soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get(); - // TODO: IDF-8642 Check whether this workaround still need for C5 // /*The Fosc CLK of calibration circuit is divided by 32. // So we need to divide the calibrate cycles of the FOSC by 32 to @@ -221,7 +220,6 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) // } uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles); - if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) { return 0; } diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c index eec25e6794..c3652b5ff4 100644 --- a/components/esp_hw_support/sleep_clock.c +++ b/components/esp_hw_support/sleep_clock.c @@ -33,7 +33,9 @@ esp_err_t sleep_clock_system_retention_init(void) { #if CONFIG_IDF_TARGET_ESP32C6 #define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_REG - DR_REG_PCR_BASE) / 4) + 1) -#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + #define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_1_REG - DR_REG_PCR_BASE) / 4) + 1) +#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION #define N_REGS_PCR() (((PCR_PWDET_SAR_CLK_CONF_REG - DR_REG_PCR_BASE) / 4) + 1) #endif const static sleep_retention_entries_config_t pcr_regs_retention[] = { diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 2fb850aba5..c5f33787ed 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -99,6 +99,7 @@ menu "ESP System Settings" default y if IDF_TARGET_ESP32C6 default n if IDF_TARGET_ESP32H2 # IDF-5667 default y if IDF_TARGET_ESP32P4 + default y if IDF_TARGET_ESP32C5 depends on SOC_RTC_FAST_MEM_SUPPORTED config ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP @@ -359,7 +360,8 @@ menu "ESP System Settings" prompt "UART console baud rate" if ESP_CONSOLE_UART_CUSTOM depends on ESP_CONSOLE_UART default 74880 if (IDF_TARGET_ESP32C2 && XTAL_FREQ_26) - default 138240 if (IDF_TARGET_ESP32C5_BETA3_VERSION && XTAL_FREQ_48) + # TODO: IDF-8651 Check if need update + default 138240 if (IDF_TARGET_ESP32C5 && XTAL_FREQ_48) default 115200 range 1200 4000000 if !PM_ENABLE range 1200 1000000 if PM_ENABLE diff --git a/components/esp_system/fpga_overrides_clk.c b/components/esp_system/fpga_overrides_clk.c index 51b9bae8fb..4fd5607c6d 100644 --- a/components/esp_system/fpga_overrides_clk.c +++ b/components/esp_system/fpga_overrides_clk.c @@ -27,6 +27,8 @@ #include "esp32h2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32P4 #include "esp32p4/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rom/rtc.h" #endif #include "esp_log.h" #include "esp_rom_sys.h" diff --git a/components/esp_system/ld/esp32c5/mp/.gitkeep b/components/esp_system/ld/esp32c5/mp/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/components/esp_system/ld/esp32c5/mp/memory.ld.in b/components/esp_system/ld/esp32c5/mp/memory.ld.in index e69de29bb2..41b06aa691 100644 --- a/components/esp_system/ld/esp32c5/mp/memory.ld.in +++ b/components/esp_system/ld/esp32c5/mp/memory.ld.in @@ -0,0 +1,139 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * ESP32-C5 Linker Script Memory Layout + * This file describes the memory layout (memory blocks) by virtual memory addresses. + * This linker script is passed through the C preprocessor to include configuration options. + * Please use preprocessor features sparingly! + * Restrict to simple macros with numeric values, and/or #if/#endif blocks. + */ + +#include "sdkconfig.h" +#include "ld.common" + +/** + * physical memory is mapped twice to the vritual address (IRAM and DRAM). + * `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory + */ +#define SRAM_IRAM_START 0x40800000 +#define SRAM_DRAM_START 0x40800000 + +#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START) +#define SRAM_DRAM_END 0x4086E610 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */ + +#define SRAM_IRAM_ORG (SRAM_IRAM_START) +#define SRAM_DRAM_ORG (SRAM_DRAM_START) + +#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS +/* + * IDRAM0_2_SEG_SIZE_DEFAULT is used when page size is 64KB + */ +#define IDRAM0_2_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 8) +#endif + +#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE + +MEMORY +{ + /** + * All these values assume the flash cache is on, and have the blocks this uses subtracted from the length + * of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but + * are connected to the data port of the CPU and eg allow byte-wise access. + */ + + /* IRAM for PRO CPU. */ + iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + /* Flash mapped instruction data */ + irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 + + /** + * (0x20 offset above is a convenience for the app binary image generation. + * Flash cache has 64KB pages. The .bin file which is flashed to the chip + * has a 0x18 byte file header, and each segment has a 0x08 byte segment + * header. Setting this offset makes it simple to meet the flash cache MMU's + * constraint that (paddr % 64KB == vaddr % 64KB).) + */ +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + + /** + * Shared data RAM, excluding memory reserved for ROM bss/data/stack. + * Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available. + */ + dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + /* Flash mapped constant data */ + drom_seg (R) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 + + /* (See irom_seg for meaning of 0x20 offset in the above.) */ +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + + /** + * lp ram memory (RWX). Persists over deep sleep. // TODO: IDF-5667 + */ +#if CONFIG_ULP_COPROC_ENABLED + lp_ram_seg(RW) : org = 0x50000000 + CONFIG_ULP_COPROC_RESERVE_MEM, + len = 0x4000 - CONFIG_ULP_COPROC_RESERVE_MEM - RESERVE_RTC_MEM +#else + lp_ram_seg(RW) : org = 0x50000000, len = 0x4000 - RESERVE_RTC_MEM +#endif // CONFIG_ULP_COPROC_ENABLED + + /* We reduced the size of lp_ram_seg by RESERVE_RTC_MEM value. + It reserves the amount of LP memory that we use for this memory segment. + This segment is intended for keeping: + - (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). + - (higher addr) bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on). + The aim of this is to keep data that will not be moved around and have a fixed address. + */ + lp_reserved_seg(RW) : org = 0x50000000 + 0x4000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM +} + +/* Heap ends at top of dram0_0_seg */ +_heap_end = 0x40000000; + +_data_seg_org = ORIGIN(rtc_data_seg); + +/** + * The lines below define location alias for .rtc.data section + * C5 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section + * Thus, the following region segments are not configurable like on other targets + */ +REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); +REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); +REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); +REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + REGION_ALIAS("default_code_seg", irom_seg); +#else + REGION_ALIAS("default_code_seg", iram0_0_seg); +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + REGION_ALIAS("default_rodata_seg", drom_seg); +#else + REGION_ALIAS("default_rodata_seg", dram0_0_seg); +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + +/** + * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must + * also be first in the segment. + */ +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), + ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") +#endif + +#if CONFIG_ESP_SYSTEM_USE_EH_FRAME + ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); + ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); +#endif diff --git a/components/esp_system/ld/esp32c5/mp/sections.ld.in b/components/esp_system/ld/esp32c5/mp/sections.ld.in index e69de29bb2..fcb2f4755b 100644 --- a/components/esp_system/ld/esp32c5/mp/sections.ld.in +++ b/components/esp_system/ld/esp32c5/mp/sections.ld.in @@ -0,0 +1,442 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ld.common" + +/* Default entry point */ +ENTRY(call_start_cpu0); + +SECTIONS +{ + /** + * RTC fast memory holds RTC wake stub code, + * including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + _rtc_fast_start = ABSOLUTE(.); + _rtc_text_start = ABSOLUTE(.); + *(.rtc.entry.text) + + mapping[rtc_text] + + *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *(.rtc_text_end_test) + + /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(4); + + _rtc_text_end = ABSOLUTE(.); + } > lp_ram_seg + + /** + * This section located in RTC FAST Memory area. + * It holds data marked with RTC_FAST_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_fast : + { + . = ALIGN(4); + _rtc_force_fast_start = ABSOLUTE(.); + + mapping[rtc_force_fast] + + *(.rtc.force_fast .rtc.force_fast.*) + . = ALIGN(4) ; + + _rtc_force_fast_end = ABSOLUTE(.); + } > lp_ram_seg + + /** + * RTC data section holds RTC wake stub + * data/rodata, including from any source file + * named rtc_wake_stub*.c and the data marked with + * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + + mapping[rtc_data] + + *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + _rtc_data_end = ABSOLUTE(.); + } > lp_ram_seg + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) + *rtc_wake_stub*.*(COMMON) + + mapping[rtc_bss] + + _rtc_bss_end = ABSOLUTE(.); + } > lp_ram_seg + + /** + * This section holds data that should not be initialized at power up + * and will be retained during deep sleep. + * User data marked with RTC_NOINIT_ATTR will be placed + * into this section. See the file "esp_attr.h" for more information. + */ + .rtc_noinit (NOLOAD): + { + . = ALIGN(4); + _rtc_noinit_start = ABSOLUTE(.); + *(.rtc_noinit .rtc_noinit.*) + . = ALIGN(4) ; + _rtc_noinit_end = ABSOLUTE(.); + } > lp_ram_seg + + /** + * This section located in RTC SLOW Memory area. + * It holds data marked with RTC_SLOW_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4) ; + _rtc_force_slow_end = ABSOLUTE(.); + } > lp_ram_seg + + /** + * This section holds RTC data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_reserved (NOLOAD): + { + . = ALIGN(4); + _rtc_reserved_start = ABSOLUTE(.); + /* New data can only be added here to ensure existing data are not moved. + Because data have adhered to the end of the segment and code is relied on it. + >> put new data here << */ + + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); + } > rtc_reserved_seg + + _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; + ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), + "RTC reserved segment data does not fit.") + + /* Get size of rtc slow data based on rtc_data_location alias */ + _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_slow_end - _rtc_data_start) + : (_rtc_force_slow_end - _rtc_force_slow_start); + + _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_fast_end - _rtc_fast_start) + : (_rtc_noinit_end - _rtc_fast_start); + + ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)), + "RTC_SLOW segment data does not fit.") + + ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)), + "RTC_FAST segment data does not fit.") + + .iram0.text : + { + _iram_start = ABSOLUTE(.); + /* Vectors go to start of IRAM */ + ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + KEEP(*(.exception_vectors_table.text)); + KEEP(*(.exception_vectors.text)); + . = ALIGN(4); + + _invalid_pc_placeholder = ABSOLUTE(.); + + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + mapping[iram0_text] + + } > iram0_0_seg + + /* Marks the end of IRAM code segment */ + .iram0.text_end (NOLOAD) : + { + /* ESP32-C5 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); + /* iram_end_test section exists for use by memprot unit tests only */ + *(.iram_end_test) + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + + .iram0.data : + { + . = ALIGN(16); + _iram_data_start = ABSOLUTE(.); + + mapping[iram0_data] + + _iram_data_end = ABSOLUTE(.); + } > iram0_0_seg + + .iram0.bss (NOLOAD) : + { + . = ALIGN(16); + _iram_bss_start = ABSOLUTE(.); + + mapping[iram0_bss] + + _iram_bss_end = ABSOLUTE(.); + . = ALIGN(16); + _iram_end = ABSOLUTE(.); + } > iram0_0_seg + + /** + * This section is required to skip .iram0.text area because iram0_0_seg and + * dram0_0_seg reflect the same address space on different buses. + */ + .dram0.dummy (NOLOAD): + { + . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start; + } > dram0_0_seg + + .dram0.data : + { + _data_start = ABSOLUTE(.); + *(.gnu.linkonce.d.*) + *(.data1) + __global_pointer$ = . + 0x800; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + + mapping[dram0_data] + + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } > dram0_0_seg + + /** + * This section holds data that should not be initialized at power up. + * The section located in Internal SRAM memory region. The macro _NOINIT + * can be used as attribute to place data into this section. + * See the "esp_attr.h" file for more information. + */ + .noinit (NOLOAD): + { + . = ALIGN(4); + _noinit_start = ABSOLUTE(.); + *(.noinit .noinit.*) + . = ALIGN(4) ; + _noinit_end = ABSOLUTE(.); + } > dram0_0_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + + /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + mapping[dram0_bss] + + . = ALIGN(4); + _bss_end = ABSOLUTE(.); + } > dram0_0_seg + + ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") + + .flash.text : + { + _stext = .; + _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + _text_start = ABSOLUTE(.); + + mapping[flash_text] + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + + /** CPU will try to prefetch up to 16 bytes of + * of instructions. This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += _esp_flash_mmap_prefetch_pad_size; + + _text_end = ABSOLUTE(.); + _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + _etext = .; + + /** + * Similar to _iram_start, this symbol goes here so it is + * resolved by addr2line in preference to the first symbol in + * the flash.text segment. + */ + _flash_cache_start = ABSOLUTE(0); + } > default_code_seg + + /** + * This dummy section represents the .flash.text section but in default_rodata_seg. + * Thus, it must have its alignment and (at least) its size. + */ + .flash_rodata_dummy (NOLOAD): + { + _flash_rodata_dummy_start = .; + /* Start at the same alignment constraint than .flash.text */ + . = ALIGN(ALIGNOF(.flash.text)); + /* Create an empty gap as big as .flash.text section */ + . = . + SIZEOF(.flash.text); + /* Prepare the alignment of the section above. Few bytes (0x20) must be + * added for the mapping header. */ + . = ALIGN(_esp_mmu_block_size) + 0x20; + } > default_rodata_seg + + .flash.appdesc : ALIGN(0x10) + { + _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + _rodata_start = ABSOLUTE(.); + + *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ + *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + + /* Create an empty gap within this section. Thanks to this, the end of this + * section will match .flash.rodata's begin address. Thus, both sections + * will be merged when creating the final bin image. */ + . = ALIGN(ALIGNOF(.flash.rodata)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) + + .flash.rodata : ALIGN(0x10) + { + _flash_rodata_start = ABSOLUTE(.); + + mapping[flash_rodata] + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 7) & ~ 3; + /* + * C++ constructor and destructor tables + * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. + * But the init_priority sections will be sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending order during startup, however. + * Hence a different section is generated for the init_priority functions which is iterated in + * ascending order during startup. The corresponding code can be found in startup.c. + */ + __init_priority_array_start = ABSOLUTE(.); + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) + __init_priority_array_end = ABSOLUTE(.); + __init_array_start = ABSOLUTE(.); + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.*(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ + soc_reserved_memory_region_start = ABSOLUTE(.); + KEEP (*(.reserved_memory_address)) + soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.flash.tls)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls) + + .flash.tls : ALIGN(8) + { + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) + + /* Keep this section shall be at least aligned on 4 */ + .eh_frame : ALIGN(8) + { + __eh_frame = ABSOLUTE(.); + KEEP (*(.eh_frame)) + __eh_frame_end = ABSOLUTE(.); + /* Guarantee that this section and the next one will be merged by making + * them adjacent. */ + . = ALIGN(ALIGNOF(.eh_frame_hdr)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + + /* To avoid any exception in C++ exception frame unwinding code, this section + * shall be aligned on 8. */ + .eh_frame_hdr : ALIGN(8) + { + __eh_frame_hdr = ABSOLUTE(.); + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); + } > default_rodata_seg + + /* + This section is a place where we dump all the rodata which aren't used at runtime, + so as to avoid binary size increase + */ + .flash.rodata_noload (NOLOAD) : + { + /* + This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address + We don't need to include the noload rodata in this section + */ + _rodata_reserved_end = ABSOLUTE(.); + . = ALIGN (4); + mapping[rodata_noload] + } > default_rodata_seg + + /* Marks the end of data, bss and possibly rodata */ + .dram0.heap_start (NOLOAD) : + { + . = ALIGN (16); + _heap_start = ABSOLUTE(.); + } > dram0_0_seg +} + +ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") + +ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), + "DRAM segment data does not fit.") diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index fc017b5c02..1a1f1ce8ae 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -15,18 +15,24 @@ #include "esp32c5/rom/ets_sys.h" #include "esp32c5/rom/uart.h" #include "soc/soc.h" +#include "soc/soc_caps.h" #include "soc/rtc.h" #include "soc/rtc_periph.h" #include "soc/i2s_reg.h" #include "esp_cpu.h" #include "hal/wdt_hal.h" +#if SOC_MODEM_CLOCK_SUPPORTED #include "hal/modem_lpcon_ll.h" +#endif #include "esp_private/esp_modem_clock.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" #include "esp_private/esp_pmu.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" +#if CONFIG_IDF_TARGET_ESP32C5_MP_VERSION +#include "ocode_init.h" +#endif /* Number of cycles to wait from the 32k XTAL oscillator to consider it running. * Larger values increase startup delay. Smaller values may cause false positive @@ -43,16 +49,30 @@ static const char *TAG = "clk"; // TODO: [ESP32C5] IDF-8642 __attribute__((weak)) void esp_clk_init(void) { +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION #if SOC_PMU_SUPPORTED pmu_init(); #endif assert((rtc_clk_xtal_freq_get() == SOC_XTAL_FREQ_40M) || (rtc_clk_xtal_freq_get() == SOC_XTAL_FREQ_48M)); - +#if SOC_MODEM_CLOCK_SUPPORTED modem_lpcon_ll_set_pwr_tick_target(&MODEM_LPCON, rtc_clk_xtal_freq_get() - 1); +#endif + rtc_clk_8m_enable(true); + rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST); +#elif CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION +#if !CONFIG_IDF_ENV_FPGA + pmu_init(); + if (esp_rom_get_reset_reason(0) == RESET_REASON_CHIP_POWER_ON) { + esp_ocode_calib_init(); + } + + assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M); rtc_clk_8m_enable(true); rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST); +#endif +#endif #ifdef CONFIG_BOOTLOADER_WDT_ENABLE // WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed. @@ -76,7 +96,11 @@ __attribute__((weak)) void esp_clk_init(void) #elif defined(CONFIG_RTC_CLK_SRC_INT_RC32K) select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_RC32K); #else +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION abort(); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_RC_SLOW); +#endif #endif #ifdef CONFIG_BOOTLOADER_WDT_ENABLE @@ -141,7 +165,7 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) if (retry_32k_xtal-- > 0) { continue; } -#if CONFIG_IDF_TARGET_ESP32C5 +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION ESP_EARLY_LOGW(TAG, "32 kHz clock not found, switching to internal 32 kHz oscillator"); rtc_slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC32K; #else @@ -182,7 +206,10 @@ void rtc_clk_select_rtc_slow_clk(void) */ __attribute__((weak)) void esp_perip_clk_init(void) { -#if 0 // TODO: [ESP32C5] IDF-8844 +// TODO: [ESP32C5] IDF-8844 +#if CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + // modem_clock_domain_pmu_state_icg_map_init(); +#endif /* During system initialization, the low-power clock source of the modem * (WiFi, BLE or Coexist) follows the configuration of the slow clock source * of the system. If the WiFi, BLE or Coexist module needs a higher @@ -190,15 +217,14 @@ __attribute__((weak)) void esp_perip_clk_init(void) * oscillator (40 MHz) to provide the clock during the sleep process in some * scenarios), the module needs to switch to the required clock source by * itself. */ //TODO - WIFI-5233 - soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); - modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t)(\ - (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? MODEM_CLOCK_LPCLK_SRC_XTAL32K \ - : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) ? MODEM_CLOCK_LPCLK_SRC_RC32K \ - : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K \ - : MODEM_CLOCK_LPCLK_SRC_RC32K); - - modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); -#endif + // soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); + // modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t)( + // (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_RC_SLOW + // : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? MODEM_CLOCK_LPCLK_SRC_XTAL32K + // : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) ? MODEM_CLOCK_LPCLK_SRC_RC32K + // : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K + // : SOC_RTC_SLOW_CLK_SRC_RC_SLOW); + // modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet"); #if 0 // TODO: [ESP32C5] IDF-8844 @@ -292,7 +318,11 @@ __attribute__((weak)) void esp_perip_clk_init(void) /* Set WiFi light sleep clock source to RTC slow clock */ REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0); +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_XTAL32K | SYSTEM_LPCLK_SEL_XTAL | SYSTEM_LPCLK_SEL_8M | SYSTEM_LPCLK_SEL_RTC_SLOW); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M); +#endif SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW); /* Enable RNG clock. */ diff --git a/components/esp_system/port/soc/esp32c5/system_internal.c b/components/esp_system/port/soc/esp32c5/system_internal.c index a2d8056081..1146fe3cd7 100644 --- a/components/esp_system/port/soc/esp32c5/system_internal.c +++ b/components/esp_system/port/soc/esp32c5/system_internal.c @@ -13,16 +13,21 @@ #include "esp_rom_sys.h" #include "riscv/rv_utils.h" #include "esp_rom_uart.h" +#include "soc/soc_caps.h" #include "soc/gpio_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" #include "esp_private/rtc_clk.h" #include "soc/rtc_periph.h" #include "soc/uart_reg.h" +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION #include "hal/clk_tree_ll.h" +#endif #include "hal/wdt_hal.h" +#if SOC_MODEM_CLOCK_SUPPORTED #include "hal/modem_syscon_ll.h" #include "hal/modem_lpcon_ll.h" +#endif #include "esp_private/cache_err_int.h" #include "esp32c5/rom/cache.h" @@ -35,32 +40,48 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) esp_rom_output_tx_wait_idle(0); esp_rom_output_tx_wait_idle(1); + // TODO: IDF-8845 +#if SOC_MODEM_CLOCK_SUPPORTED modem_syscon_ll_reset_all(&MODEM_SYSCON); modem_lpcon_ll_reset_all(&MODEM_LPCON); +#endif +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION // Set SPI Flash Freq to 40M clk_ll_mspi_fast_set_src(MSPI_CLK_SRC_XTAL); clk_ll_mspi_fast_set_divider(1); // Set Peripheral clk rst SET_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); +#endif + // Set Peripheral clk rst SET_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN); SET_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN); SET_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN); SET_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN); SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN); +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION SET_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN); SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN); // Clear Peripheral clk rst CLEAR_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); + SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN); +#endif + // Clear Peripheral clk rst CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN); CLEAR_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN); CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN); CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN); CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN); +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + // CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN); +#endif CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN); } @@ -98,7 +119,11 @@ void IRAM_ATTR esp_restart_noos(void) wdt_hal_write_protect_enable(&wdt1_context); // Disable cache +#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION Cache_Disable_ICache(); +#elif CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + Cache_Disable_Cache(); +#endif // Reset wifi/bluetooth/ethernet/sdio (bb/mac) // Moved to module internal diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h index 8ce0e1f8e4..1c1b6402be 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h @@ -665,8 +665,11 @@ static inline void __attribute__((always_inline)) vPortExitCriticalSafe(portMUX_ FORCE_INLINE_ATTR bool xPortCanYield(void) { - uint32_t threshold = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG); + #if SOC_INT_CLIC_SUPPORTED +// TODO: [ESP32C5] IDF-8655 simplify the code for c5 mp +#if !CONFIG_IDF_TARGET_ESP32C5_MP_VERSION + uint32_t threshold = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG); /* When CLIC is supported: * - The lowest interrupt threshold level is 0. Therefore, an interrupt threshold level above 0 would mean that we * are in a critical section. @@ -679,12 +682,22 @@ FORCE_INLINE_ATTR bool xPortCanYield(void) threshold = threshold >> (CLIC_CPU_INT_THRESH_S + (8 - NLBITS)); return ((intr_level == 0) && (threshold == 0)); -#endif /* SOC_INT_CLIC_SUPPORTED */ +#else + #define MINTSTATUS 0xfb1 + #define MINTTHRESH 0x347 + uint32_t threshold1 = (RV_READ_CSR(MINTTHRESH)) >> (8 - NLBITS); + uint32_t threshold2 = (RV_READ_CSR(MINTSTATUS)) >> (24 + (8 - NLBITS)); + return (threshold1 == 0) && (threshold2 == 0) ; +#endif + +#else/* !SOC_INT_CLIC_SUPPORTED */ + uint32_t threshold = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG); /* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL * and exit critical code, will recover threshold value (1). so threshold <= 1 * means not in critical code */ return (threshold <= 1); +#endif }