From 9eae151f7ceacb497252621947e61105f90df01d Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Sat, 18 Feb 2023 14:13:52 +0800 Subject: [PATCH] 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();