Merge branch 'feature/example_deep_sleep_wake_stub' into 'master'

make wake stub worked on ESP32/S2/C3/S3

Closes IDFGH-6564

See merge request espressif/esp-idf!17952
This commit is contained in:
Jiang Jiang Jian
2023-01-10 23:40:10 +08:00
39 changed files with 755 additions and 146 deletions

View File

@@ -79,6 +79,10 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "mspi_timing_tuning.c" "port/${target}/mspi_timing_config.c")
endif()
if(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED)
list(APPEND srcs "sleep_wake_stub.c")
endif()
if(CONFIG_IDF_TARGET_ESP32H2)
list(REMOVE_ITEM srcs
"adc_share_hw_ctrl.c" # TODO: IDF-6215

View File

@@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_log.h"
#include "esp_sleep.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RTC_STR(str) (__extension__({static const RTC_RODATA_ATTR char _fmt[] = (str); (const char *)&_fmt;}))
#define RTC_LOG_FORMAT(letter, format) LOG_COLOR_ ## letter format LOG_RESET_COLOR "\n"
#define ESP_RTC_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { esp_rom_printf(RTC_STR(format), ##__VA_ARGS__); \
esp_wake_stub_uart_tx_wait_idle(0); }
#define ESP_RTC_LOGE( format, ... ) ESP_RTC_LOG(ESP_LOG_ERROR, RTC_LOG_FORMAT(E, format), ##__VA_ARGS__)
#define ESP_RTC_LOGW( format, ... ) ESP_RTC_LOG(ESP_LOG_WARN, RTC_LOG_FORMAT(W, format), ##__VA_ARGS__)
#define ESP_RTC_LOGI( format, ... ) ESP_RTC_LOG(ESP_LOG_INFO, RTC_LOG_FORMAT(I, format), ##__VA_ARGS__)
#define ESP_RTC_LOGD( format, ... ) ESP_RTC_LOG(ESP_LOG_DEBUG, RTC_LOG_FORMAT(D, format), ##__VA_ARGS__)
#define ESP_RTC_LOGV( format, ... ) ESP_RTC_LOG(ESP_LOG_VERBOSE, RTC_LOG_FORMAT(V, format), ##__VA_ARGS__)
/**
* @brief Enter deep-sleep mode from deep sleep wake stub code
*
* This should be called from the wake stub code.
*
* @param new_stub new wake stub function will be set
*/
void esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub);
/**
* @brief Wait while uart transmission is in progress
*
* This function is waiting while uart transmission is not completed,
* and this function should be called from the wake stub code.
*
* @param uart_no UART port to wait idle
*/
void esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no);
/**
* @brief Set wakeup time from deep sleep stub.
*
* This should be called from the wake stub code.
*
* @param time_in_us wakeup time in us
*/
void esp_wake_stub_set_wakeup_time(uint64_t time_in_us);
/**
* @brief Get wakeup cause from deep sleep stub.
*
* This should be called from the wake stub code.
*
* @return wakeup casue value
*/
uint32_t esp_wake_stub_get_wakeup_cause(void);
#ifdef __cplusplus
}
#endif

View File

@@ -7,6 +7,7 @@
#include <stdint.h>
#include "esp_rom_sys.h"
#include "hal/clk_tree_ll.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/rtc.h"
#include "soc/timer_periph.h"
#include "esp_hw_log.h"
@@ -152,20 +153,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
int attempts = 1000;
while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) {
esp_rom_delay_us(1); // might take 1 RTC slowclk period, don't flood RTC bus
if (attempts) {
if (--attempts == 0 && clk_ll_xtal32k_digi_is_enabled()) {
ESP_HW_LOGE(TAG, "rtc_time_get() 32kHz xtal has been stopped");
}
}
}
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}
void rtc_clk_wait_for_slow_cycle(void)

View File

@@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "hal/clk_tree_ll.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/timer_group_reg.h"
#include "esp_rom_sys.h"
@@ -166,10 +167,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}
uint64_t rtc_light_slp_time_get(void)

