From 709adaaa37a67fb3f901d8ce937c9021344fbdf9 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 17 Feb 2023 20:30:51 +0800 Subject: [PATCH 1/9] soc_caps: since esp32c6 only support one ext wakeup src, split SOC_PM_SUPPORT_EXT_WAKEUP Close IDF-5924 --- components/esp_hw_support/include/esp_sleep.h | 7 ++++--- components/esp_hw_support/sleep_modes.c | 21 +++++++++++++------ .../esp_system_unity_tests/main/test_sleep.c | 6 ++++-- components/hal/include/hal/rtc_hal.h | 4 ++-- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 8 +++++++ components/soc/esp32/include/soc/soc_caps.h | 5 ++++- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32c6/include/soc/soc_caps.h | 1 + .../esp32s2/include/soc/Kconfig.soc_caps.in | 8 +++++++ components/soc/esp32s2/include/soc/soc_caps.h | 5 ++++- .../esp32s3/include/soc/Kconfig.soc_caps.in | 8 +++++++ components/soc/esp32s3/include/soc/soc_caps.h | 5 ++++- docs/docs_not_updated/esp32c6.txt | 1 - .../api-reference/system/power_management.rst | 2 +- docs/en/api-reference/system/sleep_modes.rst | 8 +++---- .../api-reference/system/power_management.rst | 2 +- .../api-reference/system/sleep_modes.rst | 8 +++---- .../components/cmd_system/cmd_system.c | 2 +- .../components/cmd_system/cmd_system.c | 10 ++++----- .../system/deep_sleep/main/Kconfig.projbuild | 4 ++-- 20 files changed, 84 insertions(+), 35 deletions(-) diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index b9b861d2cc..2f9458fbad 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -193,8 +193,7 @@ touch_pad_t esp_sleep_get_touchpad_wakeup_status(void); */ bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num); -#if SOC_PM_SUPPORT_EXT_WAKEUP - +#if SOC_PM_SUPPORT_EXT0_WAKEUP /** * @brief Enable wakeup using a pin * @@ -223,7 +222,9 @@ bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num); * - ESP_ERR_INVALID_STATE if wakeup triggers conflict */ esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); +#endif // SOC_PM_SUPPORT_EXT0_WAKEUP +#if SOC_PM_SUPPORT_EXT1_WAKEUP /** * @brief Enable wakeup using multiple pins * @@ -259,7 +260,7 @@ esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); */ esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode); -#endif // SOC_PM_SUPPORT_EXT_WAKEUP +#endif // SOC_PM_SUPPORT_EXT1_WAKEUP #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP /** diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 6bb90be77c..a2edd0ddeb 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -207,8 +207,10 @@ void esp_sleep_periph_use_8m(bool use_or_not) } static uint32_t get_power_down_flags(void); -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT0_WAKEUP static void ext0_wakeup_prepare(void); +#endif +#if SOC_PM_SUPPORT_EXT1_WAKEUP static void ext1_wakeup_prepare(void); #endif static void timer_wakeup_prepare(void); @@ -433,11 +435,13 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo rtc_clk_cpu_freq_get_config(&cpu_freq_config); rtc_clk_cpu_freq_set_xtal(); -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT0_WAKEUP // Configure pins for external wakeup if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { ext0_wakeup_prepare(); } +#endif +#if SOC_PM_SUPPORT_EXT1_WAKEUP if (s_config.wakeup_triggers & RTC_EXT1_TRIG_EN) { ext1_wakeup_prepare(); } @@ -928,11 +932,13 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN; s_config.sleep_duration = 0; -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT0_WAKEUP } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) { s_config.ext0_rtc_gpio_num = 0; s_config.ext0_trigger_level = 0; s_config.wakeup_triggers &= ~RTC_EXT0_TRIG_EN; +#endif +#if SOC_PM_SUPPORT_EXT1_WAKEUP } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT1, RTC_EXT1_TRIG_EN)) { s_config.ext1_rtc_gpio_mask = 0; s_config.ext1_trigger_mode = 0; @@ -1071,8 +1077,7 @@ bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num) #endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED } -#if SOC_PM_SUPPORT_EXT_WAKEUP - +#if SOC_PM_SUPPORT_EXT0_WAKEUP esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level) { if (level < 0 || level > 1) { @@ -1101,7 +1106,9 @@ static void ext0_wakeup_prepare(void) rtcio_hal_function_select(rtc_gpio_num, RTCIO_FUNC_RTC); rtcio_hal_input_enable(rtc_gpio_num); } +#endif // SOC_PM_SUPPORT_EXT0_WAKEUP +#if SOC_PM_SUPPORT_EXT1_WAKEUP esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode) { if (mode > ESP_EXT1_WAKEUP_ANY_HIGH) { @@ -1339,9 +1346,11 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) return ESP_SLEEP_WAKEUP_GPIO; } else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) { return ESP_SLEEP_WAKEUP_UART; -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT0_WAKEUP } else if (wakeup_cause & RTC_EXT0_TRIG_EN) { return ESP_SLEEP_WAKEUP_EXT0; +#endif +#if SOC_PM_SUPPORT_EXT1_WAKEUP } else if (wakeup_cause & RTC_EXT1_TRIG_EN) { return ESP_SLEEP_WAKEUP_EXT1; #endif diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index 2452a1b00a..659892177b 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -386,7 +386,7 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub from stack in RTC RAM", "[dee #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT0_WAKEUP TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]") { ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); @@ -404,7 +404,9 @@ TEST_CASE("wake up using ext0 (13 low)", "[deepsleep][ignore]") ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_LOW)); esp_deep_sleep_start(); } +#endif // SOC_PM_SUPPORT_EXT0_WAKEUP +#if SOC_PM_SUPPORT_EXT1_WAKEUP TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 high)", "[deepsleep][ignore]") { // This test needs external pulldown @@ -440,7 +442,7 @@ TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 low)", "[deepsleep][igno ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW)); esp_deep_sleep_start(); } -#endif // SOC_PM_SUPPORT_EXT_WAKEUP +#endif // SOC_PM_SUPPORT_EXT1_WAKEUP __attribute__((unused)) static float get_time_ms(void) { diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index 854bca6c63..5186c947d1 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -39,7 +39,7 @@ typedef struct rtc_cntl_sleep_retent { #define RTC_HAL_DMA_LINK_NODE_SIZE (16) -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT1_WAKEUP #define rtc_hal_ext1_get_wakeup_status() rtc_cntl_ll_ext1_get_wakeup_status() @@ -51,7 +51,7 @@ typedef struct rtc_cntl_sleep_retent { #define rtc_hal_ext1_get_wakeup_pins() rtc_cntl_ll_ext1_get_wakeup_pins() -#endif +#endif // SOC_PM_SUPPORT_EXT1_WAKEUP #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 017d1f2d9f..ea0f1cf35a 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -719,6 +719,14 @@ config SOC_PHY_DIG_REGS_MEM_SIZE int default 21 +config SOC_PM_SUPPORT_EXT0_WAKEUP + bool + default y + +config SOC_PM_SUPPORT_EXT1_WAKEUP + bool + default y + config SOC_PM_SUPPORT_EXT_WAKEUP bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index af8d62a00a..353d3b8509 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -365,7 +365,10 @@ #define SOC_PHY_DIG_REGS_MEM_SIZE (21*4) /*-------------------------- Power Management CAPS ---------------------------*/ -#define SOC_PM_SUPPORT_EXT_WAKEUP (1) +#define SOC_PM_SUPPORT_EXT0_WAKEUP (1) +#define SOC_PM_SUPPORT_EXT1_WAKEUP (1) +#define SOC_PM_SUPPORT_EXT_WAKEUP (1) /*!count) { int io_num = deep_sleep_args.wakeup_gpio_num->ival[0]; if (!esp_sleep_is_valid_wakeup_gpio(io_num)) { @@ -266,7 +266,7 @@ static int deep_sleep(int argc, char **argv) ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) ); ESP_LOGE(TAG, "GPIO wakeup from deep sleep currently unsupported on ESP32-C3"); } -#endif // SOC_PM_SUPPORT_EXT_WAKEUP +#endif // SOC_PM_SUPPORT_EXT1_WAKEUP #if CONFIG_IDF_TARGET_ESP32 rtc_gpio_isolate(GPIO_NUM_12); @@ -280,7 +280,7 @@ static void register_deep_sleep(void) int num_args = 1; deep_sleep_args.wakeup_time = arg_int0("t", "time", "", "Wake up time, ms"); -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP deep_sleep_args.wakeup_gpio_num = arg_int0(NULL, "io", "", "If specified, wakeup using GPIO with given number"); @@ -293,7 +293,7 @@ static void register_deep_sleep(void) const esp_console_cmd_t cmd = { .command = "deep_sleep", .help = "Enter deep sleep mode. " -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP "Two wakeup modes are supported: timer and GPIO. " #else "Timer wakeup mode is supported. " diff --git a/examples/system/deep_sleep/main/Kconfig.projbuild b/examples/system/deep_sleep/main/Kconfig.projbuild index d3e89751b3..cdce6b8d70 100644 --- a/examples/system/deep_sleep/main/Kconfig.projbuild +++ b/examples/system/deep_sleep/main/Kconfig.projbuild @@ -15,7 +15,7 @@ menu "Example Configuration" bool "Enable wakeup from GPIO (ext0)" default y if !IDF_TARGET_ESP32 default n if IDF_TARGET_ESP32 - depends on SOC_PM_SUPPORT_EXT_WAKEUP + depends on SOC_PM_SUPPORT_EXT0_WAKEUP help This option enables wake up from deep sleep from GPIO25(ESP32)/GPIO3(ESP32S2,S3). The pin should be connected to LOW to avoid being in a floating state. When triggering a wake up, connect the pin to HIGH. @@ -26,7 +26,7 @@ menu "Example Configuration" config EXAMPLE_EXT1_WAKEUP bool "Enable wakeup from GPIO (ext1)" default y - depends on SOC_PM_SUPPORT_EXT_WAKEUP + depends on SOC_PM_SUPPORT_EXT1_WAKEUP help This option enables wake up from deep sleep from GPIO2 and GPIO4. They should be connected to LOW to avoid floating pins. When triggering a wake up, connect one or both of the pins to HIGH. Note that floating From 4e80c7544a447a9735d9ba49ee8acdc8d8c2a5e1 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 17 Feb 2023 20:32:40 +0800 Subject: [PATCH 2/9] esp32c6: soc caps adjustment --- .../soc/esp32c6/include/soc/Kconfig.soc_caps.in | 12 ++++++++++++ components/soc/esp32c6/include/soc/soc_caps.h | 6 +++++- .../soc/esp32h2/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32h2/include/soc/soc_caps.h | 3 +++ .../soc/esp32h4/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32h4/include/soc/soc_caps.h | 6 ++++++ 6 files changed, 34 insertions(+), 1 deletion(-) diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index dfe355ff55..098dd3904d 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -171,6 +171,10 @@ config SOC_LP_TIMER_SUPPORTED bool default y +config SOC_LP_AON_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y @@ -399,6 +403,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x000000007FFFFF00 +config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP + bool + default y + config SOC_RTCIO_PIN_COUNT int default 8 @@ -411,6 +419,10 @@ config SOC_RTCIO_HOLD_SUPPORTED bool default y +config SOC_RTCIO_WAKE_SUPPORTED + bool + default y + config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM int default 8 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index def821eb65..62f0120329 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -68,6 +68,7 @@ #define SOC_PMU_SUPPORTED 1 #define SOC_PAU_SUPPORTED 1 #define SOC_LP_TIMER_SUPPORTED 1 +#define SOC_LP_AON_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_40M 1 @@ -183,11 +184,14 @@ // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_8~GPIO_NUM_30) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x000000007FFFFF00ULL +// Support to hold a single GPIO when the digital domain is powered off +#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) + /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 8 #define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 #define SOC_RTCIO_HOLD_SUPPORTED 1 -// #define SOC_RTCIO_WAKE_SUPPORTED 1 // TODO: IDF-5645 +#define SOC_RTCIO_WAKE_SUPPORTED 1 /*-------------------------- Dedicated GPIO CAPS -----------------------------*/ #define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 453d23bdea..c66e51f6dc 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -371,6 +371,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x000000000FFF807F +config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP + bool + default y + config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM int default 8 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index c691fa0c7a..c1ad381f06 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -181,6 +181,9 @@ // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_0~6. GPIO_NUM_15~27) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x000000000FFF807FULL +// Support to hold a single GPIO when the digital domain is powered off +#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) + /*-------------------------- Dedicated GPIO CAPS -----------------------------*/ #define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 356fc7aa54..917ac0755b 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -319,6 +319,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x000001FFFFFFFFC0 +config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP + bool + default y + config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM int default 8 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index d8332be15f..28c0d8dce6 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -172,6 +172,12 @@ #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x0000000003FFE07FULL #endif +#if CONFIG_IDF_TARGET_ESP32H4_BETA_VERSION_2 +// Support to hold a single GPIO when the digital domain is powered off +// ESP32H4-BETA1 only supports hold all in deepsleep +#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) +#endif + /*-------------------------- Dedicated GPIO CAPS -----------------------------*/ #define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ From d1d6b7349fc42d7286e7adffa1dd2f342a1d89c1 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 17 Feb 2023 20:34:41 +0800 Subject: [PATCH 3/9] pmu: pmu parameter adjustment --- .../esp_hw_support/port/esp32c6/pmu_sleep.c | 12 +++-- .../port/esp32c6/private_include/pmu_param.h | 50 +++++++++---------- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index 37c9dedd85..b4abcb8116 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -15,6 +15,7 @@ #include "soc/rtc.h" #include "soc/pmu_struct.h" #include "esp_private/esp_pmu.h" +#include "esp32c6/rom/rtc.h" #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) @@ -152,11 +153,9 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->digital = digital_default; pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags); - if (!(pd_flags & PMU_SLEEP_PD_MODEM)){ - analog_default.hp_sys.analog.slp_logic_dbias += 2; - } - if (!(pd_flags & PMU_SLEEP_PD_TOP)){ - analog_default.hp_sys.analog.slp_logic_dbias += 2; + if (!(pd_flags & PMU_SLEEP_PD_TOP) || !(pd_flags & PMU_SLEEP_PD_MODEM)){ + analog_default.hp_sys.analog.xpd = 1; + analog_default.hp_sys.analog.dbias = 2; } config->analog = analog_default; } @@ -200,10 +199,13 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b); + pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_xpd); pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias); + pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.xpd); pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias); pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b); + pmu_ll_lp_set_dbg_atten (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbg_atten); pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur); pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep); pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd); diff --git a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h index 24b15a2958..dd3fbd7da9 100644 --- a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h @@ -172,14 +172,14 @@ typedef struct { #define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ .hp_sys = { \ .analog = { \ - .xpd_bias = 0x0, \ - .dbg_atten = 0x0, \ + .xpd_bias = 0, \ + .dbg_atten = 0, \ .pd_cur = 1, \ .bias_sleep = 1, \ .slp_mem_xpd = 1, \ .slp_logic_xpd = 1, \ - .slp_mem_dbias = 0x4, \ - .slp_logic_dbias = 0x4, \ + .slp_mem_dbias = 4, \ + .slp_logic_dbias = 4, \ .xpd = 0, \ .dbias = 0, \ .drv_b = 0 \ @@ -188,23 +188,23 @@ typedef struct { .lp_sys[PMU_MODE_LP_ACTIVE] = { \ .analog = { \ .slp_xpd = 0, \ - .slp_dbias = 0xc, \ + .slp_dbias = 0, \ .xpd = 1, \ - .dbias = 0x1a, \ - .drv_b = 0x0 \ + .dbias = 26, \ + .drv_b = 0 \ } \ }, \ .lp_sys[PMU_MODE_LP_SLEEP] = { \ .analog = { \ .xpd_bias = 0, \ - .dbg_atten = 0x0, \ + .dbg_atten = 0, \ .pd_cur = 1, \ .bias_sleep = 1, \ .xpd = 0, \ - .dbias = 0x1c, \ + .dbias = 28, \ .slp_xpd = 1, \ - .slp_dbias = 0x3, \ - .drv_b = 0x0 \ + .slp_dbias = 3, \ + .drv_b = 0 \ } \ } \ } @@ -213,37 +213,37 @@ typedef struct { .hp_sys = { \ .analog = { \ .xpd_bias = 0, \ - .dbg_atten = 0x3, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ + .dbg_atten = 0, \ + .pd_cur = 0, \ + .bias_sleep = 0, \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ .xpd = 0, \ - .dbias = 0x15, \ - .slp_mem_xpd = 1, \ - .slp_mem_dbias = 0xc, \ - .slp_logic_xpd = 1, \ - .slp_logic_dbias = 0x5, \ - .drv_b = 0x18c \ + .dbias = 0, \ + .drv_b = 0 \ } \ }, \ .lp_sys[PMU_MODE_LP_ACTIVE] = { \ .analog = { \ - .xpd = 1, \ - .dbias = 0x1a, \ .slp_xpd = 0, \ .slp_dbias = 0, \ - .drv_b = 0x7 \ + .xpd = 1, \ + .dbias = 26, \ + .drv_b = 0 \ } \ }, \ .lp_sys[PMU_MODE_LP_SLEEP] = { \ .analog = { \ .xpd_bias = 0, \ - .dbg_atten = 0xe, \ + .dbg_atten = 14, \ .pd_cur = 1, \ .bias_sleep = 1, \ .xpd = 0, \ .dbias = 0, \ .slp_xpd = 1, \ - .slp_dbias = 0xe, \ + .slp_dbias = 14, \ .drv_b = 0 \ } \ } \ From d3ec7880fec535ce2db46131cdecc507a2289227 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 21 Feb 2023 21:40:20 +0800 Subject: [PATCH 4/9] bugfix: support GPIO current leakage workaround for esp32c6/esp32h2 --- components/esp_hw_support/CMakeLists.txt | 1 + .../include/esp_private/esp_sleep_internal.h | 5 +- components/esp_hw_support/sleep_gpio.c | 3 +- components/esp_hw_support/sleep_modes.c | 3 +- .../hal/esp32h4/include/rev1/hal/gpio_ll.h | 49 +++++++++++++++++++ 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 5a9a94b35f..e6ad10abd1 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -110,6 +110,7 @@ if(NOT BOOTLOADER_BUILD) "sleep_cpu.c" # TODO: IDF-6267 "sleep_modes.c" # TODO: IDF-6267 "sleep_wake_stub.c" # TODO: IDF-6267 + "sleep_gpio.c" # TODO: IDF-6267 ) endif() else() diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index 07af89ff9f..56a6b5fde1 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,8 +21,7 @@ extern "C" { */ void esp_sleep_enable_adc_tsens_monitor(bool enable); -// TODO: IDF-6051, IDF-6052 -#if !CONFIG_IDF_TARGET_ESP32H4 && !CONFIG_IDF_TARGET_ESP32C6 +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Isolate all digital IOs except those that are held during deep sleep * diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 0b30f0b10d..3d2e6b52da 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -107,8 +107,7 @@ void esp_sleep_enable_gpio_switch(bool enable) } } -// TODO: IDF-6051, IDF-6052 -#if !CONFIG_IDF_TARGET_ESP32H4 && !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP IRAM_ATTR void esp_sleep_isolate_digital_gpio(void) { gpio_hal_context_t gpio_hal = { diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index a2edd0ddeb..14212f2e9e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -533,8 +533,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo uint32_t result; if (deep_sleep) { -// TODO: IDF-6051, IDF-6052 -#if !CONFIG_IDF_TARGET_ESP32H4 && !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP esp_sleep_isolate_digital_gpio(); #endif diff --git a/components/hal/esp32h4/include/rev1/hal/gpio_ll.h b/components/hal/esp32h4/include/rev1/hal/gpio_ll.h index c57700fb8e..37c0bc928c 100644 --- a/components/hal/esp32h4/include/rev1/hal/gpio_ll.h +++ b/components/hal/esp32h4/include/rev1/hal/gpio_ll.h @@ -270,6 +270,22 @@ static inline void gpio_ll_od_enable(gpio_dev_t *hw, uint32_t gpio_num) hw->pin[gpio_num].pin_pad_driver = 1; } +/** + * @brief Select a function for the pin in the IOMUX + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @param func Function to assign to the pin + */ +static inline __attribute__((always_inline)) void gpio_ll_func_sel(gpio_dev_t *hw, uint8_t gpio_num, uint32_t func) +{ + // Disable USB Serial JTAG if pins 18 or pins 19 needs to select an IOMUX function + if (gpio_num == USB_DM_GPIO_NUM || gpio_num == USB_DP_GPIO_NUM) { + CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE); + } + PIN_FUNC_SELECT(IO_MUX_GPIO0_REG + (gpio_num * 4), func); +} + /** * @brief GPIO set output level * @@ -383,6 +399,21 @@ static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD); } +/** + * @brief Get deep sleep hold status + * + * @param hw Peripheral GPIO hardware instance address. + * + * @return + * - true deep sleep hold is enabled + * - false deep sleep hold is disabled + */ +__attribute__((always_inline)) +static inline bool gpio_ll_deep_sleep_hold_is_en(gpio_dev_t *hw) +{ + return !GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD) && GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); +} + /** * @brief Enable gpio pad hold function. * @@ -417,6 +448,24 @@ static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) } } +/** + * @brief Get digital gpio pad hold status. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number, only support output GPIOs + * + * @note caller must ensure that gpio_num is a digital io pad + * + * @return + * - true digital gpio pad is held + * - false digital gpio pad is unheld + */ +__attribute__((always_inline)) +static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num) +{ + return GET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, BIT(gpio_num)); +} + /** * @brief Set pad input to a peripheral signal through the IOMUX. * From 9eae151f7ceacb497252621947e61105f90df01d Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Sat, 18 Feb 2023 14:13:52 +0800 Subject: [PATCH 5/9] esp32c6: bringup deepsleep examples --- components/driver/gpio/gpio.c | 4 + .../include/esp_private/esp_pmu.h | 15 +++ components/esp_hw_support/include/esp_sleep.h | 1 + .../esp_hw_support/port/esp32c6/pmu_sleep.c | 5 +- components/esp_hw_support/sleep_cpu.c | 1 - components/esp_hw_support/sleep_gpio.c | 8 +- components/esp_hw_support/sleep_modes.c | 49 ++++++---- components/esp_hw_support/sleep_wake_stub.c | 14 ++- .../esp_system/ld/esp32c6/sections.ld.in | 2 + components/hal/esp32c6/include/hal/gpio_ll.h | 76 ++++----------- .../hal/esp32c6/include/hal/lp_aon_hal.h | 24 +++++ .../hal/esp32c6/include/hal/lp_aon_ll.h | 97 +++++++++++++++++++ .../hal/esp32c6/include/hal/rtc_io_ll.h | 34 +++++++ components/hal/include/hal/gpio_hal.h | 2 +- components/hal/include/hal/rtc_hal.h | 2 +- components/hal/include/hal/rtc_io_hal.h | 30 ++++++ examples/system/deep_sleep/README.md | 2 +- .../system/deep_sleep/main/Kconfig.projbuild | 1 + .../main/rtc_wake_stub_example.c | 2 +- 19 files changed, 282 insertions(+), 87 deletions(-) create mode 100644 components/hal/esp32c6/include/hal/lp_aon_hal.h create mode 100644 components/hal/esp32c6/include/hal/lp_aon_ll.h diff --git a/components/driver/gpio/gpio.c b/components/driver/gpio/gpio.c index d1582bde9f..610d38efcf 100644 --- a/components/driver/gpio/gpio.c +++ b/components/driver/gpio/gpio.c @@ -22,6 +22,10 @@ #include "hal/gpio_hal.h" #include "esp_rom_gpio.h" +#if (SOC_RTCIO_PIN_COUNT > 0) +#include "hal/rtc_io_hal.h" +#endif + static const char *GPIO_TAG = "gpio"; #define GPIO_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, GPIO_TAG, "%s", str) 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 7179e9cc33..3463e7221e 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -37,6 +37,14 @@ extern "C" { #define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17) #define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature +#if SOC_PM_SUPPORT_EXT0_WAKEUP +#define RTC_EXT0_TRIG_EN PMU_EXT0_WAKEUP_EN //!< EXT0 wakeup +#else +#define RTC_EXT0_TRIG_EN 0 +#endif +#if SOC_PM_SUPPORT_EXT1_WAKEUP +#define RTC_EXT1_TRIG_EN PMU_EXT1_WAKEUP_EN //!< EXT1 wakeup +#endif #define RTC_GPIO_TRIG_EN PMU_GPIO_WAKEUP_EN //!< GPIO wakeup #define RTC_TIMER_TRIG_EN PMU_LP_TIMER_WAKEUP_EN //!< Timer wakeup #define RTC_WIFI_TRIG_EN PMU_WIFI_SOC_WAKEUP_EN //!< WIFI wakeup (light sleep only) @@ -60,6 +68,12 @@ extern "C" { RTC_USB_TRIG_EN | \ RTC_BROWNOUT_DET_TRIG_EN) +#if SOC_PM_SUPPORT_EXT0_WAKEUP +#define PMU_EXT0_WAKEUP_EN BIT(0) +#endif +#if SOC_PM_SUPPORT_EXT1_WAKEUP +#define PMU_EXT1_WAKEUP_EN BIT(1) +#endif #define PMU_GPIO_WAKEUP_EN BIT(2) #define PMU_WIFI_BEACON_WAKEUP_EN BIT(3) @@ -82,6 +96,7 @@ extern "C" { #define PMU_SLEEP_PD_MEM_G1 BIT(7) #define PMU_SLEEP_PD_MEM_G2 BIT(8) #define PMU_SLEEP_PD_MEM_G3 BIT(9) +#define PMU_SLEEP_PD_MEM (PMU_SLEEP_PD_MEM_G0|PMU_SLEEP_PD_MEM_G1|PMU_SLEEP_PD_MEM_G2|PMU_SLEEP_PD_MEM_G3) #define PMU_SLEEP_PD_XTAL BIT(10) #define PMU_SLEEP_PD_RC_FAST BIT(11) #define PMU_SLEEP_PD_XTAL32K BIT(12) diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 2f9458fbad..90813a16f5 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -250,6 +250,7 @@ esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); * - ESP32: 0, 2, 4, 12-15, 25-27, 32-39; * - ESP32-S2: 0-21; * - ESP32-S3: 0-21. + * - ESP32-C6: 0-7. * @param mode select logic function used to determine wakeup condition: * - ESP_EXT1_WAKEUP_ALL_LOW: wake up when all selected GPIOs are low * - ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index b4abcb8116..90f00dc130 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -14,8 +14,8 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/pmu_struct.h" +#include "hal/lp_aon_hal.h" #include "esp_private/esp_pmu.h" -#include "esp32c6/rom/rtc.h" #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) @@ -250,6 +250,9 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp) uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) { assert(PMU_instance()->hal); + + lp_aon_hal_inform_wakeup_type(dslp); + pmu_ll_hp_set_wakeup_enable(PMU_instance()->hal->dev, wakeup_opt); pmu_ll_hp_set_reject_enable(PMU_instance()->hal->dev, reject_opt); diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c index 318e8b85f3..28f6eeb2d3 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -565,7 +565,6 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, { RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save(); if ((frame->pmufunc & 0x3) == 0x1) { - REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */ REG_WRITE(LIGHT_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore); return (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp); } diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 3d2e6b52da..f8d2e8d7bb 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -21,7 +21,9 @@ #include "hal/gpio_hal.h" #include "hal/rtc_io_hal.h" -#if !SOC_PMU_SUPPORTED +#if SOC_LP_AON_SUPPORTED +#include "hal/lp_aon_hal.h" +#else #include "hal/rtc_hal.h" #endif @@ -145,11 +147,11 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void) } } } -#endif +#endif // !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP void esp_deep_sleep_wakeup_io_reset(void) { -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT1_WAKEUP uint32_t rtc_io_mask = rtc_hal_ext1_get_wakeup_pins(); // Disable ext1 wakeup before releasing hold, such that wakeup status can reflect the correct wakeup pin rtc_hal_ext1_clear_wakeup_pins(); diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 14212f2e9e..f97991241b 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -25,7 +25,9 @@ #include "driver/rtc_io.h" #include "hal/rtc_io_hal.h" -#if !SOC_PMU_SUPPORTED +#if SOC_LP_AON_SUPPORTED +#include "hal/lp_aon_hal.h" +#else #include "hal/rtc_cntl_ll.h" #include "hal/rtc_hal.h" #endif @@ -156,12 +158,16 @@ typedef struct { portMUX_TYPE lock; uint64_t sleep_duration; uint32_t wakeup_triggers : 15; +#if SOC_PM_SUPPORT_EXT1_WAKEUP uint32_t ext1_trigger_mode : 1; - uint32_t ext1_rtc_gpio_mask : 22; //22 is the maximum RTCIO number in all chips + uint32_t ext1_rtc_gpio_mask : 22; // 22 is the maximum RTCIO number in all chips +#endif +#if SOC_PM_SUPPORT_EXT0_WAKEUP uint32_t ext0_trigger_level : 1; uint32_t ext0_rtc_gpio_num : 5; - uint32_t gpio_wakeup_mask : 6; - uint32_t gpio_trigger_mode : 6; +#endif + uint32_t gpio_wakeup_mask : 8; // 8 is the maximum RTCIO number in all chips that support GPIO wakeup + uint32_t gpio_trigger_mode : 8; uint32_t sleep_time_adjustment; uint32_t ccount_ticks_record; uint32_t sleep_time_overhead_out; @@ -237,14 +243,19 @@ static void RTC_IRAM_ATTR __attribute__((used, noinline)) esp_wake_stub_start(vo * must be simple enough to ensure that there is no litteral data before the * wake stub entry, otherwise, the litteral data before the wake stub entry * will not be CRC checked. */ -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void) { #define _SYM2STR(s) # s #define SYM2STR(s) _SYM2STR(s) #ifdef __riscv - __asm__ __volatile__ ("call " SYM2STR(esp_wake_stub_start) "\n"); + __asm__ __volatile__ ( + "addi sp, sp, -16 \n" + "sw ra, 0(sp) \n" + "jal ra, " SYM2STR(esp_wake_stub_start) "\n" + "lw ra, 0(sp) \n" + "addi sp, sp, 16 \n" + ); #else // call4 has a larger effective addressing range (-524284 to 524288 bytes), // which is sufficient for instruction addressing in RTC fast memory. @@ -252,7 +263,6 @@ static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void #endif } -#endif // !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY /* Wake from deep sleep stub @@ -537,8 +547,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo esp_sleep_isolate_digital_gpio(); #endif -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349 - #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY extern char _rtc_text_start[]; #if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM @@ -549,7 +557,12 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start; #endif esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length); + // Enter Deep Sleep +#if SOC_PMU_SUPPORTED + result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); +#else result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep); +#endif #else #if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP /* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */ @@ -563,9 +576,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo #endif #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY -#else - result = ESP_OK; -#endif } else { /* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode. @@ -649,7 +659,14 @@ void IRAM_ATTR esp_deep_sleep_start(void) // Correct the sleep time s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US; +#if SOC_PMU_SUPPORTED + uint32_t force_pd_flags = PMU_SLEEP_PD_TOP | PMU_SLEEP_PD_VDDSDIO | PMU_SLEEP_PD_MODEM | PMU_SLEEP_PD_HP_PERIPH \ + | PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_MEM | PMU_SLEEP_PD_XTAL | PMU_SLEEP_PD_RC_FAST \ + | PMU_SLEEP_PD_XTAL32K |PMU_SLEEP_PD_RC32K; +#else uint32_t force_pd_flags = RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | RTC_SLEEP_PD_INT_8M | RTC_SLEEP_PD_XTAL; +#endif + #if SOC_PM_SUPPORT_WIFI_PD force_pd_flags |= RTC_SLEEP_PD_WIFI; @@ -1191,25 +1208,20 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void) return gpio_mask; } -#endif // SOC_PM_SUPPORT_EXT_WAKEUP +#endif // SOC_PM_SUPPORT_EXT1_WAKEUP #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP uint64_t esp_sleep_get_gpio_wakeup_status(void) { -#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349 - return 0; -#else if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_GPIO) { return 0; } return rtc_hal_gpio_get_wakeup_status(); -#endif } static void gpio_deep_sleep_wakeup_prepare(void) { -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349 for (gpio_num_t gpio_idx = GPIO_NUM_0; gpio_idx < GPIO_NUM_MAX; gpio_idx++) { if (((1ULL << gpio_idx) & s_config.gpio_wakeup_mask) == 0) { continue; @@ -1225,7 +1237,6 @@ static void gpio_deep_sleep_wakeup_prepare(void) } // Clear state from previous wakeup rtc_hal_gpio_clear_wakeup_status(); -#endif } esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode) diff --git a/components/esp_hw_support/sleep_wake_stub.c b/components/esp_hw_support/sleep_wake_stub.c index 023e766c45..29779160d7 100644 --- a/components/esp_hw_support/sleep_wake_stub.c +++ b/components/esp_hw_support/sleep_wake_stub.c @@ -68,6 +68,9 @@ void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub) // Go to sleep. #if SOC_PMU_SUPPORTED + pmu_ll_hp_clear_wakeup_intr_status(&PMU); + pmu_ll_hp_clear_reject_intr_status(&PMU); + pmu_ll_hp_clear_reject_cause(&PMU); pmu_ll_hp_set_sleep_enable(&PMU); #else rtc_cntl_ll_sleep_enable(); @@ -87,8 +90,15 @@ void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us) { #if SOC_LP_TIMER_SUPPORTED uint64_t rtc_count_delta = lp_timer_ll_time_to_count(time_in_us); - uint64_t rtc_curr_count = lp_timer_hal_get_cycle_count(0); - lp_timer_hal_set_alarm_target(0, rtc_curr_count + rtc_count_delta); + + lp_timer_ll_counter_snapshot(&LP_TIMER); + uint32_t lo = lp_timer_ll_get_counter_value_low(&LP_TIMER, 0); + uint32_t hi = lp_timer_ll_get_counter_value_high(&LP_TIMER, 0); + uint64_t rtc_curr_count = (uint64_t)hi << 32 | lo; + + lp_timer_ll_clear_alarm_intr_status(&LP_TIMER); + lp_timer_ll_set_alarm_target(&LP_TIMER, 0, rtc_curr_count + rtc_count_delta); + lp_timer_ll_set_target_enable(&LP_TIMER, 0, true); #else uint64_t rtc_count_delta = rtc_cntl_ll_time_to_count(time_in_us); uint64_t rtc_curr_count = rtc_cntl_ll_get_rtc_time(); diff --git a/components/esp_system/ld/esp32c6/sections.ld.in b/components/esp_system/ld/esp32c6/sections.ld.in index 34c9bd38d3..cecadef2d1 100644 --- a/components/esp_system/ld/esp32c6/sections.ld.in +++ b/components/esp_system/ld/esp32c6/sections.ld.in @@ -17,6 +17,8 @@ SECTIONS { . = ALIGN(4); _rtc_fast_start = ABSOLUTE(.); + _rtc_text_start = ABSOLUTE(.); + *(.rtc.entry.text) mapping[rtc_text] diff --git a/components/hal/esp32c6/include/hal/gpio_ll.h b/components/hal/esp32c6/include/hal/gpio_ll.h index 1e59fb37fe..a6e64e3e5b 100644 --- a/components/hal/esp32c6/include/hal/gpio_ll.h +++ b/components/hal/esp32c6/include/hal/gpio_ll.h @@ -20,6 +20,7 @@ #include "soc/gpio_periph.h" #include "soc/gpio_struct.h" #include "soc/lp_aon_struct.h" +#include "soc/lp_io_struct.h" #include "soc/pmu_reg.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/pcr_struct.h" @@ -396,6 +397,24 @@ static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) LP_AON.gpio_hold0.gpio_hold0 &= ~GPIO_HOLD_MASK[gpio_num]; } +/** + * @brief Get digital gpio pad hold status. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number, only support output GPIOs + * + * @note caller must ensure that gpio_num is a digital io pad + * + * @return + * - true digital gpio pad is held + * - false digital gpio pad is unheld + */ +__attribute__((always_inline)) +static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num) +{ + return !!(LP_AON.gpio_hold0.gpio_hold0 & GPIO_HOLD_MASK[gpio_num]); +} + /** * @brief Set pad input to a peripheral signal through the IOMUX. * @@ -589,63 +608,6 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num PIN_SLP_OUTPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } -/** - * @brief Enable GPIO deep-sleep wake-up function. - * - * @param hw Peripheral GPIO hardware instance address. - * @param gpio_num GPIO number. - * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used. - */ -static inline void gpio_ll_deepsleep_wakeup_enable(gpio_dev_t *hw, uint32_t gpio_num, gpio_int_type_t intr_type) -{ - HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function"); - - LP_AON.ext_wakeup_cntl.ext_wakeup_filter = 1; - - uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel); - wakeup_sel_mask |= BIT(gpio_num); - HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask); - - bool trigger_level = (intr_type == GPIO_INTR_LOW_LEVEL) ? 0 : 1; - uint32_t wakeup_level_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv); - if (trigger_level) { - wakeup_level_mask |= BIT(gpio_num); - } else { - wakeup_level_mask &= ~BIT(gpio_num); - } - HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv, wakeup_level_mask); -} - -/** - * @brief Disable GPIO deep-sleep wake-up function. - * - * @param hw Peripheral GPIO hardware instance address. - * @param gpio_num GPIO number - */ -static inline void gpio_ll_deepsleep_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num) -{ - HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function"); - - uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel); - wakeup_sel_mask &= ~BIT(gpio_num); - HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask); -} - -/** - * @brief Get the status of whether an IO is used for deep-sleep wake-up. - * - * @param hw Peripheral GPIO hardware instance address. - * @param gpio_num GPIO number - * @return True if the pin is enabled to wake up from deep-sleep - */ -static inline bool gpio_ll_deepsleep_wakeup_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) -{ - HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function"); - - uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel); - return wakeup_sel_mask & BIT(gpio_num); -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/lp_aon_hal.h b/components/hal/esp32c6/include/hal/lp_aon_hal.h new file mode 100644 index 0000000000..c619dc0a6d --- /dev/null +++ b/components/hal/esp32c6/include/hal/lp_aon_hal.h @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "hal/lp_aon_ll.h" + +#define rtc_hal_ext1_get_wakeup_status() lp_aon_hal_ext1_get_wakeup_status() +#define rtc_hal_ext1_clear_wakeup_status() lp_aon_hal_ext1_clear_wakeup_status() +#define rtc_hal_ext1_set_wakeup_pins(mask, mode) lp_aon_hal_ext1_set_wakeup_pins(mask, mode) +#define rtc_hal_ext1_clear_wakeup_pins() lp_aon_hal_ext1_clear_wakeup_pins() +#define rtc_hal_ext1_get_wakeup_pins() lp_aon_hal_ext1_get_wakeup_pins() + + +#define lp_aon_hal_ext1_get_wakeup_status() lp_aon_ll_ext1_get_wakeup_status() +#define lp_aon_hal_ext1_clear_wakeup_status() lp_aon_ll_ext1_clear_wakeup_status() +#define lp_aon_hal_ext1_set_wakeup_pins(mask, mode) lp_aon_ll_ext1_set_wakeup_pins(mask, mode) +#define lp_aon_hal_ext1_clear_wakeup_pins() lp_aon_ll_ext1_clear_wakeup_pins() +#define lp_aon_hal_ext1_get_wakeup_pins() lp_aon_ll_ext1_get_wakeup_pins() + +#define lp_aon_hal_inform_wakeup_type(dslp) lp_aon_ll_inform_wakeup_type(dslp) diff --git a/components/hal/esp32c6/include/hal/lp_aon_ll.h b/components/hal/esp32c6/include/hal/lp_aon_ll.h new file mode 100644 index 0000000000..db08715964 --- /dev/null +++ b/components/hal/esp32c6/include/hal/lp_aon_ll.h @@ -0,0 +1,97 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-C6 LP_AON register operations + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/lp_aon_struct.h" +#include "hal/misc.h" +#include "esp32c6/rom/rtc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get ext1 wakeup source status + * @return The lower 8 bits of the returned value are the bitmap of + * the wakeup source status, bit 0~7 corresponds to LP_IO 0~7 + */ +static inline uint32_t lp_aon_ll_ext1_get_wakeup_status(void) +{ + return HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_status); +} + +/** + * @brief Clear the ext1 wakeup source status + */ +static inline void lp_aon_ll_ext1_clear_wakeup_status(void) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_status_clr, 1); +} + +/** + * @brief Set the wake-up LP_IO of the ext1 wake-up source + * @param mask wakeup LP_IO bitmap, bit 0~7 corresponds to LP_IO 0~7 + * @param mode 0: Wake the chip when all selected GPIOs go low + * 1: Wake the chip when any of the selected GPIOs go high + */ +static inline void lp_aon_ll_ext1_set_wakeup_pins(uint32_t mask, int mode) +{ + uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel); + wakeup_sel_mask |= mask; + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask); + + uint32_t wakeup_level_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv); + if (mode) { + wakeup_level_mask |= mask; + } else { + wakeup_level_mask &= ~mask; + } + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv, wakeup_level_mask); +} + +/** + * @brief Clear all ext1 wakup-source setting + */ +static inline void lp_aon_ll_ext1_clear_wakeup_pins(void) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, 0); +} + +/** + * @brief Get ext1 wakeup source setting + * @return The lower 8 bits of the returned value are the bitmap of + * the wakeup source status, bit 0~7 corresponds to LP_IO 0~7 + */ +static inline uint32_t lp_aon_ll_ext1_get_wakeup_pins(void) +{ + return HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel); +} + + +/** + * @brief ROM obtains the wake-up type through LP_AON_STORE9_REG[0]. + * Set the flag to inform + * @param true: deepsleep false: lightsleep + */ +static inline void lp_aon_ll_inform_wakeup_type(bool dslp) +{ + if (dslp) { + REG_SET_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */ + + } else { + REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */ + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/include/hal/rtc_io_ll.h b/components/hal/esp32c6/include/hal/rtc_io_ll.h index 8d081f90ad..7cf23de8ae 100644 --- a/components/hal/esp32c6/include/hal/rtc_io_ll.h +++ b/components/hal/esp32c6/include/hal/rtc_io_ll.h @@ -13,12 +13,14 @@ #pragma once #include +#include #include "soc/rtc_periph.h" #include "soc/pcr_struct.h" #include "soc/rtc_io_struct.h" #include "soc/lp_aon_struct.h" #include "soc/pmu_struct.h" #include "hal/misc.h" +#include "hal/assert.h" #include "hal/gpio_types.h" #include "soc/io_mux_reg.h" @@ -366,6 +368,38 @@ static inline void rtcio_ll_disable_sleep_setting(gpio_num_t gpio_num) LP_IO.gpio[gpio_num].slp_sel = 0; } +/** + * @brief Get the status of whether an IO is used for sleep wake-up. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return True if the pin is enabled to wake up from deep-sleep + */ +static inline bool rtcio_ll_wakeup_is_enabled(gpio_num_t gpio_num) +{ + HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function"); + // On ESP32-C6, (lp_io pin number) == (gpio pin number) + return LP_IO.pin[gpio_num].wakeup_enable; +} + +/** + * @brief Get the rtc io interrupt status + * + * @return bit 0~7 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT. + */ +static inline uint32_t rtcio_ll_get_interrupt_status(void) +{ + return (uint32_t)(LP_IO.status.status_interrupt); +} + +/** + * @brief Clear all LP IO pads status + */ +static inline void rtcio_ll_clear_interrupt_status(void) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IO.status_w1tc, status_w1tc, 0xff); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/gpio_hal.h b/components/hal/include/hal/gpio_hal.h index 250a912f5c..b765e7c0b9 100644 --- a/components/hal/include/hal/gpio_hal.h +++ b/components/hal/include/hal/gpio_hal.h @@ -448,7 +448,7 @@ void gpio_hal_sleep_pupd_config_apply(gpio_hal_context_t *hal, uint32_t gpio_num void gpio_hal_sleep_pupd_config_unapply(gpio_hal_context_t *hal, uint32_t gpio_num); #endif // CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL -#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT == 0) /** * @brief Enable GPIO deep-sleep wake-up function. * diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index 5186c947d1..6848d559d8 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -53,7 +53,7 @@ typedef struct rtc_cntl_sleep_retent { #endif // SOC_PM_SUPPORT_EXT1_WAKEUP -#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT == 0) #define rtc_hal_gpio_get_wakeup_status() rtc_cntl_ll_gpio_get_wakeup_status() diff --git a/components/hal/include/hal/rtc_io_hal.h b/components/hal/include/hal/rtc_io_hal.h index c094b08bfa..1763d0f92b 100644 --- a/components/hal/include/hal/rtc_io_hal.h +++ b/components/hal/include/hal/rtc_io_hal.h @@ -254,6 +254,36 @@ void rtcio_hal_isolate(int rtc_num); #endif +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT > 0) + +#define gpio_hal_deepsleep_wakeup_enable(hal, gpio_num, intr_type) rtcio_hal_wakeup_enable(gpio_num, intr_type) +#define gpio_hal_deepsleep_wakeup_disable(hal, gpio_num) rtcio_hal_wakeup_disable(gpio_num) +#define gpio_hal_deepsleep_wakeup_is_enabled(hal, gpio_num) rtcio_hal_wakeup_is_enabled(gpio_num) +#define rtc_hal_gpio_get_wakeup_status() rtcio_hal_get_interrupt_status() +#define rtc_hal_gpio_clear_wakeup_status() rtcio_hal_clear_interrupt_status() + +/** + * @brief Get the status of whether an IO is used for sleep wake-up. + * + * @param hw Peripheral GPIO hardware instance address. + * @param rtcio_num GPIO number + * @return True if the pin is enabled to wake up from deep-sleep + */ +#define rtcio_hal_wakeup_is_enabled(rtcio_num) rtcio_ll_wakeup_is_enabled(rtcio_num) + +/** + * @brief Get the rtc io interrupt status + * + * @return bit 0~7 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT. + */ +#define rtcio_hal_get_interrupt_status() rtcio_ll_get_interrupt_status() + +/** + * @brief Clear all LP IO pads status + */ +#define rtcio_hal_clear_interrupt_status() rtcio_ll_clear_interrupt_status() + +#endif //SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP #ifdef __cplusplus } #endif diff --git a/examples/system/deep_sleep/README.md b/examples/system/deep_sleep/README.md index 60a03d51c6..f2aa4434a1 100644 --- a/examples/system/deep_sleep/README.md +++ b/examples/system/deep_sleep/README.md @@ -11,7 +11,7 @@ The following wake up sources are demonstrated in this example (refer to the [Wa - **Timer:** An RTC timer that can be programmed to trigger a wake up after a preset time. This example will trigger a wake up every 20 seconds. - **EXT0:** External wake up 0 can trigger wakeup when one predefined RTC GPIO is at a predefined logic level. This example uses GPIO25 in ESP32 or GPIO3 in ESP32-S2/S3 to trigger a wake up when the pin is HIGH. (This wake up source is only available on ESP32, ESP32-S2, and ESP32-S3.) -- **EXT1:** External wake up 1 which is tied to multiple RTC GPIOs. This example uses GPIO2 and GPIO4 to trigger a wake up with any one of the two pins are HIGH. (This wake up source is only available on ESP32, ESP32-S2, and ESP32-S3.) +- **EXT1:** External wake up 1 which is tied to multiple RTC GPIOs. This example uses GPIO2 and GPIO4 to trigger a wake up with any one of the two pins are HIGH. (This wake up source is available on ESP32, ESP32-S2, ESP32-S3 and ESP32-C6.) - **GPIO:** Pads powered by VDD3P3_RTC can be used to trigger a wake up from deep sleep. You may choose the pin and trigger level in menuconfig. (This wake up source is unavailable on ESP32, ESP32-S2, and ESP32-S3.) - **Touch:** Touch pad sensor interrupt. This example uses touch pads connected to GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2/S3 to trigger a wake up when any of the pads are pressed. - **ULP:** Ultra Low Power Coprocessor which can continue to run during deep sleep. This example utilizes the ULP and constantly sample the chip's temperature and trigger a wake up if the chips temperature exceeds ~5 degrees Celsius. diff --git a/examples/system/deep_sleep/main/Kconfig.projbuild b/examples/system/deep_sleep/main/Kconfig.projbuild index cdce6b8d70..6a680f6cfd 100644 --- a/examples/system/deep_sleep/main/Kconfig.projbuild +++ b/examples/system/deep_sleep/main/Kconfig.projbuild @@ -62,6 +62,7 @@ menu "Example Configuration" int "Enable wakeup from GPIO" default 0 if !IDF_TARGET_ESP32H4_BETA_VERSION_2 default 7 if IDF_TARGET_ESP32H4_BETA_VERSION_2 + range 0 7 if IDF_TARGET_ESP32C6 range 0 5 if !IDF_TARGET_ESP32H4_BETA_VERSION_2 range 7 12 if IDF_TARGET_ESP32H4_BETA_VERSION_2 diff --git a/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c b/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c index 628af418c1..6ae8c4156c 100644 --- a/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c +++ b/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c @@ -34,7 +34,7 @@ static const uint32_t s_max_count = 20; static uint32_t wakeup_cause; // wake up stub function stored in RTC memory -void wake_stub_example(void) +void __attribute__((aligned(4))) wake_stub_example(void) { // Get wakeup cause. wakeup_cause = esp_wake_stub_get_wakeup_cause(); From 38c4910996190687bd7ecaac8bde47b9a2da3fbc Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Sat, 18 Feb 2023 18:27:13 +0800 Subject: [PATCH 6/9] ci: enable esp32c6 deepsleep ci tests --- examples/system/.build-test-rules.yml | 6 +++--- examples/system/deep_sleep/README.md | 4 ++-- examples/system/deep_sleep/pytest_deep_sleep.py | 4 ++-- examples/system/deep_sleep_wake_stub/README.md | 4 ++-- .../deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py | 1 + 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index f39f074401..9068f4550e 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -40,13 +40,13 @@ examples/system/console/basic: examples/system/deep_sleep: disable: - - if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"] + - if: IDF_TARGET in ["esp32c2", "esp32h2"] temporary: true - reason: target(s) not supported yet + reason: target(s) not supported yet # IDF-5432 / IDF-6268 examples/system/deep_sleep_wake_stub: disable: - - if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"] + - if: IDF_TARGET in ["esp32c2", "esp32h2"] temporary: true reason: target(s) is not supported yet diff --git a/examples/system/deep_sleep/README.md b/examples/system/deep_sleep/README.md index f2aa4434a1..a57e61f2ee 100644 --- a/examples/system/deep_sleep/README.md +++ b/examples/system/deep_sleep/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | # Deep Sleep Example diff --git a/examples/system/deep_sleep/pytest_deep_sleep.py b/examples/system/deep_sleep/pytest_deep_sleep.py index 12ef483fda..098158672f 100644 --- a/examples/system/deep_sleep/pytest_deep_sleep.py +++ b/examples/system/deep_sleep/pytest_deep_sleep.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging @@ -12,7 +12,7 @@ touch_wake_up_support = ['esp32', 'esp32s2'] CONFIGS = [ pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]), - pytest.param('basic', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32c3]), + pytest.param('basic', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32c3, pytest.mark.esp32c6]), ] diff --git a/examples/system/deep_sleep_wake_stub/README.md b/examples/system/deep_sleep_wake_stub/README.md index c93e69a9dd..fd4b6c4011 100644 --- a/examples/system/deep_sleep_wake_stub/README.md +++ b/examples/system/deep_sleep_wake_stub/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | # Deep Sleep Wake Stub Example diff --git a/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py b/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py index 29482ca5d3..19303733a0 100644 --- a/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py +++ b/examples/system/deep_sleep_wake_stub/pytest_deep_sleep_wake_stub.py @@ -12,6 +12,7 @@ from pytest_embedded import Dut @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c3 +@pytest.mark.esp32c6 @pytest.mark.generic @pytest.mark.parametrize('config', ['default',], indirect=True) def test_deep_sleep_wake_stub(config: str, dut: Dut) -> None: From 7ee64bd8e85bfd65432768361679f3857728e0fb Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 24 Feb 2023 13:53:38 +0800 Subject: [PATCH 7/9] refactor: always jump to wake stub wrapper after wakeup --- components/esp_hw_support/include/esp_sleep.h | 5 +++ components/esp_hw_support/sleep_modes.c | 31 +++++++++++++------ components/esp_hw_support/sleep_wake_stub.c | 24 +++++++------- components/esp_rom/include/esp32c6/rom/rtc.h | 9 ++++-- components/esp_rom/include/esp32h2/rom/rtc.h | 11 +++++-- components/esp_rom/include/esp32h4/rom/rtc.h | 9 ++++-- components/esp_rom/include/esp32s3/rom/rtc.h | 9 ++++-- .../main/rtc_wake_stub_example.c | 2 +- .../main/wake_stub_example_main.c | 1 - 9 files changed, 68 insertions(+), 33 deletions(-) diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 90813a16f5..ed23aac6b5 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -477,6 +477,11 @@ typedef void (*esp_deep_sleep_wake_stub_fn_t)(void); */ void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub); +/** + * @brief Set wake stub entry to default `esp_wake_stub_entry` + */ +void esp_set_deep_sleep_wake_stub_default_entry(void); + /** * @brief Get current wake from deep sleep stub * @return Return current wake from deep sleep stub, or NULL if diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index f97991241b..d2f36ee43a 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -263,6 +263,19 @@ static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void #endif } + +void RTC_IRAM_ATTR esp_set_deep_sleep_wake_stub_default_entry(void) +{ + extern char _rtc_text_start[]; +#if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM + extern char _rtc_noinit_end[]; + size_t rtc_fast_length = (size_t)_rtc_noinit_end - (size_t)_rtc_text_start; +#else + extern char _rtc_force_fast_end[]; + size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start; +#endif + esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length); +} #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY /* Wake from deep sleep stub @@ -281,7 +294,13 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void) return stub_ptr; } -void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub) +#if CONFIG_IDF_TARGET_ESP32 +/* APP core of esp32 can't access to RTC FAST MEMORY, do not define it with RTC_IRAM_ATTR */ +void +#else +void RTC_IRAM_ATTR +#endif +esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub) { #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY wake_stub_fn_handler = new_stub; @@ -548,15 +567,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo #endif #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY - extern char _rtc_text_start[]; -#if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM - extern char _rtc_noinit_end[]; - size_t rtc_fast_length = (size_t)_rtc_noinit_end - (size_t)_rtc_text_start; -#else - extern char _rtc_force_fast_end[]; - size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start; -#endif - esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length); + esp_set_deep_sleep_wake_stub_default_entry(); // Enter Deep Sleep #if SOC_PMU_SUPPORTED result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); diff --git a/components/esp_hw_support/sleep_wake_stub.c b/components/esp_hw_support/sleep_wake_stub.c index 29779160d7..7c49241ba9 100644 --- a/components/esp_hw_support/sleep_wake_stub.c +++ b/components/esp_hw_support/sleep_wake_stub.c @@ -50,19 +50,19 @@ void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub) { -#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY - extern char _rtc_text_start[]; - #if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM - extern char _rtc_noinit_end[]; - size_t rtc_fast_length = (size_t)_rtc_noinit_end - (size_t)_rtc_text_start; - #else - extern char _rtc_force_fast_end[]; - size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start; - #endif // CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM - esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)new_stub, rtc_fast_length); -#else - // Set the pointer of the wake stub function. + +#if CONFIG_IDF_TARGET_ESP32 + // Since the app core of esp32 does not support access to RTC_FAST_MEMORY, + // `esp_set_deep_sleep_wake_stub` is not declared in RTC_FAST_MEMORY, + // so we cannot call it here REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub); +#else + esp_set_deep_sleep_wake_stub(new_stub); +#endif + +#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY + esp_set_deep_sleep_wake_stub_default_entry(); +#else set_rtc_memory_crc(); #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_MEM diff --git a/components/esp_rom/include/esp32c6/rom/rtc.h b/components/esp_rom/include/esp32c6/rom/rtc.h index 3fba551945..6a046fa25a 100644 --- a/components/esp_rom/include/esp32c6/rom/rtc.h +++ b/components/esp_rom/include/esp32c6/rom/rtc.h @@ -178,6 +178,8 @@ typedef void (* esp_rom_wake_func_t)(void); * @brief Read stored RTC wake function address * * Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid. + * valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values + * and the crc check passes * * @param None * @@ -191,8 +193,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void); * Set a new RTC wake address function. If a non-NULL function pointer is set then the function * memory is calculated and stored also. * - * @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0. - * @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size. + * @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep, + * if NULL length will be ignored and all registers are cleared to 0. + * + * @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes. + * otherwise all registers are cleared to 0. * * @return None */ diff --git a/components/esp_rom/include/esp32h2/rom/rtc.h b/components/esp_rom/include/esp32h2/rom/rtc.h index 4bfa6b7533..1a89e39891 100644 --- a/components/esp_rom/include/esp32h2/rom/rtc.h +++ b/components/esp_rom/include/esp32h2/rom/rtc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -175,6 +175,8 @@ typedef void (* esp_rom_wake_func_t)(void); * @brief Read stored RTC wake function address * * Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid. + * valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values + * and the crc check passes * * @param None * @@ -188,8 +190,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void); * Set a new RTC wake address function. If a non-NULL function pointer is set then the function * memory is calculated and stored also. * - * @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0. - * @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size. + * @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep, + * if NULL length will be ignored and all registers are cleared to 0. + * + * @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes. + * otherwise all registers are cleared to 0. * * @return None */ diff --git a/components/esp_rom/include/esp32h4/rom/rtc.h b/components/esp_rom/include/esp32h4/rom/rtc.h index 8499f1b052..ed529a5e40 100644 --- a/components/esp_rom/include/esp32h4/rom/rtc.h +++ b/components/esp_rom/include/esp32h4/rom/rtc.h @@ -175,6 +175,8 @@ typedef void (* esp_rom_wake_func_t)(void); * @brief Read stored RTC wake function address * * Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid. + * valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values + * and the crc check passes * * @param None * @@ -188,8 +190,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void); * Set a new RTC wake address function. If a non-NULL function pointer is set then the function * memory is calculated and stored also. * - * @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0. - * @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size. + * @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep, + * if NULL length will be ignored and all registers are cleared to 0. + * + * @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes. + * otherwise all registers are cleared to 0. * * @return None */ diff --git a/components/esp_rom/include/esp32s3/rom/rtc.h b/components/esp_rom/include/esp32s3/rom/rtc.h index 168ca7997a..daa6ff0eec 100644 --- a/components/esp_rom/include/esp32s3/rom/rtc.h +++ b/components/esp_rom/include/esp32s3/rom/rtc.h @@ -173,6 +173,8 @@ typedef void (* esp_rom_wake_func_t)(void); * @brief Read stored RTC wake function address * * Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid. + * valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values + * and the crc check passes * * @param None * @@ -186,8 +188,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void); * Set a new RTC wake address function. If a non-NULL function pointer is set then the function * memory is calculated and stored also. * - * @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0. - * @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size. + * @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep, + * if NULL length will be ignored and all registers are cleared to 0. + * + * @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes. + * otherwise all registers are cleared to 0. * * @return None */ diff --git a/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c b/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c index 6ae8c4156c..628af418c1 100644 --- a/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c +++ b/examples/system/deep_sleep_wake_stub/main/rtc_wake_stub_example.c @@ -34,7 +34,7 @@ static const uint32_t s_max_count = 20; static uint32_t wakeup_cause; // wake up stub function stored in RTC memory -void __attribute__((aligned(4))) wake_stub_example(void) +void wake_stub_example(void) { // Get wakeup cause. wakeup_cause = esp_wake_stub_get_wakeup_cause(); diff --git a/examples/system/deep_sleep_wake_stub/main/wake_stub_example_main.c b/examples/system/deep_sleep_wake_stub/main/wake_stub_example_main.c index 47e49bc939..59262477b4 100644 --- a/examples/system/deep_sleep_wake_stub/main/wake_stub_example_main.c +++ b/examples/system/deep_sleep_wake_stub/main/wake_stub_example_main.c @@ -43,7 +43,6 @@ void app_main(void) rtc_gpio_isolate(GPIO_NUM_12); #endif - // Set the wake stub function esp_set_deep_sleep_wake_stub(&wake_stub_example); printf("Entering deep sleep\n"); From 51777a68626cf48ee3741013e2d71337c7c16d52 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Sun, 26 Feb 2023 23:09:02 +0800 Subject: [PATCH 8/9] gpio: Fix io hold functionality on esp32c6 and esp32h2 --- components/driver/gpio/gpio.c | 5 ++- components/driver/gpio/include/driver/gpio.h | 9 ++-- .../driver/test_apps/gpio/main/test_rtcio.c | 6 +-- components/esp_system/port/cpu_start.c | 2 + components/hal/esp32c6/include/hal/gpio_ll.h | 42 +++++++++--------- .../hal/esp32c6/include/hal/rtc_io_ll.h | 24 +--------- components/hal/esp32h2/include/hal/gpio_ll.h | 44 ++++++++++--------- components/hal/include/hal/gpio_hal.h | 6 ++- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32c6/include/soc/soc_caps.h | 4 +- .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32h2/include/soc/soc_caps.h | 4 +- .../deep_sleep/main/deep_sleep_example_main.c | 2 + 13 files changed, 78 insertions(+), 78 deletions(-) diff --git a/components/driver/gpio/gpio.c b/components/driver/gpio/gpio.c index 610d38efcf..971b2ac5d7 100644 --- a/components/driver/gpio/gpio.c +++ b/components/driver/gpio/gpio.c @@ -734,6 +734,7 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num) return ret; } +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP void gpio_deep_sleep_hold_en(void) { portENTER_CRITICAL(&gpio_context.gpio_spinlock); @@ -747,9 +748,9 @@ void gpio_deep_sleep_hold_dis(void) gpio_hal_deep_sleep_hold_dis(gpio_context.gpio_hal); portEXIT_CRITICAL(&gpio_context.gpio_spinlock); } +#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP #if SOC_GPIO_SUPPORT_FORCE_HOLD - esp_err_t IRAM_ATTR gpio_force_hold_all() { #if SOC_RTCIO_HOLD_SUPPORTED @@ -771,7 +772,7 @@ esp_err_t IRAM_ATTR gpio_force_unhold_all() #endif return ESP_OK; } -#endif +#endif //SOC_GPIO_SUPPORT_FORCE_HOLD void gpio_iomux_in(uint32_t gpio, uint32_t signal_idx) { diff --git a/components/driver/gpio/include/driver/gpio.h b/components/driver/gpio/include/driver/gpio.h index f22d3d1e84..cc8cf8c9f5 100644 --- a/components/driver/gpio/include/driver/gpio.h +++ b/components/driver/gpio/include/driver/gpio.h @@ -374,10 +374,9 @@ esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *stren * in output mode: the output level of the GPIO will be locked and can not be changed. * in input mode: the input read value can still reflect the changes of the input signal. * - * However, this function cannot be used to hold the state of a digital GPIO during Deep-sleep. Even if this - * function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from - * Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call - * `gpio_deep_sleep_hold_en`. + * However, on ESP32/S2/C3/S3/C2, this function cannot be used to hold the state of a digital GPIO during Deep-sleep. + * Even if this function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from + * Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call `gpio_deep_sleep_hold_en`. * * Power down or call `gpio_hold_dis` will disable this function. * @@ -408,6 +407,7 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num); */ esp_err_t gpio_hold_dis(gpio_num_t gpio_num); +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Enable all digital gpio pads hold function during Deep-sleep. * @@ -426,6 +426,7 @@ void gpio_deep_sleep_hold_en(void); * @brief Disable all digital gpio pads hold function during Deep-sleep. */ void gpio_deep_sleep_hold_dis(void); +#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Set pad input to a peripheral signal through the IOMUX. diff --git a/components/driver/test_apps/gpio/main/test_rtcio.c b/components/driver/test_apps/gpio/main/test_rtcio.c index 971711dcfd..a74ecdaaec 100644 --- a/components/driver/test_apps/gpio/main/test_rtcio.c +++ b/components/driver/test_apps/gpio/main/test_rtcio.c @@ -326,10 +326,9 @@ TEST_CASE("RTCIO_output_hold_test", "[rtcio]") ESP_LOGI(TAG, "RTCIO hold test over"); } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6) // TODO: IDF-5349 Remove when deep sleep is supported on ESP32C6 // It is not necessary to test every rtcio pin, it will take too much ci testing time for deep sleep // Only tests on s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX] pin -// (ESP32: IO25, ESP32S2, S3: IO6) these pads' default configuration is low level +// (ESP32: IO25, ESP32S2, S3: IO6, C6: IO5) these pads' default configuration is low level #define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5 static void rtcio_deep_sleep_hold_test_first_stage(void) @@ -375,5 +374,4 @@ static void rtcio_deep_sleep_hold_test_second_stage(void) TEST_CASE_MULTIPLE_STAGES("RTCIO_deep_sleep_output_hold_test", "[rtcio]", rtcio_deep_sleep_hold_test_first_stage, rtcio_deep_sleep_hold_test_second_stage) -#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) -#endif // #if SOC_RTCIO_HOLD_SUPPORTED +#endif //SOC_RTCIO_HOLD_SUPPORTED diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index f641fdc7c0..c2aba37a42 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -541,10 +541,12 @@ void IRAM_ATTR call_start_cpu0(void) #endif #endif +#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6268 // Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins if (rst_reas[0] == RESET_REASON_CORE_DEEP_SLEEP) { esp_deep_sleep_wakeup_io_reset(); } +#endif #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP esp_cache_err_int_init(); diff --git a/components/hal/esp32c6/include/hal/gpio_ll.h b/components/hal/esp32c6/include/hal/gpio_ll.h index a6e64e3e5b..e92c1bc332 100644 --- a/components/hal/esp32c6/include/hal/gpio_ll.h +++ b/components/hal/esp32c6/include/hal/gpio_ll.h @@ -21,7 +21,7 @@ #include "soc/gpio_struct.h" #include "soc/lp_aon_struct.h" #include "soc/lp_io_struct.h" -#include "soc/pmu_reg.h" +#include "soc/pmu_struct.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/pcr_struct.h" #include "soc/clk_tree_defs.h" @@ -355,26 +355,6 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu *strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S); } -/** - * @brief Enable all digital gpio pads hold function during Deep-sleep. - * - * @param hw Peripheral GPIO hardware instance address. - */ -static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) -{ - REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_HIGH_HP_PAD_HOLD_ALL); -} - -/** - * @brief Disable all digital gpio pads hold function during Deep-sleep. - * - * @param hw Peripheral GPIO hardware instance address. - */ -static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) -{ - REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_LOW_HP_PAD_HOLD_ALL); -} - /** * @brief Enable gpio pad hold function. * @@ -497,6 +477,26 @@ static inline void gpio_ll_iomux_set_clk_src(soc_module_clk_t src) } } +/** + * @brief Force hold digital io pad. + * @note GPIO force hold, whether the chip in sleep mode or wakeup mode. + */ +static inline void gpio_ll_force_hold_all(void) +{ + // WT flag, it gets self-cleared after the configuration is done + PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1; +} + +/** + * @brief Force unhold digital io pad. + * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode. + */ +static inline void gpio_ll_force_unhold_all(void) +{ + // WT flag, it gets self-cleared after the configuration is done + PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1; +} + /** * @brief Enable GPIO pin to use sleep mode pin functions during light sleep. * diff --git a/components/hal/esp32c6/include/hal/rtc_io_ll.h b/components/hal/esp32c6/include/hal/rtc_io_ll.h index 7cf23de8ae..159e0fcdd1 100644 --- a/components/hal/esp32c6/include/hal/rtc_io_ll.h +++ b/components/hal/esp32c6/include/hal/rtc_io_ll.h @@ -30,8 +30,6 @@ extern "C" { #define RTCIO_LL_PIN_FUNC 0 -#define RTCIO_LL_PIN_MASK_ALL ((1 << SOC_RTCIO_PIN_COUNT) - 1) - typedef enum { RTCIO_FUNC_RTC = 0x0, /*!< The pin controlled by RTC module. */ RTCIO_FUNC_DIGITAL = 0x1, /*!< The pin controlled by DIGITAL module. */ @@ -244,22 +242,6 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num) LP_AON.gpio_hold0.gpio_hold0 &= ~BIT(rtcio_num); } -/** - * @brief Enable all LP IO pads hold function during Deep-sleep - */ -static inline void rtcio_ll_deep_sleep_hold_en_all(void) -{ - PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1; -} - -/** - * @brief Disable all LP IO pads hold function during Deep-sleep - */ -static inline void rtcio_ll_deep_sleep_hold_dis_all(void) -{ - PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1; -} - /** * Enable force hold function for all RTC IO pads * @@ -270,8 +252,7 @@ static inline void rtcio_ll_deep_sleep_hold_dis_all(void) */ static inline void rtcio_ll_force_hold_all(void) { - // No such a 'hold_all' bit on C6, use bit hold instead - LP_AON.gpio_hold0.gpio_hold0 |= RTCIO_LL_PIN_MASK_ALL; + PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1; } /** @@ -281,8 +262,7 @@ static inline void rtcio_ll_force_hold_all(void) */ static inline void rtcio_ll_force_unhold_all(void) { - // No such a 'hold_all' bit on C6, use bit hold instead - LP_AON.gpio_hold0.gpio_hold0 &= ~RTCIO_LL_PIN_MASK_ALL; + PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1; } /** diff --git a/components/hal/esp32h2/include/hal/gpio_ll.h b/components/hal/esp32h2/include/hal/gpio_ll.h index 6d2e2abc71..e999d4e9f8 100644 --- a/components/hal/esp32h2/include/hal/gpio_ll.h +++ b/components/hal/esp32h2/include/hal/gpio_ll.h @@ -20,7 +20,7 @@ #include "soc/gpio_periph.h" #include "soc/gpio_struct.h" #include "soc/lp_aon_struct.h" -#include "soc/pmu_reg.h" +#include "soc/pmu_struct.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/pcr_struct.h" #include "soc/clk_tree_defs.h" @@ -398,26 +398,6 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_ *strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S); } -/** - * @brief Enable all digital gpio pad hold function during Deep-sleep. - * - * @param hw Peripheral GPIO hardware instance address. - */ -static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) -{ - REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_HIGH_HP_PAD_HOLD_ALL); -} - -/** - * @brief Disable all digital gpio pad hold function during Deep-sleep. - * - * @param hw Peripheral GPIO hardware instance address. - */ -static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) -{ - REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_LOW_HP_PAD_HOLD_ALL); -} - /** * @brief Enable gpio pad hold function. * @@ -522,6 +502,28 @@ static inline void gpio_ll_iomux_set_clk_src(soc_module_clk_t src) } } +/** + * @brief Force hold all digital(VDDPST2) and lp(VDDPST1) io pads. + * @note GPIO force hold, whether the chip in sleep mode or wakeup mode. + */ +static inline void gpio_ll_force_hold_all(void) +{ + // WT flags, they get self-cleared after the configuration is done + PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1; +} + +/** + * @brief Force unhold all digital(VDDPST2) and lp(VDDPST1) io pads. + * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode. + */ +static inline void gpio_ll_force_unhold_all(void) +{ + // WT flags, they get self-cleared after the configuration is done + PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1; +} + /** * @brief Enable GPIO pin to use sleep mode pin functions during light sleep. * diff --git a/components/hal/include/hal/gpio_hal.h b/components/hal/include/hal/gpio_hal.h index b765e7c0b9..22fba943f7 100644 --- a/components/hal/include/hal/gpio_hal.h +++ b/components/hal/include/hal/gpio_hal.h @@ -242,8 +242,8 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num); * in output mode: the output level of the pad will be force locked and can not be changed. * in input mode: the input value read will not change, regardless the changes of input signal. * - * The state of digital gpio cannot be held during Deep-sleep, and it will resume the hold function - * when the chip wakes up from Deep-sleep. If the digital gpio also needs to be held during Deep-sleep, + * On ESP32/S2/C3/S3/C2, the state of digital gpio cannot be held during Deep-sleep, and it will resume the hold + * function when the chip wakes up from Deep-sleep. If the digital gpio also needs to be held during Deep-sleep, * `gpio_deep_sleep_hold_en` should also be called. * * Power down or call gpio_hold_dis will disable this function. @@ -285,6 +285,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num); */ #define gpio_hal_is_digital_io_hold(hal, gpio_num) gpio_ll_is_digital_io_hold((hal)->dev, gpio_num) +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Enable all digital gpio pad hold function during Deep-sleep. * @@ -315,6 +316,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num); * - false deep sleep hold is disabled */ #define gpio_hal_deep_sleep_hold_is_en(hal) gpio_ll_deep_sleep_hold_is_en((hal)->dev) +#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Set pad input to a peripheral signal through the IOMUX. diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 098dd3904d..49d9ca8f38 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -403,6 +403,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x000000007FFFFF00 +config SOC_GPIO_SUPPORT_FORCE_HOLD + bool + default y + config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 62f0120329..96e2a9c345 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -184,7 +184,9 @@ // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_8~GPIO_NUM_30) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x000000007FFFFF00ULL -// Support to hold a single GPIO when the digital domain is powered off +// Support to force hold all IOs +#define SOC_GPIO_SUPPORT_FORCE_HOLD (1) +// Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) /*-------------------------- RTCIO CAPS --------------------------------------*/ diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index c66e51f6dc..795a6379c0 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -371,6 +371,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x000000000FFF807F +config SOC_GPIO_SUPPORT_FORCE_HOLD + bool + default y + config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index c1ad381f06..439b99a112 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -181,7 +181,9 @@ // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_0~6. GPIO_NUM_15~27) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x000000000FFF807FULL -// Support to hold a single GPIO when the digital domain is powered off +// Support to force hold all IOs +#define SOC_GPIO_SUPPORT_FORCE_HOLD (1) +// Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) /*-------------------------- Dedicated GPIO CAPS -----------------------------*/ diff --git a/examples/system/deep_sleep/main/deep_sleep_example_main.c b/examples/system/deep_sleep/main/deep_sleep_example_main.c index 4ae570e79d..b8e60afc6e 100644 --- a/examples/system/deep_sleep/main/deep_sleep_example_main.c +++ b/examples/system/deep_sleep/main/deep_sleep_example_main.c @@ -133,7 +133,9 @@ void app_main(void) * during deepsleep. However, RTC IO relies on the RTC_PERIPH power domain. Keeping this power domain on will * increase some power comsumption. */ # if CONFIG_EXAMPLE_EXT1_USE_INTERNAL_PULLUPS +#if SOC_PM_SUPPORT_RTC_PERIPH_PD ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); +#endif ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_1)); ESP_ERROR_CHECK(rtc_gpio_pulldown_en(ext_wakeup_pin_1)); ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_2)); From 975a53aee1f0cb81db86bc7899e4b448253d26bd Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 28 Feb 2023 20:04:30 +0800 Subject: [PATCH 9/9] bugfix: workaround for CPU stuck due to DBUS request blocking when fetching unaligned instructions in LP_RAM --- components/esp_hw_support/sleep_wake_stub.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/sleep_wake_stub.c b/components/esp_hw_support/sleep_wake_stub.c index 7c49241ba9..ec8153fe8c 100644 --- a/components/esp_hw_support/sleep_wake_stub.c +++ b/components/esp_hw_support/sleep_wake_stub.c @@ -11,6 +11,7 @@ #include "esp_attr.h" #include "esp_sleep.h" +#include "esp_cpu.h" #include "soc/soc.h" #include "soc/rtc.h" @@ -77,7 +78,11 @@ void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub) #endif // A few CPU cycles may be necessary for the sleep to start... - while (true) {}; +#if __XTENSA__ + xt_utils_wait_for_intr(); +#else + rv_utils_wait_for_intr(); +#endif // __XTENSA__ // never reaches here. }