Merge branch 'feature/add_system_components_to_esp32c5mp' into 'master'

feat(esp32c5mp): add system related components (Stage 5/7)

See merge request espressif/esp-idf!29603
This commit is contained in:
Kevin (Lao Kaiyao) 2024-03-19 16:48:56 +08:00
commit a77a7ab550
27 changed files with 1067 additions and 56 deletions

View File

@ -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();

View File

@ -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.

View File

@ -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

View File

@ -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
*/

View File

@ -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
}

View File

@ -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");
}

View File

@ -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);

View File

@ -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);

View File

@ -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
*/

View File

@ -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}")

View File

@ -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

View File

@ -6,6 +6,7 @@
#include <string.h>
#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;
}

View File

@ -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

View File

@ -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;

View File

@ -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 \
} \

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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[] = {

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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.")

View File

@ -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. */

View File

@ -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

View File

@ -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
}