View File

@@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "hal/clk_tree_ll.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/timer_group_reg.h"
#include "esp_rom_sys.h"
@@ -169,10 +170,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}
uint64_t rtc_light_slp_time_get(void)

View File

@@ -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
*/
@@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/lp_timer_reg.h"
#include "hal/clk_tree_ll.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/timer_group_reg.h"
#include "esp_rom_sys.h"
#include "assert.h"
@@ -206,10 +207,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(LP_TIMER_UPDATE_REG, LP_TIMER_MAIN_TIMER_UPDATE);
uint64_t t = READ_PERI_REG(LP_TIMER_MAIN_BUF0_LOW_REG);
t |= ((uint64_t) READ_PERI_REG(LP_TIMER_MAIN_BUF0_HIGH_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}
uint64_t rtc_light_slp_time_get(void)

View File

@@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "hal/clk_tree_ll.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/timer_group_reg.h"
#include "esp_rom_sys.h"
@@ -163,10 +164,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}
uint64_t rtc_light_slp_time_get(void)

View File

@@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "hal/clk_tree_ll.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/timer_group_reg.h"
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
@@ -234,10 +235,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}
uint64_t rtc_light_slp_time_get(void)

View File

@@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "hal/clk_tree_ll.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/timer_group_reg.h"
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
@@ -168,10 +169,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}
uint64_t rtc_light_slp_time_get(void)

View File

@@ -1272,11 +1272,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
return ESP_SLEEP_WAKEUP_UNDEFINED;
}
#ifdef CONFIG_IDF_TARGET_ESP32
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
#else
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
#endif
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
if (wakeup_cause & RTC_TIMER_TRIG_EN) {
return ESP_SLEEP_WAKEUP_TIMER;

View File

@@ -0,0 +1,81 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include <sys/lock.h>
#include <sys/param.h>
#include "esp_attr.h"
#include "esp_sleep.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/soc_caps.h"
#include "hal/rtc_cntl_ll.h"
#include "hal/uart_ll.h"
#include "sdkconfig.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H4
#include "esp32h4/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h"
#endif
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.
REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
set_rtc_memory_crc();
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_MEM
// Go to sleep.
rtc_cntl_ll_sleep_enable();
// A few CPU cycles may be necessary for the sleep to start...
while (true) {};
// never reaches here.
}
void RTC_IRAM_ATTR esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no)
{
while (!uart_ll_is_tx_idle(UART_LL_GET_HW(uart_no))) {};
}
void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us)
{
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();
rtc_cntl_ll_set_wakeup_timer(rtc_curr_count + rtc_count_delta);
}
uint32_t RTC_IRAM_ATTR esp_wake_stub_get_wakeup_cause(void)
{
return rtc_cntl_ll_get_wakeup_cause();
}

View File

@@ -63,7 +63,7 @@ SECTIONS
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location

View File

@@ -59,7 +59,7 @@ SECTIONS
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location
@@ -67,7 +67,7 @@ SECTIONS
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
*rtc_wake_stub*.*(COMMON)
mapping[rtc_bss]

View File

@@ -59,7 +59,7 @@ SECTIONS
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.);
} > lp_ram_seg
@@ -67,7 +67,7 @@ SECTIONS
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
*rtc_wake_stub*.*(COMMON)
mapping[rtc_bss]

View File

@@ -59,7 +59,7 @@ SECTIONS
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.);
} > lp_ram_seg
@@ -67,7 +67,7 @@ SECTIONS
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
*rtc_wake_stub*.*(COMMON)
mapping[rtc_bss]

View File

@@ -61,7 +61,7 @@ SECTIONS
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location
@@ -69,7 +69,7 @@ SECTIONS
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
*rtc_wake_stub*.*(COMMON)
mapping[rtc_bss]

View File

@@ -71,7 +71,7 @@ SECTIONS
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location

View File

@@ -65,7 +65,7 @@ SECTIONS
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location

View File

