forked from espressif/esp-idf
Merge branch 'feature/introduce_internal_sleep_sub_mode_configure_api' into 'master'
feat(esp_hw_support): introduce internal sleep sub mode configure api Closes PM-216 See merge request espressif/esp-idf!30687
This commit is contained in:
@ -127,7 +127,7 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a
|
|||||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||||
} else {
|
} else {
|
||||||
#if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED
|
#if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED
|
||||||
esp_sleep_enable_adc_tsens_monitor(true);
|
esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle)
|
|||||||
sar_periph_ctrl_adc_oneshot_power_release();
|
sar_periph_ctrl_adc_oneshot_power_release();
|
||||||
} else {
|
} else {
|
||||||
#if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED
|
#if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED
|
||||||
esp_sleep_enable_adc_tsens_monitor(false);
|
esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "driver/ledc.h"
|
#include "driver/ledc.h"
|
||||||
#include "esp_rom_gpio.h"
|
#include "esp_rom_gpio.h"
|
||||||
#include "clk_ctrl_os.h"
|
#include "clk_ctrl_os.h"
|
||||||
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
#include "esp_private/gpio.h"
|
#include "esp_private/gpio.h"
|
||||||
#include "esp_private/esp_gpio_reserve.h"
|
#include "esp_private/esp_gpio_reserve.h"
|
||||||
@ -561,6 +562,16 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
|||||||
}
|
}
|
||||||
p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_num] = true;
|
p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_num] = true;
|
||||||
if (p_ledc_obj[speed_mode]->glb_clk != glb_clk) {
|
if (p_ledc_obj[speed_mode]->glb_clk != glb_clk) {
|
||||||
|
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||||
|
/* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */
|
||||||
|
if (glb_clk == LEDC_SLOW_CLK_RC_FAST) {
|
||||||
|
/* Keep ESP_PD_DOMAIN_RC_FAST on during light sleep */
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, true);
|
||||||
|
} else if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_RC_FAST) {
|
||||||
|
/* No need to keep ESP_PD_DOMAIN_RC_FAST on during light sleep anymore */
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// TODO: release old glb_clk (if not UNINIT), and acquire new glb_clk [clk_tree]
|
// TODO: release old glb_clk (if not UNINIT), and acquire new glb_clk [clk_tree]
|
||||||
p_ledc_obj[speed_mode]->glb_clk = glb_clk;
|
p_ledc_obj[speed_mode]->glb_clk = glb_clk;
|
||||||
LEDC_FUNC_CLOCK_ATOMIC() {
|
LEDC_FUNC_CLOCK_ATOMIC() {
|
||||||
@ -571,12 +582,6 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
|||||||
portEXIT_CRITICAL(&ledc_spinlock);
|
portEXIT_CRITICAL(&ledc_spinlock);
|
||||||
|
|
||||||
ESP_LOGD(LEDC_TAG, "In slow speed mode, global clk set: %d", glb_clk);
|
ESP_LOGD(LEDC_TAG, "In slow speed mode, global clk set: %d", glb_clk);
|
||||||
|
|
||||||
/* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */
|
|
||||||
#if SOC_LIGHT_SLEEP_SUPPORTED
|
|
||||||
extern void esp_sleep_periph_use_8m(bool use_or_not);
|
|
||||||
esp_sleep_periph_use_8m(glb_clk == LEDC_SLOW_CLK_RC_FAST);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The divisor is correct, we can write in the hardware. */
|
/* The divisor is correct, we can write in the hardware. */
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "unity_test_utils.h"
|
#include "unity_test_utils.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
#define TEST_MEMORY_LEAK_THRESHOLD (200)
|
#define TEST_MEMORY_LEAK_THRESHOLD (212)
|
||||||
|
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
{
|
{
|
||||||
|
@ -31,13 +31,35 @@ typedef struct {
|
|||||||
void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx);
|
void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ESP_SLEEP_RTC_USE_RC_FAST_MODE, //!< The mode requested by RTC peripherals to keep RC_FAST clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (Will override the RC_FAST domain config by esp_sleep_pd_config)
|
||||||
|
ESP_SLEEP_DIG_USE_RC_FAST_MODE, //!< The mode requested by digital peripherals to keep RC_FAST clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the RC_FAST domain config by esp_sleep_pd_config)
|
||||||
|
ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, //!< Will enables the use of ADC and temperature sensor in monitor (ULP) mode.
|
||||||
|
ESP_SLEEP_ULTRA_LOW_MODE, //!< In ultra low mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT.
|
||||||
|
ESP_SLEEP_RTC_FAST_USE_XTAL_MODE, //!< The mode in which the crystal is used as the RTC_FAST clock source, need keep XTAL on in HP_SLEEP mode when ULP is working.
|
||||||
|
ESP_SLEEP_DIG_USE_XTAL_MODE, //!< The mode requested by digital peripherals to keep XTAL clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the XTAL domain config by esp_sleep_pd_config)
|
||||||
|
ESP_SLEEP_MODE_MAX,
|
||||||
|
} esp_sleep_sub_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode
|
* @brief Set sub-sleep power mode in sleep, mode enabled status is maintained by reference count.
|
||||||
|
* This submode configuration will kept after deep sleep wakeup.
|
||||||
*
|
*
|
||||||
* @note This state is kept in RTC memory and will keep its value after a deep sleep wakeup
|
* @param mode sub-sleep mode type
|
||||||
|
* @param activate Activate or deactivate the sleep sub mode
|
||||||
*
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
|
||||||
*/
|
*/
|
||||||
void esp_sleep_enable_adc_tsens_monitor(bool enable);
|
esp_err_t esp_sleep_sub_mode_config(esp_sleep_sub_mode_t mode, bool activate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump the sub-sleep power mode enable status
|
||||||
|
* @param stream The stream to dump to, if NULL then nothing will be dumped
|
||||||
|
* @return return the reference count array pointer
|
||||||
|
*/
|
||||||
|
int32_t* esp_sleep_sub_mode_dump_config(FILE *stream);
|
||||||
|
|
||||||
#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
||||||
/**
|
/**
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "esp_private/rtc_clk.h"
|
#include "esp_private/rtc_clk.h"
|
||||||
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
#include "soc/rtc_periph.h"
|
#include "soc/rtc_periph.h"
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
@ -273,15 +274,23 @@ void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32
|
|||||||
|
|
||||||
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||||
{
|
{
|
||||||
clk_ll_rtc_slow_set_src(clk_src);
|
#ifndef BOOTLOADER_BUILD
|
||||||
|
soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src();
|
||||||
|
// Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256.
|
||||||
|
if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true);
|
||||||
|
} else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clk_ll_rtc_slow_set_src(clk_src);
|
||||||
// The logic should be moved to BT driver
|
// The logic should be moved to BT driver
|
||||||
if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||||
clk_ll_xtal32k_digi_enable();
|
clk_ll_xtal32k_digi_enable();
|
||||||
} else {
|
} else {
|
||||||
clk_ll_xtal32k_digi_disable();
|
clk_ll_xtal32k_digi_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "esp32c2/rom/rtc.h"
|
#include "esp32c2/rom/rtc.h"
|
||||||
#include "esp32c2/rom/uart.h"
|
#include "esp32c2/rom/uart.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
#include "esp_private/rtc_clk.h"
|
#include "esp_private/rtc_clk.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
@ -66,6 +67,16 @@ bool rtc_clk_8md256_enabled(void)
|
|||||||
|
|
||||||
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||||
{
|
{
|
||||||
|
#ifndef BOOTLOADER_BUILD
|
||||||
|
soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src();
|
||||||
|
// Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256.
|
||||||
|
if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true);
|
||||||
|
} else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
clk_ll_rtc_slow_set_src(clk_src);
|
clk_ll_rtc_slow_set_src(clk_src);
|
||||||
|
|
||||||
/* Why we need to connect this clock to digital?
|
/* Why we need to connect this clock to digital?
|
||||||
@ -76,7 +87,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
|||||||
} else {
|
} else {
|
||||||
clk_ll_xtal32k_digi_disable();
|
clk_ll_xtal32k_digi_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "esp32c3/rom/rtc.h"
|
#include "esp32c3/rom/rtc.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
#include "esp_private/rtc_clk.h"
|
#include "esp_private/rtc_clk.h"
|
||||||
#include "esp_hw_log.h"
|
#include "esp_hw_log.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
@ -99,8 +100,17 @@ bool rtc_clk_8md256_enabled(void)
|
|||||||
|
|
||||||
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||||
{
|
{
|
||||||
clk_ll_rtc_slow_set_src(clk_src);
|
#ifndef BOOTLOADER_BUILD
|
||||||
|
soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src();
|
||||||
|
// Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256.
|
||||||
|
if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true);
|
||||||
|
} else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clk_ll_rtc_slow_set_src(clk_src);
|
||||||
/* Why we need to connect this clock to digital?
|
/* Why we need to connect this clock to digital?
|
||||||
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
||||||
*/
|
*/
|
||||||
@ -109,7 +119,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
|||||||
} else {
|
} else {
|
||||||
clk_ll_xtal32k_digi_disable();
|
clk_ll_xtal32k_digi_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "esp32s2/rom/rtc.h"
|
#include "esp32s2/rom/rtc.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "esp_private/rtc_clk.h"
|
#include "esp_private/rtc_clk.h"
|
||||||
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/rtc_io_reg.h"
|
#include "soc/rtc_io_reg.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
@ -174,8 +175,17 @@ void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32
|
|||||||
|
|
||||||
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||||
{
|
{
|
||||||
clk_ll_rtc_slow_set_src(clk_src);
|
#ifndef BOOTLOADER_BUILD
|
||||||
|
soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src();
|
||||||
|
// Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256.
|
||||||
|
if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true);
|
||||||
|
} else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clk_ll_rtc_slow_set_src(clk_src);
|
||||||
/* Why we need to connect this clock to digital?
|
/* Why we need to connect this clock to digital?
|
||||||
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
||||||
*/
|
*/
|
||||||
@ -184,7 +194,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
|||||||
} else {
|
} else {
|
||||||
clk_ll_xtal32k_digi_disable();
|
clk_ll_xtal32k_digi_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "esp32s3/rom/rtc.h"
|
#include "esp32s3/rom/rtc.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
#include "esp_private/rtc_clk.h"
|
#include "esp_private/rtc_clk.h"
|
||||||
#include "soc/rtc_io_reg.h"
|
#include "soc/rtc_io_reg.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
@ -114,8 +115,17 @@ bool rtc_clk_8md256_enabled(void)
|
|||||||
|
|
||||||
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||||
{
|
{
|
||||||
clk_ll_rtc_slow_set_src(clk_src);
|
#ifndef BOOTLOADER_BUILD
|
||||||
|
soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src();
|
||||||
|
// Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256.
|
||||||
|
if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true);
|
||||||
|
} else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clk_ll_rtc_slow_set_src(clk_src);
|
||||||
/* Why we need to connect this clock to digital?
|
/* Why we need to connect this clock to digital?
|
||||||
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
||||||
*/
|
*/
|
||||||
@ -124,7 +134,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
|||||||
} else {
|
} else {
|
||||||
clk_ll_xtal32k_digi_disable();
|
clk_ll_xtal32k_digi_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_rom_caps.h"
|
#include "esp_rom_caps.h"
|
||||||
@ -279,16 +280,9 @@ static bool s_light_sleep_wakeup = false;
|
|||||||
static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
static const char *TAG = "sleep";
|
static const char *TAG = "sleep";
|
||||||
static RTC_FAST_ATTR bool s_adc_tsen_enabled = false;
|
static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0 };
|
||||||
//in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT.
|
//in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT.
|
||||||
static bool s_ultra_low_enabled = false;
|
|
||||||
|
|
||||||
static bool s_periph_use_8m_flag = false;
|
|
||||||
|
|
||||||
void esp_sleep_periph_use_8m(bool use_or_not)
|
|
||||||
{
|
|
||||||
s_periph_use_8m_flag = use_or_not;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t get_power_down_flags(void);
|
static uint32_t get_power_down_flags(void);
|
||||||
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
||||||
@ -686,7 +680,7 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s
|
|||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C61
|
#if !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C61
|
||||||
// TODO: IDF-7370
|
// TODO: IDF-7370
|
||||||
if (!(deep_sleep && s_adc_tsen_enabled)){
|
if (!(deep_sleep && (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE] != 0))){
|
||||||
sar_periph_ctrl_power_disable();
|
sar_periph_ctrl_power_disable();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -778,20 +772,6 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
|||||||
|
|
||||||
int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment;
|
int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment;
|
||||||
|
|
||||||
#if SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
|
|
||||||
//Keep the RTC8M_CLK on if RTC clock is rc_fast_d256.
|
|
||||||
bool rtc_using_8md256 = (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256);
|
|
||||||
#else
|
|
||||||
bool rtc_using_8md256 = false;
|
|
||||||
#endif
|
|
||||||
//Keep the RTC8M_CLK on if the ledc low-speed channel is clocked by RTC8M_CLK in lightsleep mode
|
|
||||||
bool periph_using_8m = !deep_sleep && s_periph_use_8m_flag;
|
|
||||||
|
|
||||||
//Override user-configured power modes.
|
|
||||||
if (rtc_using_8md256 || periph_using_8m) {
|
|
||||||
pd_flags &= ~RTC_SLEEP_PD_INT_8M;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sleep UART prepare
|
// Sleep UART prepare
|
||||||
if (deep_sleep) {
|
if (deep_sleep) {
|
||||||
flush_uarts();
|
flush_uarts();
|
||||||
@ -903,17 +883,31 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
|||||||
reject_triggers |= sleep_modem_reject_triggers();
|
reject_triggers |= sleep_modem_reject_triggers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Override user-configured FOSC power modes.
|
||||||
|
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_RTC_USE_RC_FAST_MODE]) {
|
||||||
|
pd_flags &= ~RTC_SLEEP_PD_INT_8M;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override user-configured XTAL power modes.
|
||||||
|
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_XTAL_MODE] && !deep_sleep) {
|
||||||
|
pd_flags &= ~RTC_SLEEP_PD_XTAL;
|
||||||
|
}
|
||||||
|
|
||||||
//Append some flags in addition to power domains
|
//Append some flags in addition to power domains
|
||||||
uint32_t sleep_flags = pd_flags;
|
uint32_t sleep_flags = pd_flags;
|
||||||
if (s_adc_tsen_enabled) {
|
|
||||||
|
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_RC_FAST_MODE] && !deep_sleep) {
|
||||||
|
pd_flags &= ~RTC_SLEEP_PD_INT_8M;
|
||||||
|
sleep_flags |= RTC_SLEEP_DIG_USE_8M;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE]) {
|
||||||
sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR;
|
sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR;
|
||||||
}
|
}
|
||||||
if (!s_ultra_low_enabled) {
|
|
||||||
|
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_ULTRA_LOW_MODE] == 0) {
|
||||||
sleep_flags |= RTC_SLEEP_NO_ULTRA_LOW;
|
sleep_flags |= RTC_SLEEP_NO_ULTRA_LOW;
|
||||||
}
|
}
|
||||||
if (periph_using_8m) {
|
|
||||||
sleep_flags |= RTC_SLEEP_DIG_USE_8M;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_ESP_SLEEP_DEBUG
|
#if CONFIG_ESP_SLEEP_DEBUG
|
||||||
if (s_sleep_ctx != NULL) {
|
if (s_sleep_ctx != NULL) {
|
||||||
@ -2178,6 +2172,42 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_sleep_sub_mode_config(esp_sleep_sub_mode_t mode, bool activate)
|
||||||
|
{
|
||||||
|
if (mode >= ESP_SLEEP_MODE_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
portENTER_CRITICAL_SAFE(&s_config.lock);
|
||||||
|
if (activate) {
|
||||||
|
s_sleep_sub_mode_ref_cnt[mode]++;
|
||||||
|
} else {
|
||||||
|
s_sleep_sub_mode_ref_cnt[mode]--;
|
||||||
|
}
|
||||||
|
assert(s_sleep_sub_mode_ref_cnt[mode] >= 0);
|
||||||
|
portEXIT_CRITICAL_SAFE(&s_config.lock);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t* esp_sleep_sub_mode_dump_config(FILE *stream) {
|
||||||
|
if (stream) {
|
||||||
|
for (uint32_t mode = 0; mode < ESP_SLEEP_MODE_MAX; mode++) {
|
||||||
|
fprintf(stream, LOG_COLOR_I "%s : %s (cnt = %" PRId32 ")\n" LOG_RESET_COLOR,
|
||||||
|
(const char*[]){
|
||||||
|
[ESP_SLEEP_RTC_USE_RC_FAST_MODE] = "ESP_SLEEP_RTC_USE_RC_FAST_MODE",
|
||||||
|
[ESP_SLEEP_DIG_USE_RC_FAST_MODE] = "ESP_SLEEP_DIG_USE_RC_FAST_MODE",
|
||||||
|
[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE] = "ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE",
|
||||||
|
[ESP_SLEEP_ULTRA_LOW_MODE] = "ESP_SLEEP_ULTRA_LOW_MODE",
|
||||||
|
[ESP_SLEEP_RTC_FAST_USE_XTAL_MODE] = "ESP_SLEEP_RTC_FAST_USE_XTAL_MODE",
|
||||||
|
[ESP_SLEEP_DIG_USE_XTAL_MODE] = "ESP_SLEEP_DIG_USE_XTAL_MODE",
|
||||||
|
}[mode],
|
||||||
|
s_sleep_sub_mode_ref_cnt[mode] ? "ENABLED" : "DISABLED",
|
||||||
|
s_sleep_sub_mode_ref_cnt[mode]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s_sleep_sub_mode_ref_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The modules in the CPU and modem power domains still depend on the top power domain.
|
* The modules in the CPU and modem power domains still depend on the top power domain.
|
||||||
* To be safe, the CPU and Modem power domains must also be powered off and saved when
|
* To be safe, the CPU and Modem power domains must also be powered off and saved when
|
||||||
@ -2382,12 +2412,17 @@ esp_deep_sleep_disable_rom_logging(void)
|
|||||||
rtc_suppress_rom_log();
|
rtc_suppress_rom_log();
|
||||||
}
|
}
|
||||||
|
|
||||||
void esp_sleep_enable_adc_tsens_monitor(bool enable)
|
__attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void esp_sleep_periph_use_8m(bool use_or_not)
|
||||||
{
|
{
|
||||||
s_adc_tsen_enabled = enable;
|
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, use_or_not);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtc_sleep_enable_ultra_low(bool enable)
|
__attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void esp_sleep_enable_adc_tsens_monitor(bool enable)
|
||||||
{
|
{
|
||||||
s_ultra_low_enabled = enable;
|
esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void rtc_sleep_enable_ultra_low(bool enable)
|
||||||
|
{
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, enable);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -21,6 +21,11 @@
|
|||||||
|
|
||||||
static const char TAG[] = "rtc_power";
|
static const char TAG[] = "rtc_power";
|
||||||
|
|
||||||
|
static void check_deepsleep_reset(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
|
||||||
|
}
|
||||||
|
|
||||||
static void test_deepsleep(void)
|
static void test_deepsleep(void)
|
||||||
{
|
{
|
||||||
esp_sleep_enable_timer_wakeup(2000000);
|
esp_sleep_enable_timer_wakeup(2000000);
|
||||||
@ -28,33 +33,48 @@ static void test_deepsleep(void)
|
|||||||
esp_deep_sleep_start();
|
esp_deep_sleep_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deepsleep (with 8MD256 or ADC/TSEN in monitor)
|
|
||||||
TEST_CASE("Power Test: DSLP_8MD256", "[pm]")
|
|
||||||
{
|
|
||||||
esp_sleep_enable_adc_tsens_monitor(true);
|
|
||||||
|
|
||||||
test_deepsleep();
|
static void test_set_adc_tsen_monitor_mode(void) {
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_unset_adc_tesen_monitor_mode(void) {
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, false);
|
||||||
|
TEST_ASSERT_EQUAL(0, esp_sleep_sub_mode_dump_config(NULL)[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deepsleep (with 8MD256 or ADC/TSEN in monitor)
|
||||||
|
TEST_CASE_MULTIPLE_STAGES( "Power Test: DSLP_8MD256", "[pm]",
|
||||||
|
test_set_adc_tsen_monitor_mode,
|
||||||
|
test_deepsleep,
|
||||||
|
check_deepsleep_reset,
|
||||||
|
test_unset_adc_tesen_monitor_mode
|
||||||
|
)
|
||||||
|
|
||||||
#if !CONFIG_RTC_CLK_SRC_INT_8MD256
|
#if !CONFIG_RTC_CLK_SRC_INT_8MD256
|
||||||
// Deepsleep (default)
|
// Deepsleep (default)
|
||||||
TEST_CASE("Power Test: DSLP_DEFAULT", "[pm]")
|
TEST_CASE_MULTIPLE_STAGES( "Power Test: DSLP_DEFAULT", "[pm]",
|
||||||
{
|
test_deepsleep,
|
||||||
esp_sleep_enable_adc_tsens_monitor(false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case.
|
check_deepsleep_reset
|
||||||
|
)
|
||||||
|
|
||||||
test_deepsleep();
|
static void test_set_ultra_low_mode(void) {
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_unset_ultra_low_mode(void) {
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, false);
|
||||||
|
TEST_ASSERT_EQUAL(0, esp_sleep_sub_mode_dump_config(NULL)[ESP_SLEEP_ULTRA_LOW_MODE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deepsleep (ultra-low power)
|
// Deepsleep (ultra-low power)
|
||||||
TEST_CASE("Power Test: DSLP_ULTRA_LOW", "[pm]")
|
TEST_CASE_MULTIPLE_STAGES( "Power Test: DSLP_ULTRA_LOW", "[pm]",
|
||||||
{
|
test_set_ultra_low_mode,
|
||||||
esp_sleep_enable_adc_tsens_monitor(false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case.
|
test_deepsleep,
|
||||||
|
check_deepsleep_reset,
|
||||||
|
test_unset_ultra_low_mode
|
||||||
|
)
|
||||||
|
|
||||||
extern void rtc_sleep_enable_ultra_low(bool);
|
|
||||||
rtc_sleep_enable_ultra_low(true);
|
|
||||||
|
|
||||||
test_deepsleep();
|
|
||||||
}
|
|
||||||
#endif //!CONFIG_RTC_CLK_SRC_INT_8MD256
|
#endif //!CONFIG_RTC_CLK_SRC_INT_8MD256
|
||||||
|
|
||||||
static void test_lightsleep(void)
|
static void test_lightsleep(void)
|
||||||
@ -125,17 +145,14 @@ TEST_CASE("Power Test: LSLP_8MD256", "[pm]")
|
|||||||
// Lightsleep (with ADC/TSEN in monitor)
|
// Lightsleep (with ADC/TSEN in monitor)
|
||||||
TEST_CASE("Power Test: LSLP_ADC_TSENS", "[pm]")
|
TEST_CASE("Power Test: LSLP_ADC_TSENS", "[pm]")
|
||||||
{
|
{
|
||||||
extern void esp_sleep_enable_adc_tsens_monitor(bool);
|
esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, true);
|
||||||
esp_sleep_enable_adc_tsens_monitor(true);
|
|
||||||
|
|
||||||
test_lightsleep();
|
test_lightsleep();
|
||||||
|
esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lightsleep (default)
|
// Lightsleep (default)
|
||||||
TEST_CASE("Power Test: LSLP_DEFAULT", "[pm]")
|
TEST_CASE("Power Test: LSLP_DEFAULT", "[pm]")
|
||||||
{
|
{
|
||||||
esp_sleep_enable_adc_tsens_monitor(false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case.
|
|
||||||
|
|
||||||
test_lightsleep();
|
test_lightsleep();
|
||||||
}
|
}
|
||||||
#endif //!CONFIG_RTC_CLK_SRC_INT_8MD256
|
#endif //!CONFIG_RTC_CLK_SRC_INT_8MD256
|
||||||
|
Reference in New Issue
Block a user