diff --git a/components/bootloader_support/src/bootloader_clock_init.c b/components/bootloader_support/src/bootloader_clock_init.c index da34d7ab37..a86daa6d0c 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-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,14 +9,7 @@ #include "soc/chip_revision.h" #include "hal/efuse_hal.h" -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO: IDF-5645 -#include "soc/rtc_cntl_reg.h" -#else -#include "soc/lp_wdt_reg.h" -#include "soc/lp_timer_reg.h" -#include "soc/lp_analog_peri_reg.h" -#include "soc/pmu_reg.h" -#endif +#include "soc/rtc_cntl_periph.h" #if CONFIG_IDF_TARGET_ESP32 #include "hal/clk_tree_ll.h" @@ -163,7 +156,16 @@ __attribute__((weak)) void bootloader_clock_configure(void) SET_PERI_REG_MASK(LP_ANALOG_PERI_LP_INT_CLR_REG, LP_ANALOG_PERI_LP_INT_CLR_REG); /* BROWN_OUT */ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */ #elif CONFIG_IDF_TARGET_ESP32S31 - //ESP32S31-TODO IDF-14696 + // CLR ENA + CLEAR_PERI_REG_MASK(RTC_WDT_INT_ENA_REG, RTC_WDT_SUPER_WDT_INT_ENA); /* SWD */ + CLEAR_PERI_REG_MASK(LP_ANA_LP_INT_ENA_REG, LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */ + CLEAR_PERI_REG_MASK(RTC_WDT_INT_ENA_REG, RTC_WDT_LP_WDT_INT_ENA); /* WDT */ + CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */ + CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */ + // SET CLR + SET_PERI_REG_MASK(RTC_WDT_INT_CLR_REG, RTC_WDT_SUPER_WDT_INT_CLR); /* SWD */ + SET_PERI_REG_MASK(LP_ANA_LP_INT_CLR_REG, LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */ + SET_PERI_REG_MASK(RTC_WDT_INT_CLR_REG, RTC_WDT_LP_WDT_INT_CLR); /* WDT */ #else REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); diff --git a/components/bootloader_support/src/bootloader_random.c b/components/bootloader_support/src/bootloader_random.c index e7cbfaf6d5..66fdfb4b6e 100644 --- a/components/bootloader_support/src/bootloader_random.c +++ b/components/bootloader_support/src/bootloader_random.c @@ -45,7 +45,7 @@ assert(buffer != NULL); for (size_t i = 0; i < length; i++) { -#if SOC_RTC_TIMER_V2_SUPPORTED +#if !SOC_RTC_TIMER_V1 random = REG_READ(WDEV_RND_REG); start = esp_cpu_get_cycle_count(); do { diff --git a/components/esp_hal_rtc_timer/README.md b/components/esp_hal_rtc_timer/README.md index 705191d962..ae52a7baed 100644 --- a/components/esp_hal_rtc_timer/README.md +++ b/components/esp_hal_rtc_timer/README.md @@ -8,8 +8,9 @@ The `esp_hal_rtc_timer` component provides a **unified Hardware Abstraction Layer** for RTC Timer peripherals across all ESP-IDF supported targets. This HAL abstracts hardware differences between legacy RTC timer implementations (in RTC_CNTL peripheral) and modern low-power timer implementations, providing a consistent API for wakeup timer configuration and RTC time reading across different ESP chip families. The component consolidates timer functionality from two different hardware implementations: -- **SOC_RTC_TIMER_V1_SUPPORTED**: Legacy RTC timer functionality in RTC_CNTL peripheral (ESP32, ESP32C2, ESP32C3, ESP32S2, ESP32S3) -- **SOC_RTC_TIMER_V2_SUPPORTED**: Newer LP timer peripheral (ESP32C5, ESP32C6, ESP32C61, ESP32H2, ESP32H21, ESP32H4, ESP32P4) +- **SOC_RTC_TIMER_V1**: Legacy RTC timer functionality in RTC_CNTL peripheral for ESP32, ESP32C2, ESP32C3, ESP32S2, ESP32S3 +- **SOC_RTC_TIMER_V2**: LP timer peripheral for ESP32C5, ESP32C6, ESP32C61, ESP32H2, ESP32H21, ESP32H4, ESP32P4 +- **SOC_RTC_TIMER_V3**: RTC timer peripheral for ESP32S31 ### Unified HAL API (All Chips) - Wakeup timer configuration via `rtc_timer_hal_set_wakeup_time()` diff --git a/components/esp_hal_rtc_timer/esp32s31/include/hal/rtc_timer_ll.h b/components/esp_hal_rtc_timer/esp32s31/include/hal/rtc_timer_ll.h index b742aa76c1..f6fb9c2fc4 100644 --- a/components/esp_hal_rtc_timer/esp32s31/include/hal/rtc_timer_ll.h +++ b/components/esp_hal_rtc_timer/esp32s31/include/hal/rtc_timer_ll.h @@ -1,19 +1,18 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer for ESP32-P4 RTC_Timer register operations +// The LL layer for ESP32S31 RTC_Timer register operations #pragma once #include #include #include "soc/soc.h" -#include "soc/lp_timer_struct.h" -#include "soc/lp_timer_reg.h" -#include "soc/lp_system_reg.h" +#include "soc/rtc_timer_struct.h" +#include "soc/rtc_timer_reg.h" #include "hal/misc.h" #include "esp_attr.h" @@ -21,7 +20,106 @@ extern "C" { #endif -// TODO: ["ESP32S31"] IDF-14642 +FORCE_INLINE_ATTR void rtc_timer_ll_set_alarm_target(rtc_timer_dev_t *dev, uint8_t timer_id, uint64_t value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->target[timer_id].hi, target_hi, (value >> 32) & 0xFFFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->target[timer_id].lo, target_lo, value & 0xFFFFFFFF); +} + +FORCE_INLINE_ATTR void rtc_timer_ll_set_target_enable(rtc_timer_dev_t *dev, uint8_t timer_id, bool en) +{ + dev->target[timer_id].hi.enable = en; +} + +FORCE_INLINE_ATTR uint32_t rtc_timer_ll_get_counter_value_low(rtc_timer_dev_t *dev, uint8_t timer_id) +{ + return HAL_FORCE_READ_U32_REG_FIELD(dev->counter[timer_id].lo, counter_lo); +} + +FORCE_INLINE_ATTR uint32_t rtc_timer_ll_get_counter_value_high(rtc_timer_dev_t *dev, uint8_t timer_id) +{ + return HAL_FORCE_READ_U32_REG_FIELD(dev->counter[timer_id].hi, counter_hi); +} + +FORCE_INLINE_ATTR void rtc_timer_ll_counter_snapshot(rtc_timer_dev_t *dev) +{ + dev->update.main_timer_update = 1; +} + +/** + * @brief Clear alarm interrupt status + * + * @param dev LP timer peripheral instance + * @param timer_id Timer ID (0 for main timer, 1 for LP timer) + */ +FORCE_INLINE_ATTR void rtc_timer_ll_clear_alarm_intr_status(rtc_timer_dev_t *dev, uint8_t timer_id) +{ + if (timer_id == 0) { + dev->int_clr.soc_wakeup_int_clr = 1; + } else if (timer_id == 1) { + dev->lp_int_clr.main_timer_lp_int_clr = 1; + } +} + +/** + * @brief Get interrupt raw status + * + * @param dev LP timer peripheral instance + * @param timer_id Timer ID (0 for main timer, 1 for LP timer) + * @return Interrupt raw status value + */ +FORCE_INLINE_ATTR uint32_t rtc_timer_ll_get_intr_raw(rtc_timer_dev_t *dev, uint8_t timer_id) +{ + if (timer_id == 0) { + return dev->int_raw.val; + } else if (timer_id == 1) { + return dev->lp_int_raw.val; + } + return 0; +} + +/** + * @brief Enable/disable alarm interrupt + * + * @param dev LP timer peripheral instance + * @param timer_id Timer ID (0 for main timer, 1 for LP timer) + * @param enable Enable or disable interrupt + */ +FORCE_INLINE_ATTR void rtc_timer_ll_alarm_intr_enable(rtc_timer_dev_t *dev, uint8_t timer_id, bool enable) +{ + if (timer_id == 0) { + dev->int_ena.soc_wakeup_int_ena = enable; + } else if (timer_id == 1) { + dev->lp_int_ena.main_timer_lp_int_ena = enable; + } +} + +/** + * @brief Set wakeup timer value + * + * @param timer_id Timer ID + * @param ticks Timer value in RTC slow clock ticks + */ +FORCE_INLINE_ATTR void rtc_timer_ll_set_wakeup_time(uint8_t timer_id, uint64_t ticks) +{ + rtc_timer_ll_clear_alarm_intr_status(&RTC_TIMER, timer_id); + rtc_timer_ll_set_alarm_target(&RTC_TIMER, timer_id, ticks); + rtc_timer_ll_set_target_enable(&RTC_TIMER, timer_id, true); +} + +/** + * @brief Get current RTC timer cycle count + * + * @param timer_id Timer ID + * @return Current RTC time in RTC slow clock ticks + */ +FORCE_INLINE_ATTR uint64_t rtc_timer_ll_get_cycle_count(uint8_t timer_id) +{ + rtc_timer_ll_counter_snapshot(&RTC_TIMER); + uint32_t lo = rtc_timer_ll_get_counter_value_low(&RTC_TIMER, timer_id); + uint32_t hi = rtc_timer_ll_get_counter_value_high(&RTC_TIMER, timer_id); + return ((uint64_t)hi << 32) | lo; +} #ifdef __cplusplus } diff --git a/components/esp_hal_wdt/esp32s31/include/hal/lpwdt_ll.h b/components/esp_hal_wdt/esp32s31/include/hal/lpwdt_ll.h deleted file mode 100644 index d1550f93e8..0000000000 --- a/components/esp_hal_wdt/esp32s31/include/hal/lpwdt_ll.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "hal/misc.h" -#include "hal/wdt_types.h" -#include "soc/rtc_cntl_periph.h" -#include "soc/efuse_reg.h" -#include "esp_attr.h" -#include "esp_assert.h" - -#include "esp32s31/rom/ets_sys.h" - -// TODO: ["ESP32S31"] IDF-14636 - -/* The value that needs to be written to LP_WDT_WPROTECT_REG to write-enable the wdt registers */ -#define LP_WDT_WKEY_VALUE 0x50D83AA1 -/* The value that needs to be written to LP_WDT_SWD_WPROTECT_REG to write-enable the swd registers */ -#define LP_WDT_SWD_WKEY_VALUE 0x50D83AA1 - -/* Possible values for RTC_CNTL_WDT_CPU_RESET_LENGTH and RTC_CNTL_WDT_SYS_RESET_LENGTH */ -#define LP_WDT_RESET_LENGTH_100_NS 0 -#define LP_WDT_RESET_LENGTH_200_NS 1 -#define LP_WDT_RESET_LENGTH_300_NS 2 -#define LP_WDT_RESET_LENGTH_400_NS 3 -#define LP_WDT_RESET_LENGTH_500_NS 4 -#define LP_WDT_RESET_LENGTH_800_NS 5 -#define LP_WDT_RESET_LENGTH_1600_NS 6 -#define LP_WDT_RESET_LENGTH_3200_NS 7 - -#define LP_WDT_STG_SEL_OFF 0 -#define LP_WDT_STG_SEL_INT 1 -#define LP_WDT_STG_SEL_RESET_CPU 2 -#define LP_WDT_STG_SEL_RESET_SYSTEM 3 -#define LP_WDT_STG_SEL_RESET_RTC 4 - -//Type check wdt_stage_action_t -ESP_STATIC_ASSERT(WDT_STAGE_ACTION_OFF == LP_WDT_STG_SEL_OFF, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); -ESP_STATIC_ASSERT(WDT_STAGE_ACTION_INT == LP_WDT_STG_SEL_INT, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); -ESP_STATIC_ASSERT(WDT_STAGE_ACTION_RESET_CPU == LP_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); -ESP_STATIC_ASSERT(WDT_STAGE_ACTION_RESET_SYSTEM == LP_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); -ESP_STATIC_ASSERT(WDT_STAGE_ACTION_RESET_RTC == LP_WDT_STG_SEL_RESET_RTC, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); -//Type check wdt_reset_sig_length_t -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_100ns == LP_WDT_RESET_LENGTH_100_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_200ns == LP_WDT_RESET_LENGTH_200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_300ns == LP_WDT_RESET_LENGTH_300_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_400ns == LP_WDT_RESET_LENGTH_400_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_500ns == LP_WDT_RESET_LENGTH_500_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_800ns == LP_WDT_RESET_LENGTH_800_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_1_6us == LP_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_3_2us == LP_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); - -/** - * @brief Enable the RWDT - * - * @param hw Start address of the peripheral registers. - */ -FORCE_INLINE_ATTR void lpwdt_ll_enable(lp_wdt_dev_t *hw) -{ - hw->config0.wdt_en = 1; -} - -/** - * @brief Disable the RWDT - * - * @param hw Start address of the peripheral registers. - * @note This function does not disable the flashboot mode. Therefore, given that - * the MWDT is disabled using this function, a timeout can still occur - * if the flashboot mode is simultaneously enabled. - */ -FORCE_INLINE_ATTR void lpwdt_ll_disable(lp_wdt_dev_t *hw) -{ - hw->config0.wdt_en = 0; -} - -/** - * @brief Check if the RWDT is enabled - * - * @param hw Start address of the peripheral registers. - * @return True if RTC WDT is enabled - */ -FORCE_INLINE_ATTR bool lpwdt_ll_check_if_enabled(lp_wdt_dev_t *hw) -{ - return (hw->config0.wdt_en) ? true : false; -} - -/** - * @brief Configure a particular stage of the RWDT - * - * @param hw Start address of the peripheral registers. - * @param stage Which stage to configure - * @param timeout Number of timer ticks for the stage to timeout (see note). - * @param behavior What action to take when the stage times out - * - * @note The value of of RWDT stage 0 timeout register is special, in - * that an implicit multiplier is applied to that value to produce - * and effective timeout tick value. The multiplier is dependent - * on an EFuse value. Therefore, when configuring stage 0, the valid - * values for the timeout argument are: - * - If Efuse value is 0, any even number between [2,2*UINT32_MAX] - * - If Efuse value is 1, any multiple of 4 between [4,4*UINT32_MAX] - * - If Efuse value is 2, any multiple of 8 between [8,8*UINT32_MAX] - * - If Efuse value is 3, any multiple of 16 between [16,16*UINT32_MAX] - */ -FORCE_INLINE_ATTR void lpwdt_ll_config_stage(lp_wdt_dev_t *hw, wdt_stage_t stage, uint32_t timeout_ticks, wdt_stage_action_t behavior) -{ - switch (stage) { - case WDT_STAGE0: - hw->config0.wdt_stg0 = behavior; - //Account of implicty multiplier applied to stage 0 timeout tick config value - hw->config1.val = timeout_ticks >> (1 + REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_WDT_DELAY_SEL)); - break; - case WDT_STAGE1: - hw->config0.wdt_stg1 = behavior; - hw->config2.val = timeout_ticks; - break; - case WDT_STAGE2: - hw->config0.wdt_stg2 = behavior; - hw->config3.val = timeout_ticks; - break; - case WDT_STAGE3: - hw->config0.wdt_stg3 = behavior; - hw->config4.val = timeout_ticks; - break; - default: - abort(); - } -} - -/** - * @brief Disable a particular stage of the RWDT - * - * @param hw Start address of the peripheral registers. - * @param stage Which stage to disable - */ -FORCE_INLINE_ATTR void lpwdt_ll_disable_stage(lp_wdt_dev_t *hw, wdt_stage_t stage) -{ - switch (stage) { - case WDT_STAGE0: - hw->config0.wdt_stg0 = WDT_STAGE_ACTION_OFF; - break; - case WDT_STAGE1: - hw->config0.wdt_stg1 = WDT_STAGE_ACTION_OFF; - break; - case WDT_STAGE2: - hw->config0.wdt_stg2 = WDT_STAGE_ACTION_OFF; - break; - case WDT_STAGE3: - hw->config0.wdt_stg3 = WDT_STAGE_ACTION_OFF; - break; - default: - abort(); - } -} - -/** - * @brief Set the length of the CPU reset action - * - * @param hw Start address of the peripheral registers. - * @param length Length of CPU reset signal - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_cpu_reset_length(lp_wdt_dev_t *hw, wdt_reset_sig_length_t length) -{ - hw->config0.wdt_cpu_reset_length = length; -} - -/** - * @brief Set the length of the system reset action - * - * @param hw Start address of the peripheral registers. - * @param length Length of system reset signal - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_sys_reset_length(lp_wdt_dev_t *hw, wdt_reset_sig_length_t length) -{ - hw->config0.wdt_sys_reset_length = length; -} - -/** - * @brief Enable/Disable the RWDT flashboot mode. - * - * @param hw Start address of the peripheral registers. - * @param enable True to enable RWDT flashboot mode, false to disable RWDT flashboot mode. - * - * @note Flashboot mode is independent and can trigger a WDT timeout event if the - * WDT's enable bit is set to 0. Flashboot mode for RWDT is automatically enabled - * on flashboot, and should be disabled by software when flashbooting completes. - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_flashboot_en(lp_wdt_dev_t *hw, bool enable) -{ - hw->config0.wdt_flashboot_mod_en = (enable) ? 1 : 0; -} - -/** - * @brief Enable/Disable the CPU0 to be reset on WDT_STAGE_ACTION_RESET_CPU - * - * @param hw Start address of the peripheral registers. - * @param enable True to enable CPU0 to be reset, false to disable. - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_procpu_reset_en(lp_wdt_dev_t *hw, bool enable) -{ - hw->config0.wdt_procpu_reset_en = (enable) ? 1 : 0; -} - -/** - * @brief Enable/Disable the CPU1 to be reset on WDT_STAGE_ACTION_RESET_CPU - * - * @param hw Start address of the peripheral registers. - * @param enable True to enable CPU1 to be reset, false to disable. - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_appcpu_reset_en(lp_wdt_dev_t *hw, bool enable) -{ - hw->config0.wdt_appcpu_reset_en = (enable) ? 1 : 0; -} - -/** - * @brief Enable/Disable the RWDT pause during sleep functionality - * - * @param hw Start address of the peripheral registers. - * @param enable True to enable, false to disable. - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_pause_in_sleep_en(lp_wdt_dev_t *hw, bool enable) -{ - hw->config0.wdt_pause_in_slp = (enable) ? 1 : 0; -} - -/** - * @brief Enable/Disable chip reset on RWDT timeout. - * - * A chip reset also resets the analog portion of the chip. It will appear as a - * POWERON reset rather than an RTC reset. - * - * @param hw Start address of the peripheral registers. - * @param enable True to enable, false to disable. - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_chip_reset_en(lp_wdt_dev_t *hw, bool enable) -{ - // hw->config0.wdt_chip_reset_en = (enable) ? 1 : 0; -} - -/** - * @brief Set width of chip reset signal - * - * @param hw Start address of the peripheral registers. - * @param width Width of chip reset signal in terms of number of RTC_SLOW_CLK cycles - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_chip_reset_width(lp_wdt_dev_t *hw, uint32_t width) -{ - // HAL_FORCE_MODIFY_U32_REG_FIELD(hw->config0, wdt_chip_reset_width, width); -} - -/** - * @brief Feed the RWDT - * - * Resets the current timer count and current stage. - * - * @param hw Start address of the peripheral registers. - */ -FORCE_INLINE_ATTR void lpwdt_ll_feed(lp_wdt_dev_t *hw) -{ - // hw->feed.rtc_wdt_feed = 1; -} - -/** - * @brief Enable write protection of the RWDT registers - * - * @param hw Start address of the peripheral registers. - */ -FORCE_INLINE_ATTR void lpwdt_ll_write_protect_enable(lp_wdt_dev_t *hw) -{ - hw->wprotect.val = 0; -} - -/** - * @brief Disable write protection of the RWDT registers - * - * @param hw Start address of the peripheral registers. - */ -FORCE_INLINE_ATTR void lpwdt_ll_write_protect_disable(lp_wdt_dev_t *hw) -{ - hw->wprotect.val = LP_WDT_WKEY_VALUE; -} - -/** - * @brief Enable the RWDT interrupt. - * - * @param hw Start address of the peripheral registers. - * @param enable True to enable RWDT interrupt, false to disable. - */ -FORCE_INLINE_ATTR void lpwdt_ll_set_intr_enable(lp_wdt_dev_t *hw, bool enable) -{ - hw->int_ena.lp_wdt_int_ena = (enable) ? 1 : 0; -} - -/** - * @brief Check if the RWDT interrupt has been triggered - * - * @param hw Start address of the peripheral registers. - * @return True if the RWDT interrupt was triggered - */ -FORCE_INLINE_ATTR bool lpwdt_ll_check_intr_status(lp_wdt_dev_t *hw) -{ - return (hw->int_st.lp_wdt_int_st) ? true : false; -} - -/** - * @brief Clear the RWDT interrupt status. - * - * @param hw Start address of the peripheral registers. - */ -FORCE_INLINE_ATTR void lpwdt_ll_clear_intr_status(lp_wdt_dev_t *hw) -{ - hw->int_clr.lp_wdt_int_clr = 1; -} - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hal_wdt/esp32s31/include/hal/rwdt_ll.h b/components/esp_hal_wdt/esp32s31/include/hal/rwdt_ll.h index e10f16f9b4..f4355fcbf0 100644 --- a/components/esp_hal_wdt/esp32s31/include/hal/rwdt_ll.h +++ b/components/esp_hal_wdt/esp32s31/include/hal/rwdt_ll.h @@ -1,10 +1,8 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer for RTC(LP) watchdog register operations. -// Note that most of the register operations in this layer are non-atomic operations. #pragma once @@ -12,70 +10,321 @@ extern "C" { #endif -#include "hal/lpwdt_ll.h" +#include +#include +#include "hal/misc.h" +#include "hal/wdt_types.h" +#include "soc/rtc_cntl_periph.h" +#include "soc/efuse_reg.h" +#include "esp_attr.h" +#include "esp_assert.h" -// TODO: ["ESP32S31"] IDF-14656 +#include "esp32s31/rom/ets_sys.h" -typedef lp_wdt_dev_t rwdt_dev_t; +// TODO: ["ESP32S31"] IDF-14636 -#define RWDT_DEV_GET() &LP_WDT +/* The value that needs to be written to RTC_WDT_WPROTECT_REG to write-enable the wdt registers */ +#define RTC_WDT_WKEY_VALUE 0x50D83AA1 +/* The value that needs to be written to RTC_WDT_SWD_WPROTECT_REG to write-enable the swd registers */ +#define RTC_WDT_SWD_WKEY_VALUE 0x50D83AA1 -#define rwdt_ll_enable(hw) \ - lpwdt_ll_enable(hw) +/* Possible values for RTC_CNTL_WDT_CPU_RESET_LENGTH and RTC_CNTL_WDT_SYS_RESET_LENGTH */ +#define RTC_WDT_RESET_LENGTH_100_NS 0 +#define RTC_WDT_RESET_LENGTH_200_NS 1 +#define RTC_WDT_RESET_LENGTH_300_NS 2 +#define RTC_WDT_RESET_LENGTH_400_NS 3 +#define RTC_WDT_RESET_LENGTH_500_NS 4 +#define RTC_WDT_RESET_LENGTH_800_NS 5 +#define RTC_WDT_RESET_LENGTH_1600_NS 6 +#define RTC_WDT_RESET_LENGTH_3200_NS 7 -#define rwdt_ll_disable(hw) \ - lpwdt_ll_disable(hw) +#define RTC_WDT_STG_SEL_OFF 0 +#define RTC_WDT_STG_SEL_INT 1 +#define RTC_WDT_STG_SEL_RESET_CPU 2 +#define RTC_WDT_STG_SEL_RESET_SYSTEM 3 +#define RTC_WDT_STG_SEL_RESET_RTC 4 -#define rwdt_ll_check_if_enabled(hw) \ - lpwdt_ll_check_if_enabled(hw) +//Type check wdt_stage_action_t +ESP_STATIC_ASSERT(WDT_STAGE_ACTION_OFF == RTC_WDT_STG_SEL_OFF, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); +ESP_STATIC_ASSERT(WDT_STAGE_ACTION_INT == RTC_WDT_STG_SEL_INT, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); +ESP_STATIC_ASSERT(WDT_STAGE_ACTION_RESET_CPU == RTC_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); +ESP_STATIC_ASSERT(WDT_STAGE_ACTION_RESET_SYSTEM == RTC_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); +ESP_STATIC_ASSERT(WDT_STAGE_ACTION_RESET_RTC == RTC_WDT_STG_SEL_RESET_RTC, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t"); +//Type check wdt_reset_sig_length_t +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_100ns == RTC_WDT_RESET_LENGTH_100_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_200ns == RTC_WDT_RESET_LENGTH_200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_300ns == RTC_WDT_RESET_LENGTH_300_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_400ns == RTC_WDT_RESET_LENGTH_400_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_500ns == RTC_WDT_RESET_LENGTH_500_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_800ns == RTC_WDT_RESET_LENGTH_800_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_1_6us == RTC_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +ESP_STATIC_ASSERT(WDT_RESET_SIG_LENGTH_3_2us == RTC_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); -#define rwdt_ll_config_stage(hw, stage, timeout_ticks, behavior) \ - lpwdt_ll_config_stage(hw, stage, timeout_ticks, behavior) +typedef rtc_wdt_dev_t rwdt_dev_t; -#define rwdt_ll_disable_stage(hw, stage) \ - lpwdt_ll_disable_stage(hw, stage) +#define RWDT_DEV_GET() &RTC_WDT -#define rwdt_ll_set_cpu_reset_length(hw, length) \ - lpwdt_ll_set_cpu_reset_length(hw, length) +/** + * @brief Enable the RWDT + * + * @param hw Start address of the peripheral registers. + */ +FORCE_INLINE_ATTR void rwdt_ll_enable(rwdt_dev_t *hw) +{ + hw->config0.wdt_en = 1; +} -#define rwdt_ll_set_sys_reset_length(hw, length) \ - lpwdt_ll_set_sys_reset_length(hw, length) +/** + * @brief Disable the RWDT + * + * @param hw Start address of the peripheral registers. + * @note This function does not disable the flashboot mode. Therefore, given that + * the MWDT is disabled using this function, a timeout can still occur + * if the flashboot mode is simultaneously enabled. + */ +FORCE_INLINE_ATTR void rwdt_ll_disable(rwdt_dev_t *hw) +{ + hw->config0.wdt_en = 0; +} -#define rwdt_ll_set_flashboot_en(hw, enable) \ - lpwdt_ll_set_flashboot_en(hw, enable) +/** + * @brief Check if the RWDT is enabled + * + * @param hw Start address of the peripheral registers. + * @return True if RTC WDT is enabled + */ +FORCE_INLINE_ATTR bool rwdt_ll_check_if_enabled(rwdt_dev_t *hw) +{ + return (hw->config0.wdt_en) ? true : false; +} -#define rwdt_ll_set_procpu_reset_en(hw, enable) \ - lpwdt_ll_set_procpu_reset_en(hw, enable) +/** + * @brief Configure a particular stage of the RWDT + * + * @param hw Start address of the peripheral registers. + * @param stage Which stage to configure + * @param timeout Number of timer ticks for the stage to timeout (see note). + * @param behavior What action to take when the stage times out + * + * @note The value of of RWDT stage 0 timeout register is special, in + * that an implicit multiplier is applied to that value to produce + * and effective timeout tick value. The multiplier is dependent + * on an EFuse value. Therefore, when configuring stage 0, the valid + * values for the timeout argument are: + * - If Efuse value is 0, any even number between [2,2*UINT32_MAX] + * - If Efuse value is 1, any multiple of 4 between [4,4*UINT32_MAX] + * - If Efuse value is 2, any multiple of 8 between [8,8*UINT32_MAX] + * - If Efuse value is 3, any multiple of 16 between [16,16*UINT32_MAX] + */ +FORCE_INLINE_ATTR void rwdt_ll_config_stage(rwdt_dev_t *hw, wdt_stage_t stage, uint32_t timeout_ticks, wdt_stage_action_t behavior) +{ + switch (stage) { + case WDT_STAGE0: + hw->config0.wdt_stg0 = behavior; + //Account of implicty multiplier applied to stage 0 timeout tick config value + hw->config1.val = timeout_ticks >> (1 + REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_WDT_DELAY_SEL)); + break; + case WDT_STAGE1: + hw->config0.wdt_stg1 = behavior; + hw->config2.val = timeout_ticks; + break; + case WDT_STAGE2: + hw->config0.wdt_stg2 = behavior; + hw->config3.val = timeout_ticks; + break; + case WDT_STAGE3: + hw->config0.wdt_stg3 = behavior; + hw->config4.val = timeout_ticks; + break; + default: + abort(); + } +} -#define rwdt_ll_set_appcpu_reset_en(hw, enable) \ - lpwdt_ll_set_appcpu_reset_en(hw, enable) +/** + * @brief Disable a particular stage of the RWDT + * + * @param hw Start address of the peripheral registers. + * @param stage Which stage to disable + */ +FORCE_INLINE_ATTR void rwdt_ll_disable_stage(rwdt_dev_t *hw, wdt_stage_t stage) +{ + switch (stage) { + case WDT_STAGE0: + hw->config0.wdt_stg0 = WDT_STAGE_ACTION_OFF; + break; + case WDT_STAGE1: + hw->config0.wdt_stg1 = WDT_STAGE_ACTION_OFF; + break; + case WDT_STAGE2: + hw->config0.wdt_stg2 = WDT_STAGE_ACTION_OFF; + break; + case WDT_STAGE3: + hw->config0.wdt_stg3 = WDT_STAGE_ACTION_OFF; + break; + default: + abort(); + } +} -#define rwdt_ll_set_pause_in_sleep_en(hw, enable) \ - lpwdt_ll_set_pause_in_sleep_en(hw, enable) +/** + * @brief Set the length of the CPU reset action + * + * @param hw Start address of the peripheral registers. + * @param length Length of CPU reset signal + */ +FORCE_INLINE_ATTR void rwdt_ll_set_cpu_reset_length(rwdt_dev_t *hw, wdt_reset_sig_length_t length) +{ + hw->config0.wdt_cpu_reset_length = length; +} -#define rwdt_ll_set_chip_reset_en(hw, enable) \ - lpwdt_ll_set_chip_reset_en(hw, enable) +/** + * @brief Set the length of the system reset action + * + * @param hw Start address of the peripheral registers. + * @param length Length of system reset signal + */ +FORCE_INLINE_ATTR void rwdt_ll_set_sys_reset_length(rwdt_dev_t *hw, wdt_reset_sig_length_t length) +{ + hw->config0.wdt_sys_reset_length = length; +} -#define rwdt_ll_set_chip_reset_width(hw, width) \ - lpwdt_ll_set_chip_reset_width(hw, width) +/** + * @brief Enable/Disable the RWDT flashboot mode. + * + * @param hw Start address of the peripheral registers. + * @param enable True to enable RWDT flashboot mode, false to disable RWDT flashboot mode. + * + * @note Flashboot mode is independent and can trigger a WDT timeout event if the + * WDT's enable bit is set to 0. Flashboot mode for RWDT is automatically enabled + * on flashboot, and should be disabled by software when flashbooting completes. + */ +FORCE_INLINE_ATTR void rwdt_ll_set_flashboot_en(rwdt_dev_t *hw, bool enable) +{ + hw->config0.wdt_flashboot_mod_en = (enable) ? 1 : 0; +} -#define rwdt_ll_feed(hw) \ - lpwdt_ll_feed(hw) +/** + * @brief Enable/Disable the CPU0 to be reset on WDT_STAGE_ACTION_RESET_CPU + * + * @param hw Start address of the peripheral registers. + * @param enable True to enable CPU0 to be reset, false to disable. + */ +FORCE_INLINE_ATTR void rwdt_ll_set_procpu_reset_en(rwdt_dev_t *hw, bool enable) +{ + hw->config0.wdt_procpu_reset_en = (enable) ? 1 : 0; +} -#define rwdt_ll_write_protect_enable(hw) \ - lpwdt_ll_write_protect_enable(hw) +/** + * @brief Enable/Disable the CPU1 to be reset on WDT_STAGE_ACTION_RESET_CPU + * + * @param hw Start address of the peripheral registers. + * @param enable True to enable CPU1 to be reset, false to disable. + */ +FORCE_INLINE_ATTR void rwdt_ll_set_appcpu_reset_en(rwdt_dev_t *hw, bool enable) +{ + hw->config0.wdt_appcpu_reset_en = (enable) ? 1 : 0; +} -#define rwdt_ll_write_protect_disable(hw) \ - lpwdt_ll_write_protect_disable(hw) +/** + * @brief Enable/Disable the RWDT pause during sleep functionality + * + * @param hw Start address of the peripheral registers. + * @param enable True to enable, false to disable. + */ +FORCE_INLINE_ATTR void rwdt_ll_set_pause_in_sleep_en(rwdt_dev_t *hw, bool enable) +{ + hw->config0.wdt_pause_in_slp = (enable) ? 1 : 0; +} -#define rwdt_ll_set_intr_enable(hw, enable) \ - lpwdt_ll_set_intr_enable(hw, enable) +/** + * @brief Enable/Disable chip reset on RWDT timeout. + * + * A chip reset also resets the analog portion of the chip. It will appear as a + * POWERON reset rather than an RTC reset. + * + * @param hw Start address of the peripheral registers. + * @param enable True to enable, false to disable. + */ +FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rwdt_dev_t *hw, bool enable) +{ + // hw->config0.wdt_chip_reset_en = (enable) ? 1 : 0; +} -#define rwdt_ll_check_intr_status(hw) \ - lpwdt_ll_check_intr_status(hw) +/** + * @brief Set width of chip reset signal + * + * @param hw Start address of the peripheral registers. + * @param width Width of chip reset signal in terms of number of RTC_SLOW_CLK cycles + */ +FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rwdt_dev_t *hw, uint32_t width) +{ + // HAL_FORCE_MODIFY_U32_REG_FIELD(hw->config0, wdt_chip_reset_width, width); +} -#define rwdt_ll_clear_intr_status(hw) \ - lpwdt_ll_clear_intr_status(hw) +/** + * @brief Feed the RWDT + * + * Resets the current timer count and current stage. + * + * @param hw Start address of the peripheral registers. + */ +FORCE_INLINE_ATTR void rwdt_ll_feed(rwdt_dev_t *hw) +{ + // hw->feed.rtc_wdt_feed = 1; +} + +/** + * @brief Enable write protection of the RWDT registers + * + * @param hw Start address of the peripheral registers. + */ +FORCE_INLINE_ATTR void rwdt_ll_write_protect_enable(rwdt_dev_t *hw) +{ + hw->wprotect.val = 0; +} + +/** + * @brief Disable write protection of the RWDT registers + * + * @param hw Start address of the peripheral registers. + */ +FORCE_INLINE_ATTR void rwdt_ll_write_protect_disable(rwdt_dev_t *hw) +{ + hw->wprotect.val = RTC_WDT_WKEY_VALUE; +} + +/** + * @brief Enable the RWDT interrupt. + * + * @param hw Start address of the peripheral registers. + * @param enable True to enable RWDT interrupt, false to disable. + */ +FORCE_INLINE_ATTR void rwdt_ll_set_intr_enable(rwdt_dev_t *hw, bool enable) +{ + hw->int_ena.lp_wdt_int_ena = (enable) ? 1 : 0; +} + +/** + * @brief Check if the RWDT interrupt has been triggered + * + * @param hw Start address of the peripheral registers. + * @return True if the RWDT interrupt was triggered + */ +FORCE_INLINE_ATTR bool rwdt_ll_check_intr_status(rwdt_dev_t *hw) +{ + return (hw->int_st.lp_wdt_int_st) ? true : false; +} + +/** + * @brief Clear the RWDT interrupt status. + * + * @param hw Start address of the peripheral registers. + */ +FORCE_INLINE_ATTR void rwdt_ll_clear_intr_status(rwdt_dev_t *hw) +{ + hw->int_clr.lp_wdt_int_clr = 1; +} #ifdef __cplusplus } diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 550d139b9a..957d494af4 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -75,7 +75,7 @@ typedef enum { #define RTC_GPIO_TRIG_EN (PMU_GPIO_WAKEUP_EN) #endif -#if SOC_RTC_TIMER_V2_SUPPORTED +#if !SOC_RTC_TIMER_V1 #define RTC_TIMER_TRIG_EN PMU_LP_TIMER_WAKEUP_EN //!< Timer wakeup #else #define RTC_TIMER_TRIG_EN 0 diff --git a/components/esp_hw_support/test_apps/rtc_clk/main/test_rtc_clk.c b/components/esp_hw_support/test_apps/rtc_clk/main/test_rtc_clk.c index 4ab99a9f65..e5beeceaa8 100644 --- a/components/esp_hw_support/test_apps/rtc_clk/main/test_rtc_clk.c +++ b/components/esp_hw_support/test_apps/rtc_clk/main/test_rtc_clk.c @@ -247,7 +247,7 @@ static void start_freq(soc_rtc_slow_clk_src_t required_src, uint32_t start_delay printf("PASS. Time measurement..."); } uint32_t fail_measure = 0; -#if SOC_RTC_TIMER_V2_SUPPORTED +#if !SOC_RTC_TIMER_V1 uint64_t clk_rtc_time; for (int j = 0; j < 3; ++j) { clk_rtc_time = esp_clk_rtc_time(); @@ -338,7 +338,7 @@ TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_ #endif // !defined(CONFIG_IDF_CI_BUILD) || !CONFIG_SPIRAM_BANKSWITCH_ENABLE #endif // SOC_CLK_XTAL32K_SUPPORTED -#if SOC_RTC_TIMER_V2_SUPPORTED +#if !SOC_RTC_TIMER_V1 TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]") { int64_t t1 = esp_rtc_get_time_us(); diff --git a/components/esp_rom/esp32s31/include/esp32s31/rom/rtc.h b/components/esp_rom/esp32s31/include/esp32s31/rom/rtc.h index a8c964a032..778061b948 100644 --- a/components/esp_rom/esp32s31/include/esp32s31/rom/rtc.h +++ b/components/esp_rom/esp32s31/include/esp32s31/rom/rtc.h @@ -4,15 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef _ROM_RTC_H_ -#define _ROM_RTC_H_ +#pragma once + #ifdef __cplusplus extern "C" { #endif +#include +#include +#include "esp_assert.h" +#include "soc/soc.h" #include "soc/lp_system_reg.h" -#include "soc/lp_clkrst_reg.h" +#include "soc/reset_reasons.h" /** \defgroup rtc_apis, rtc registers and memory related apis * @brief rtc apis @@ -44,22 +48,16 @@ extern "C" { * RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC ************************************************************************************* */ -#define RTC_CNTL_STORE0_REG LP_SYSTEM_REG_LP_STORE0_REG -#define RTC_CNTL_STORE1_REG LP_SYSTEM_REG_LP_STORE1_REG -#define RTC_CNTL_STORE2_REG LP_SYSTEM_REG_LP_STORE2_REG -#define RTC_CNTL_STORE3_REG LP_SYSTEM_REG_LP_STORE3_REG -#define RTC_CNTL_STORE4_REG LP_SYSTEM_REG_LP_STORE4_REG -#define RTC_CNTL_STORE5_REG LP_SYSTEM_REG_LP_STORE5_REG -#define RTC_CNTL_STORE6_REG LP_SYSTEM_REG_LP_STORE6_REG -#define RTC_CNTL_STORE7_REG LP_SYSTEM_REG_LP_STORE7_REG -#define RTC_CNTL_STORE8_REG LP_SYSTEM_REG_LP_STORE8_REG -#define RTC_CNTL_STORE9_REG LP_SYSTEM_REG_LP_STORE9_REG -#define RTC_CNTL_STORE10_REG LP_SYSTEM_REG_LP_STORE10_REG -#define RTC_CNTL_STORE11_REG LP_SYSTEM_REG_LP_STORE11_REG -#define RTC_CNTL_STORE12_REG LP_SYSTEM_REG_LP_STORE12_REG -#define RTC_CNTL_STORE13_REG LP_SYSTEM_REG_LP_STORE13_REG -#define RTC_CNTL_STORE14_REG LP_SYSTEM_REG_LP_STORE14_REG -#define RTC_CNTL_STORE15_REG LP_SYSTEM_REG_LP_STORE15_REG + +#define RTC_SLOW_CLK_CAL_REG LP_SYSTEM_REG_LP_STORE1_REG +#define RTC_BOOT_TIME_LOW_REG LP_SYSTEM_REG_LP_STORE2_REG +#define RTC_BOOT_TIME_HIGH_REG LP_SYSTEM_REG_LP_STORE3_REG +#define RTC_XTAL_FREQ_REG LP_SYSTEM_REG_LP_STORE4_REG +#define RTC_ENTRY_LENGTH_REG LP_SYSTEM_REG_LP_STORE5_REG +#define RTC_ENTRY_ADDR_REG LP_SYSTEM_REG_LP_STORE6_REG +#define RTC_RESET_CAUSE_REG LP_SYSTEM_REG_LP_STORE6_REG +#define RTC_MEMORY_CRC_REG LP_SYSTEM_REG_LP_STORE7_REG + // light sleep /* use LP_SYS_LP_STORE8_REG to store light sleep wake stub addr and sleep mode for dualcore * @@ -71,53 +69,120 @@ extern "C" { /* this MACRO is common to hpcore and lpcore * they use different bitmask to check same value */ -#define SLEEP_MODE_LIGHT_SLEEP 0 -// hpcore use bit0 to check the mode -#define SLEEP_MODE_MASK BIT(0) +#define RTC_SLEEP_WAKE_STUB_ADDR_REG LP_SYSTEM_REG_LP_STORE8_REG +#define RTC_SLEEP_MODE_REG LP_SYSTEM_REG_LP_STORE8_REG -#define RTC_LIGHT_SLEEP_WAKE_STUB_ADDR_REG RTC_CNTL_STORE8_REG -#define RTC_LIGHT_SLEEP_RESTORE_FUNC_ADDR_MASK 0xFFFFFFFC -#define SLEEP_MODE_REG RTC_CNTL_STORE8_REG -// system -#define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG -#define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG -#define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG -#define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG -// deep sleep -#define RTC_ENTRY_LENGTH_REG RTC_CNTL_STORE5_REG -#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG -/* use RTC_ENTRY_ADDR_REG[0] to store if we need do stub crc check - * 0: we do not need do crc check, then RTC_MEMORY_CRC_REG and RTC_ENTRY_LENGTH_REG can be freed - * 1: we need do crc check -*/ -#define RTC_DEEP_SLEEP_STUB_CHECK_CRC 0x1 -#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG -#define ROM_LOG_CTRL_REG RTC_XTAL_FREQ_REG +#define ROM_LOG_CTRL_REG LP_SYSTEM_REG_LP_STORE4_REG +#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. -/* Reset reason hint register - same as RTC_ENTRY_ADDR_REG, can be used for both - * deep sleep wake stub entry address and reset reason hint, since wake stub - * is only used for deep sleep reset. - */ -#define RTC_RESET_CAUSE_REG RTC_ENTRY_ADDR_REG -// used to check if app core need hot boot in start.S -#define APP_CORE_BOOT_ADDR_REG LP_SYS_BOOT_ADDR_HP_CORE1_REG -// used to check if we need do software retention in start.S -#define RESET_REASON_REG LP_AONCLKRST_HPCORE0_RESET_CAUSE_REG -#define RESET_REASON_MASK LP_AONCLKRST_HPCORE0_RESET_CAUSE -#define CORE0_RESET_REASON_POS LP_AONCLKRST_HPCORE0_RESET_CAUSE_S -#define RESET_REASON1_REG LP_AONCLKRST_HPCORE0_RESET_CAUSE_REG -#define RESET_REASON1_MASK LP_AONCLKRST_HPCORE0_RESET_CAUSE -#define CORE1_RESET_REASON_POS LP_AONCLKRST_HPCORE1_RESET_CAUSE_S +typedef enum { + AWAKE = 0, // +#include "esp_attr.h" +#include "soc/soc.h" +#include "soc/lp_system_struct.h" +#include "hal/misc.h" +#include "esp32s31/rom/rtc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ROM obtains the wake-up type through LP_SYS_STORE9_REG[0]. + * Set the flag to inform + * @param true: deepsleep false: lightsleep + */ +FORCE_INLINE_ATTR void lp_sys_ll_inform_wakeup_type(bool dslp) +{ + if (dslp) { + REG_SET_BIT(RTC_SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */ + + } else { + REG_CLR_BIT(RTC_SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */ + } +} + +FORCE_INLINE_ATTR void lp_sys_ll_set_pau_aon_bypass(bool bypass) +{ + LP_SYS.backup_dma_cfg1.aon_bypass = bypass ? 1 : 0; +} + +FORCE_INLINE_ATTR void lp_sys_ll_set_pau_link_tout_thres(uint32_t tout) +{ + LP_SYS.backup_dma_cfg1.link_wait_tout_thres_aon = tout; + LP_SYS.backup_dma_cfg1.link_work_tout_thres_aon = tout; +} + +FORCE_INLINE_ATTR void lp_sys_ll_set_pau_link_backup_tout_thres(uint32_t tout) +{ + LP_SYS.backup_dma_cfg0.link_backup_tout_thres_aon = tout; +} + +FORCE_INLINE_ATTR void lp_sys_ll_set_pau_reg_read_interval(uint32_t val) +{ + LP_SYS.backup_dma_cfg0.read_interval_aon = val; +} + +FORCE_INLINE_ATTR void lp_sys_ll_set_pau_link_addr(uint32_t addr) +{ + LP_SYS.backup_dma_cfg2.link_addr_aon = addr; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 4c0305ab13..575d14a120 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -83,7 +83,7 @@ config SOC_RTC_MEM_SUPPORTED bool default y -config SOC_RTC_TIMER_V1_SUPPORTED +config SOC_RTC_TIMER_SUPPORTED bool default y @@ -519,6 +519,10 @@ config SOC_LP_TIMER_BIT_WIDTH_HI int default 16 +config SOC_RTC_TIMER_V1 + bool + default y + config SOC_TOUCH_SENSOR_VERSION int default 1 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 207020f926..b67ba9a2ac 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -86,7 +86,7 @@ #define SOC_RTC_FAST_MEM_SUPPORTED 1 #define SOC_RTC_SLOW_MEM_SUPPORTED 1 #define SOC_RTC_MEM_SUPPORTED 1 -#define SOC_RTC_TIMER_V1_SUPPORTED 1 +#define SOC_RTC_TIMER_SUPPORTED 1 #define SOC_I2S_SUPPORTED 1 #define SOC_I2S_I80_LCD_SUPPORTED 1 #define SOC_LCD_I80_SUPPORTED 1 @@ -262,7 +262,7 @@ /*-------------------------- LP_TIMER CAPS ----------------------------------*/ #define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part #define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part -#define SOC_RTC_TIMER_SUPPORTED SOC_RTC_TIMER_V1_SUPPORTED +#define SOC_RTC_TIMER_V1 1 /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_VERSION (1U) /*!wakeup_source & ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER) { diff --git a/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h b/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h index 6be9b007b2..7297f7a45c 100644 --- a/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h +++ b/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h @@ -141,7 +141,7 @@ static inline void ulp_lp_core_sw_intr_clear(void) return ulp_lp_core_sw_intr_from_hp_clear(); } -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED /** * @brief Enable the LP Timer interrupt * diff --git a/components/ulp/lp_core/lp_core/lp_core_startup.c b/components/ulp/lp_core/lp_core/lp_core_startup.c index d9dd63606c..ed59afd436 100644 --- a/components/ulp/lp_core/lp_core/lp_core_startup.c +++ b/components/ulp/lp_core/lp_core/lp_core_startup.c @@ -28,13 +28,13 @@ void lp_core_startup() ulp_lp_core_memory_shared_cfg_t* shared_mem = ulp_lp_core_memory_shared_cfg_get(); -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED uint64_t sleep_duration_ticks = shared_mem->sleep_duration_ticks; if (sleep_duration_ticks) { ulp_lp_core_lp_timer_set_wakeup_ticks(sleep_duration_ticks); } -#endif // SOC_RTC_TIMER_V2_SUPPORTED +#endif // SOC_RTC_TIMER_SUPPORTED ulp_lp_core_halt(); } diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c index cabf3070f9..48a60feea3 100644 --- a/components/ulp/lp_core/lp_core/lp_core_utils.c +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,7 @@ #include "hal/lp_i2s_ll.h" #endif -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED #include "hal/rtc_timer_ll.h" #endif @@ -82,13 +82,13 @@ void ulp_lp_core_update_wakeup_cause(void) } #endif /* SOC_ETM_SUPPORTED */ -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER) \ && (rtc_timer_ll_get_intr_raw(&LP_TIMER, 1) & LP_TIMER_MAIN_TIMER_LP_INT_RAW)) { lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER; rtc_timer_ll_clear_alarm_intr_status(&LP_TIMER, 1); } -#endif /* SOC_RTC_TIMER_V2_SUPPORTED */ +#endif /* SOC_RTC_TIMER_SUPPORTED */ } @@ -196,7 +196,7 @@ void ulp_lp_core_sw_intr_from_hp_clear(void) pmu_ll_lp_clear_sw_intr_status(&PMU); } -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED void ulp_lp_core_lp_timer_intr_enable(bool enable) { rtc_timer_ll_alarm_intr_enable(&LP_TIMER, 1, enable); diff --git a/components/ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c b/components/ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c index ba1bbf8280..88021e0194 100644 --- a/components/ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c +++ b/components/ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c @@ -6,7 +6,7 @@ #include "ulp_lp_core_lp_timer_shared.h" #include "soc/soc_caps.h" -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED #include "hal/rtc_timer_ll.h" #include "hal/clk_tree_ll.h" #include "soc/rtc.h" @@ -45,4 +45,4 @@ uint64_t ulp_lp_core_lp_timer_calculate_sleep_ticks(uint64_t sleep_duration_us) return (sleep_duration_us * (1 << RTC_CLK_CAL_FRACT) / clk_ll_rtc_slow_load_cal()); } -#endif // SOC_RTC_TIMER_V2_SUPPORTED +#endif // SOC_RTC_TIMER_SUPPORTED diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt index b343b9c605..577e258453 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt @@ -30,7 +30,7 @@ list(APPEND app_sources "test_lp_core_prefix.c") set(lp_core_sources "lp_core/test_main.c") set(lp_core_sources_counter "lp_core/test_main_counter.c") -if(CONFIG_SOC_RTC_TIMER_V2_SUPPORTED) +if(CONFIG_SOC_RTC_TIMER_SUPPORTED) set(lp_core_sources_set_timer_wakeup "lp_core/test_main_set_timer_wakeup.c") endif() @@ -71,7 +71,7 @@ ulp_embed_binary(lp_core_test_app "${lp_core_sources}" "${lp_core_exp_dep_srcs}" ulp_embed_binary(lp_core_test_app_counter "${lp_core_sources_counter}" "${lp_core_exp_dep_srcs}") ulp_embed_binary(lp_core_test_app_isr "lp_core/test_main_isr.c" "${lp_core_exp_dep_srcs}") -if(CONFIG_SOC_RTC_TIMER_V2_SUPPORTED) +if(CONFIG_SOC_RTC_TIMER_SUPPORTED) ulp_embed_binary(lp_core_test_app_set_timer_wakeup "${lp_core_sources_set_timer_wakeup}" "${lp_core_exp_dep_srcs}") endif() diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c index 2bd4de4fb7..a055ef9e73 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,7 @@ #include "lp_core_test_app_counter.h" #include "lp_core_test_app_isr.h" -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED #include "lp_core_test_app_set_timer_wakeup.h" #endif @@ -295,7 +295,7 @@ TEST_CASE("LP core can be stopped and and started again from main CPU", "[ulp]") } } -#if SOC_RTC_TIMER_V2_SUPPORTED +#if SOC_RTC_TIMER_SUPPORTED TEST_CASE("LP core can schedule next wake-up time by itself", "[ulp]") { int64_t start, test_duration; @@ -342,7 +342,7 @@ TEST_CASE("LP core gpio tests", "[ulp]") } #endif //SOC_RTCIO_PIN_COUNT > 0 -#endif // SOC_RTC_TIMER_V2_SUPPORTED +#endif // SOC_RTC_TIMER_SUPPORTED #define ISR_TEST_ITERATIONS 100 #define IO_TEST_PIN 0