@@ -445,8 +445,7 @@ __attribute__((unused)) static float get_time_ms(void)
__attribute__((unused)) static uint32_t get_cause(void)
{
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, \
RTC_CNTL_WAKEUP_CAUSE);
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
return wakeup_cause;
}

View File

@@ -8,71 +8,107 @@
#include "soc/soc.h"
#include "soc/rtc.h"
#include "esp_attr.h"
#include "clk_tree_ll.h"
#include "esp_rom_sys.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
}
static inline void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
{
REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, mask);
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
mode, RTC_CNTL_EXT_WAKEUP1_LV_S);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL);
}
static inline void rtc_cntl_ll_ulp_wakeup_enable(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ulp_wakeup_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_WAKEUP_FORCE_EN);
}
static inline void rtc_cntl_ll_ulp_int_clear(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ulp_int_clear(void)
{
REG_SET_BIT(RTC_CNTL_INT_CLR_REG, RTC_CNTL_SAR_INT_CLR);
}
static inline void rtc_cntl_ll_timer2_set_touch_wait_cycle(uint32_t wait_cycle)
FORCE_INLINE_ATTR void rtc_cntl_ll_timer2_set_touch_wait_cycle(uint32_t wait_cycle)
{
REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, wait_cycle);
}
static inline void rtc_cntl_ll_reset_system(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
}
static inline void rtc_cntl_ll_reset_cpu(int cpu_no)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
{
uint32_t rtc_cntl_rst = (cpu_no == 0) ? RTC_CNTL_SW_PROCPU_RST : RTC_CNTL_SW_APPCPU_RST;
REG_WRITE(RTC_CNTL_OPTIONS0_REG, rtc_cntl_rst);
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
int attempts = 1000;
while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) {
esp_rom_delay_us(1);
if (attempts) {
if (--attempts == 0 && clk_ll_xtal32k_digi_is_enabled()) {
esp_rom_printf("32KHz xtal has been stopped\n");
}
}
}
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
uint32_t slow_clk_value = REG_READ(RTC_CNTL_STORE1_REG);
return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value);
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
return REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
}
#ifdef __cplusplus
}
#endif

View File

@@ -10,12 +10,13 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
@@ -24,18 +25,18 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS);
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(uint32_t addr)
{
/* write memory address to register */
REG_SET_FIELD(SYSCON_RETENTION_CTRL_REG, SYSCON_RETENTION_LINK_ADDR, (uint32_t)addr);
@@ -45,21 +46,45 @@ static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr)
REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
static inline void rtc_cntl_ll_disable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void)
{
REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
static inline void rtc_cntl_ll_reset_system(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
}
static inline void rtc_cntl_ll_reset_cpu(int cpu_no)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
uint32_t slow_clk_value = REG_READ(RTC_CNTL_STORE1_REG);
return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value);
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
}
#ifdef __cplusplus
}
#endif

View File

@@ -10,12 +10,13 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
@@ -24,48 +25,72 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS);
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
{
REG_SET_FIELD(SYSCON_RETENTION_CTRL_REG, SYSCON_RETENTION_LINK_ADDR, (uint32_t)addr);
}
static inline void rtc_cntl_ll_enable_cpu_retention_clock(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention_clock(void)
{
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN);
}
static inline void rtc_cntl_ll_enable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(void)
{
/* Enable retention when cpu sleep enable */
REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
static inline void rtc_cntl_ll_disable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void)
{
REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
static inline void rtc_cntl_ll_reset_system(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
}
static inline void rtc_cntl_ll_reset_cpu(int cpu_no)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
uint32_t slow_clk_value = REG_READ(RTC_CNTL_STORE1_REG);
return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value);
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
}
#ifdef __cplusplus
}
#endif

View File

@@ -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
*/
@@ -9,57 +9,81 @@
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/lp_aon_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
// TODO: IDF-5645
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
{
// TODO: IDF-5645
return 0;
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_status(void)
{
// TODO: IDF-5645
}
static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
{
// TODO: IDF-5718 has removed the retention feature
}
static inline void rtc_cntl_ll_enable_cpu_retention_clock(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention_clock(void)
{
// TODO: IDF-5718 has removed the retention feature
}
static inline void rtc_cntl_ll_enable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(void)
{
// TODO: IDF-5718 has removed the retention feature
}
static inline void rtc_cntl_ll_disable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void)
{
// TODO: IDF-5718 has removed the retention feature
}
static inline void rtc_cntl_ll_reset_system(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
{
REG_SET_BIT(LP_AON_SYS_CFG_REG, LP_AON_HPSYS_SW_RESET);
}
static inline void rtc_cntl_ll_reset_cpu(int cpu_no)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
{
REG_SET_BIT(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
// TODO: IDF-6064
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
// TODO: IDF-6064
return 0;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
// TODO: IDF-6064
return 0;
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
// TODO: IDF-6064
return 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -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
*/
@@ -8,63 +8,87 @@
#include "soc/soc.h"
#include "soc/rtc.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
// ESP32H2-TODO: IDF-6401
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_pins(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_pins(void)
{
return 0;
// ESP32H2-TODO: IDF-6401
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
{
// ESP32H2-TODO: IDF-6401
return 0;
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_status(void)
{
// ESP32H2-TODO: IDF-6401
}
static inline void rtc_cntl_ll_gpio_set_wakeup_pins(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_set_wakeup_pins(void)
{
// ESP32H2-TODO: IDF-5718
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_pins(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_pins(void)
{
// ESP32H2-TODO: IDF-5718
}
static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
{
// ESP32H2-TODO: IDF-5718 has removed the retention feature
}
static inline void rtc_cntl_ll_enable_cpu_retention_clock(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention_clock(void)
{
// ESP32H2-TODO: IDF-5718 has removed the retention feature
}
static inline void rtc_cntl_ll_enable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(void)
{
// ESP32H2-TODO: IDF-5718 has removed the retention feature
}
static inline void rtc_cntl_ll_disable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void)
{
// ESP32H2-TODO: IDF-5718 has removed the retention feature
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
// TODO: IDF-6572
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
// TODO: IDF-6572
return 0;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
// TODO: IDF-6572
return 0;
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
// TODO: IDF-6572
return 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -10,12 +10,13 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
@@ -24,37 +25,61 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS);
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(uint32_t addr)
{
// ESP32H4-TODO: IDF-3383
}
static inline void rtc_cntl_ll_disable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void)
{
// ESP32H4-TODO: IDF-3383
}
static inline void rtc_cntl_ll_reset_system(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
}
static inline void rtc_cntl_ll_reset_cpu(int cpu_no)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
uint32_t slow_clk_value = REG_READ(RTC_CNTL_STORE1_REG);
return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value);
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
}
#ifdef __cplusplus
}
#endif

View File

@@ -9,12 +9,13 @@
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
@@ -23,55 +24,79 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
}
static inline void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
{
REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, mask);
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
mode, RTC_CNTL_EXT_WAKEUP1_LV_S);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL);
}
static inline void rtc_cntl_ll_ulp_int_clear(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ulp_int_clear(void)
{
REG_SET_BIT(RTC_CNTL_INT_CLR_REG, RTC_CNTL_ULP_CP_INT_CLR);
REG_SET_BIT(RTC_CNTL_INT_CLR_REG, RTC_CNTL_COCPU_INT_CLR);
REG_SET_BIT(RTC_CNTL_INT_CLR_REG, RTC_CNTL_COCPU_TRAP_INT_CLR);
}
static inline void rtc_cntl_ll_timer2_set_touch_wait_cycle(uint32_t wait_cycle)
FORCE_INLINE_ATTR void rtc_cntl_ll_timer2_set_touch_wait_cycle(uint32_t wait_cycle)
{
REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, wait_cycle);
}
static inline void rtc_cntl_ll_reset_system(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
}
static inline void rtc_cntl_ll_reset_cpu(int cpu_no)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
uint32_t slow_clk_value = REG_READ(RTC_CNTL_STORE1_REG);
return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value);
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
}
#ifdef __cplusplus
}
#endif

View File

@@ -10,6 +10,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/apb_ctrl_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
@@ -18,7 +19,7 @@ extern "C" {
#define RTC_CNTL_LL_RETENTION_TARGET_CPU (BIT(0))
#define RTC_CNTL_LL_RETENTION_TARGET_TAGMEM (BIT(1))
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
@@ -27,46 +28,46 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_status(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
}
static inline void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
{
REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, mask);
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
mode, RTC_CNTL_EXT_WAKEUP1_LV_S);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL);
}
static inline void rtc_cntl_ll_set_tagmem_retention_link_addr(uint32_t link_addr)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_tagmem_retention_link_addr(uint32_t link_addr)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL1_REG, APB_CTRL_RETENTION_TAG_LINK_ADDR, link_addr);
}
static inline void rtc_cntl_ll_enable_tagmem_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_tagmem_retention(void)
{
/* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */
uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | RTC_CNTL_LL_RETENTION_TARGET_TAGMEM));
}
static inline void rtc_cntl_ll_enable_icache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_icache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_START_POINT, start_point);
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_VLD_SIZE, vld_size);
@@ -74,7 +75,7 @@ static inline void rtc_cntl_ll_enable_icache_tagmem_retention(uint32_t start_poi
REG_SET_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE);
}
static inline void rtc_cntl_ll_enable_dcache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_dcache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_START_POINT, start_point);
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_VLD_SIZE, vld_size);
@@ -82,34 +83,34 @@ static inline void rtc_cntl_ll_enable_dcache_tagmem_retention(uint32_t start_poi
REG_SET_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE);
}
static inline void rtc_cntl_ll_disable_tagmem_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_tagmem_retention(void)
{
/* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */
uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target & ~RTC_CNTL_LL_RETENTION_TARGET_TAGMEM));
}
static inline void rtc_cntl_ll_disable_icache_tagmem_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_icache_tagmem_retention(void)
{
REG_CLR_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE);
}
static inline void rtc_cntl_ll_disable_dcache_tagmem_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_dcache_tagmem_retention(void)
{
REG_CLR_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE);
}
static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t link_addr)
FORCE_INLINE_ATTR void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t link_addr)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_CPU_LINK_ADDR, link_addr);
}
static inline void rtc_cntl_ll_enable_cpu_retention_clock(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention_clock(void)
{
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); /* Enable internal 20 MHz clock */
}
static inline void rtc_cntl_ll_enable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(void)
{
uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET);
@@ -118,41 +119,65 @@ static inline void rtc_cntl_ll_enable_cpu_retention(void)
REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
static inline void rtc_cntl_ll_config_cpu_retention_timing(int wait, int clkoff_wait, int done_wait)
FORCE_INLINE_ATTR void rtc_cntl_ll_config_cpu_retention_timing(int wait, int clkoff_wait, int done_wait)
{
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_WAIT, wait);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_CLKOFF_WAIT, clkoff_wait);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_DONE_WAIT, done_wait);
}
static inline void rtc_cntl_ll_disable_cpu_retention(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void)
{
REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
static inline void rtc_cntl_ll_ulp_int_clear(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_ulp_int_clear(void)
{
REG_SET_BIT(RTC_CNTL_INT_CLR_REG, RTC_CNTL_ULP_CP_INT_CLR);
REG_SET_BIT(RTC_CNTL_INT_CLR_REG, RTC_CNTL_COCPU_INT_CLR);
REG_SET_BIT(RTC_CNTL_INT_CLR_REG, RTC_CNTL_COCPU_TRAP_INT_CLR);
}
static inline void rtc_cntl_ll_timer2_set_touch_wait_cycle(uint32_t wait_cycle)
FORCE_INLINE_ATTR void rtc_cntl_ll_timer2_set_touch_wait_cycle(uint32_t wait_cycle)
{
REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, wait_cycle);
}
static inline void rtc_cntl_ll_reset_system(void)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
{
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
}
static inline void rtc_cntl_ll_reset_cpu(int cpu_no)
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
{
uint32_t rtc_cntl_rst = (cpu_no == 0) ? RTC_CNTL_SW_PROCPU_RST : RTC_CNTL_SW_APPCPU_RST;
REG_WRITE(RTC_CNTL_OPTIONS0_REG, rtc_cntl_rst);
}
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
}
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
{
uint32_t slow_clk_value = REG_READ(RTC_CNTL_STORE1_REG);
return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value);
}
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
{
return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
}
#ifdef __cplusplus
}
#endif

View File

@@ -115,3 +115,12 @@ CRC Check For Wake Stubs
.. note::
When the `CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP` option is enabled, all the RTC fast memory except the wake stubs area is added to the heap.
Example
-------
.. only:: SOC_RTC_FAST_MEM_SUPPORTED
ESP-IDF provides an example to show how to implement the Deep-sleep wake stub.
- :example:`system/deep_sleep_wake_stub`

View File

@@ -42,6 +42,12 @@ examples/system/deep_sleep:
temporary: true
reason: target(s) not supported yet
examples/system/deep_sleep_wake_stub:
disable:
- if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"]
temporary: true
reason: target(s) is not supported yet
examples/system/efuse:
disable_test:
- if: IDF_TARGET == "esp32s3"

View File

@@ -68,7 +68,7 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
## Example Output
On initial startup, this example will detect that this is the first boot and output the following low:
On initial startup, this example will detect that this is the first boot and output the following log:
```
...

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(deep_sleep_wake_stub)

View File

@@ -0,0 +1,75 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# Deep Sleep Wake Stub Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
The [Deep-sleep wake stub](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/deep-sleep-stub.html) is used to RTC fast boot mode that avoid the SPI flash booting, thus speeding up the wakeup process. This example demonstrates how to implement the wake stub.
In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot.
## How to use example
### Hardware Required
This example should be able to run on any commonly available ESP32/ESP32-S2/ESP32-S3/ESP32-C3 development board without any extra hardware if only **Timer** wake up sources are used.
### Configure the project
```
idf.py menuconfig
```
* **Wake up time** can be configured via `Example configuration > Wake up interval in seconds`
Wake up sources that are unused or unconnected should be disabled in configuration to prevent inadvertent triggering of wake up as a result of floating pins.
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
```
(Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example Output
On initial startup, this example will detect that this is the first boot and output the following log:
```
...
I (309) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
Not a deep sleep reset
Enabling timer wakeup, 10s
Entering deep sleep
```
The ESP chips will then enter deep sleep. When a timer wake up occurs, if deep sleep wake stub enabled, the ESP chips will boot from RTC memory and execute stub code. The output log such as the following:
```
...
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x5 (DSLEEP),boot:0x8 (SPI_FAST_FLASH_BOOT)
wake stub: wakeup count is 1, wakeup cause is 8
wake stub: going to deep sleep
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x5 (DSLEEP),boot:0x8 (SPI_FAST_FLASH_BOOT)
wake stub: wakeup count is 2, wakeup cause is 8
wake stub: going to deep sleep
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x5 (DSLEEP),boot:0x8 (SPI_FAST_FLASH_BOOT)
wake stub: wakeup count is 3, wakeup cause is 8
wake stub: going to deep sleep
```

View File

@@ -0,0 +1,3 @@
idf_component_register(SRCS "wake_stub_example_main.c"
"rtc_wake_stub_example.c"
INCLUDE_DIRS ".")

View File

@@ -0,0 +1,10 @@
menu "Example Configuration"
config WAKE_UP_TIME
int "Wake up interval in seconds"
default 10
range 1 60
help
Configurable wake up interval in seconds.
endmenu

View File

@@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <inttypes.h>
#include "esp_sleep.h"
#include "esp_wake_stub.h"
#include "sdkconfig.h"
/*
* Deep sleep wake stub function is a piece of code that will be loaded into 'RTC Fast Memory'.
* The first way is to use the RTC_IRAM_ATTR attribute to place a function into RTC memory,
* The second way is to place the function into any source file whose name starts with rtc_wake_stub.
* Files names rtc_wake_stub* have their contents automatically put into RTC memory by the linker.
*
* First, call esp_set_deep_sleep_wake_stub to set the wake stub function as the RTC stub entry,
* The wake stub function runs immediately as soon as the chip wakes up - before any normal
* initialisation, bootloader, or ESP-IDF code has run. After the wake stub runs, the SoC
* can go back to sleep or continue to start ESP-IDF normally.
*
* Wake stub code must be carefully written, there are some rules for wake stub:
* 1) The wake stub code can only access data loaded in RTC memory.
* 2) The wake stub code can only call functions implemented in ROM or loaded into RTC Fast Memory.
* 3) RTC memory must include any read-only data (.rodata) used by the wake stub.
*/
// counter value, stored in RTC memory
static uint32_t s_count = 0;
static const uint32_t s_max_count = 20;
// wakeup_cause stored in RTC memory
static uint32_t wakeup_cause;
// wake up stub function stored in RTC memory
void wake_stub_example(void)
{
// Get wakeup cause.
wakeup_cause = esp_wake_stub_get_wakeup_cause();
// Increment the counter.
s_count++;
// Print the counter value and wakeup cause.
ESP_RTC_LOGI("wake stub: wakeup count is %d, wakeup cause is %d", s_count, wakeup_cause);
if (s_count >= s_max_count) {
// Reset s_count
s_count = 0;
// Set the default wake stub.
// There is a default version of this function provided in esp-idf.
esp_default_wake_deep_sleep();
// Return from the wake stub function to continue
// booting the firmware.
return;
}
// s_count is < s_max_count, go back to deep sleep.
// Set wakeup time in stub, if need to check GPIOs or read some sensor periodically in the stub.
esp_wake_stub_set_wakeup_time(CONFIG_WAKE_UP_TIME*1000000);
// Print status.
ESP_RTC_LOGI("wake stub: going to deep sleep");
// Set stub entry, then going to deep sleep again.
esp_wake_stub_sleep(&wake_stub_example);
}

View File

@@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void wake_stub_example(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,53 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_sleep.h"
#include "esp_wake_stub.h"
#include "driver/rtc_io.h"
#include "rtc_wake_stub_example.h"
// sleep_enter_time stored in RTC memory
static RTC_DATA_ATTR struct timeval sleep_enter_time;
void app_main(void)
{
struct timeval now;
gettimeofday(&now, NULL);
int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000;
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TIMER) {
printf("Wake up from timer. Time spent in deep sleep: %dms\n", sleep_time_ms);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
const int wakeup_time_sec = CONFIG_WAKE_UP_TIME;
printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
#if CONFIG_IDF_TARGET_ESP32
// Isolate GPIO12 pin from external circuits. This is needed for modules
// which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
// to minimize current consumption.
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");
gettimeofday(&sleep_enter_time, NULL);
esp_deep_sleep_start();
}

View File

@@ -0,0 +1,28 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import time
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c3
@pytest.mark.generic
@pytest.mark.parametrize('config', ['default',], indirect=True)
def test_deep_sleep_wake_stub(config: str, dut: Dut) -> None:
if config == 'default':
dut.expect_exact('Enabling timer wakeup, 10s', timeout=10)
dut.expect_exact('Entering deep sleep', timeout=10)
start_sleep = time.time()
logging.info('Waiting for wakeup...')
dut.expect_exact('wake stub: going to deep sleep')
sleep_time = time.time() - start_sleep
logging.info('Host measured sleep time at {:.2f}s'.format(sleep_time))
assert 8 < sleep_time < 12 # note: high tolerance as measuring time on the host may have some timing skew

View File

@@ -0,0 +1 @@
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y