feat: support dump last time sleep context

This commit is contained in:
wuzhenghui 2023-10-08 16:48:00 +08:00 committed by Xu Si Yu
parent 7011329b35
commit 9a246bcbf1
3 changed files with 80 additions and 15 deletions

View File

@ -172,6 +172,12 @@ menu "Hardware Settings"
For chips after esp32, the delay will be executed only in light sleep flow, the delay For chips after esp32, the delay will be executed only in light sleep flow, the delay
controlled by the EFUSE_FLASH_TPUW in ROM will be executed in deepsleep wake up flow.) controlled by the EFUSE_FLASH_TPUW in ROM will be executed in deepsleep wake up flow.)
config ESP_SLEEP_DEBUG
bool "esp sleep debug"
default n
help
Enable esp sleep debug.
config ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS config ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS
bool "Allow to enable internal pull-up/downs for the Deep-Sleep wakeup IOs" bool "Allow to enable internal pull-up/downs for the Deep-Sleep wakeup IOs"
default y default y

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -13,6 +13,23 @@ extern "C" {
#endif #endif
#if CONFIG_ESP_SLEEP_DEBUG
typedef struct {
uint32_t lightsleep_cnt;
uint64_t sleep_in_rtc_time_stamp;
uint64_t sleep_out_rtc_time_stamp;
uint32_t wakeup_triggers;
uint32_t sleep_flags;
esp_err_t sleep_request_result;
} esp_sleep_context_t;
/**
* @brief Set the context pointer of last sleep request
* @param sleep_ctx Structure where the context of the sleep information needs to be recorded in
*/
void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx);
#endif
/** /**
* @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode * @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode
* *

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -83,7 +83,6 @@
#include "esp32c2/rom/rtc.h" #include "esp32c2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C6 #elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/rtc.h" #include "esp32c6/rom/rtc.h"
#include "hal/lp_timer_hal.h"
#include "hal/gpio_ll.h" #include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h" #include "esp32h2/rom/rtc.h"
@ -196,8 +195,10 @@ typedef struct {
uint32_t ext0_trigger_level : 1; uint32_t ext0_trigger_level : 1;
uint32_t ext0_rtc_gpio_num : 5; uint32_t ext0_rtc_gpio_num : 5;
#endif #endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
uint32_t gpio_wakeup_mask : 8; // 8 is the maximum RTCIO number in all chips that support GPIO wakeup 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 gpio_trigger_mode : 8;
#endif
uint32_t sleep_time_adjustment; uint32_t sleep_time_adjustment;
uint32_t ccount_ticks_record; uint32_t ccount_ticks_record;
uint32_t sleep_time_overhead_out; uint32_t sleep_time_overhead_out;
@ -207,6 +208,17 @@ typedef struct {
} sleep_config_t; } sleep_config_t;
#if CONFIG_ESP_SLEEP_DEBUG
static esp_sleep_context_t *s_sleep_ctx = NULL;
void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx)
{
s_sleep_ctx = sleep_ctx;
}
#endif
static uint32_t s_lightsleep_cnt = 0;
_Static_assert(22 >= SOC_RTCIO_PIN_COUNT, "Chip has more RTCIOs than 22, should increase ext1_rtc_gpio_mask field size"); _Static_assert(22 >= SOC_RTCIO_PIN_COUNT, "Chip has more RTCIOs than 22, should increase ext1_rtc_gpio_mask field size");
static sleep_config_t s_config = { static sleep_config_t s_config = {
@ -715,11 +727,18 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
if (periph_using_8m) { if (periph_using_8m) {
sleep_flags |= RTC_SLEEP_DIG_USE_8M; sleep_flags |= RTC_SLEEP_DIG_USE_8M;
} }
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->sleep_flags = sleep_flags;
}
#endif
// Enter sleep // Enter sleep
esp_err_t result; esp_err_t result;
#if SOC_PMU_SUPPORTED #if SOC_PMU_SUPPORTED
pmu_sleep_config_t config; pmu_sleep_config_t config;
pmu_sleep_init(pmu_sleep_config_default(&config, pd_flags, s_config.sleep_time_adjustment, pmu_sleep_init(pmu_sleep_config_default(&config, sleep_flags, s_config.sleep_time_adjustment,
s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period,
deep_sleep), deep_sleep); deep_sleep), deep_sleep);
#else #else
@ -749,6 +768,11 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
if (should_skip_sleep) { if (should_skip_sleep) {
result = ESP_ERR_SLEEP_REJECT; result = ESP_ERR_SLEEP_REJECT;
} else { } else {
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers;
}
#endif
if (deep_sleep) { if (deep_sleep) {
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP #if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
esp_sleep_isolate_digital_gpio(); esp_sleep_isolate_digital_gpio();
@ -792,8 +816,9 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0); esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0);
if (pd_flags & PMU_SLEEP_PD_CPU) { if (pd_flags & PMU_SLEEP_PD_CPU) {
result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
} else { } else
#endif #endif
{
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
} }
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_EXIT_SLEEP, (void *)0); esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_EXIT_SLEEP, (void *)0);
@ -1063,15 +1088,18 @@ esp_err_t esp_light_sleep_start(void)
*/ */
esp_clk_private_lock(); esp_clk_private_lock();
#if SOC_LP_TIMER_SUPPORTED
s_config.rtc_ticks_at_sleep_start = lp_timer_hal_get_cycle_count();
#else
s_config.rtc_ticks_at_sleep_start = rtc_time_get(); s_config.rtc_ticks_at_sleep_start = rtc_time_get();
#endif
uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count(); uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count();
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_TIME_START, (void *)0); esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_TIME_START, (void *)0);
uint64_t high_res_time_at_start = esp_timer_get_time(); uint64_t high_res_time_at_start = esp_timer_get_time();
uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->sleep_in_rtc_time_stamp = s_config.rtc_ticks_at_sleep_start;
}
#endif
esp_ipc_isr_stall_other_cpu(); esp_ipc_isr_stall_other_cpu();
// Decide which power domains can be powered down // Decide which power domains can be powered down
@ -1164,6 +1192,13 @@ esp_err_t esp_light_sleep_start(void)
// reset light sleep wakeup flag before a new light sleep // reset light sleep wakeup flag before a new light sleep
s_light_sleep_wakeup = false; s_light_sleep_wakeup = false;
s_lightsleep_cnt++;
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->lightsleep_cnt = s_lightsleep_cnt;
}
#endif
// if rtc timer wakeup source is enabled, need to compare final sleep duration and min sleep duration to avoid late wakeup // if rtc timer wakeup source is enabled, need to compare final sleep duration and min sleep duration to avoid late wakeup
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && (final_sleep_duration_us <= min_sleep_duration_us)) { if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && (final_sleep_duration_us <= min_sleep_duration_us)) {
err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION; err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION;
@ -1176,13 +1211,15 @@ esp_err_t esp_light_sleep_start(void)
s_light_sleep_wakeup = (err == ESP_OK); s_light_sleep_wakeup = (err == ESP_OK);
// System timer has been stopped for the duration of the sleep, correct for that. // System timer has been stopped for the duration of the sleep, correct for that.
#if SOC_LP_TIMER_SUPPORTED
uint64_t rtc_ticks_at_end = lp_timer_hal_get_cycle_count();
#else
uint64_t rtc_ticks_at_end = rtc_time_get(); uint64_t rtc_ticks_at_end = rtc_time_get();
#endif
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period); uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period);
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->sleep_out_rtc_time_stamp = rtc_ticks_at_end;
}
#endif
/** /**
* If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero. * If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero.
* In this case, just ignore the time compensation and keep esp_timer monotonic. * In this case, just ignore the time compensation and keep esp_timer monotonic.
@ -1211,6 +1248,12 @@ esp_err_t esp_light_sleep_start(void)
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_EXIT_SLEEP, (void *)0); esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_EXIT_SLEEP, (void *)0);
s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->sleep_request_result = err;
}
#endif
return err; return err;
} }
@ -1307,7 +1350,7 @@ static esp_err_t timer_wakeup_prepare(int64_t sleep_duration)
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// Last timer wake-up validity check // Last timer wake-up validity check
if ((sleep_duration == 0) || \ if ((sleep_duration == 0) || \
(target_wakeup_tick < lp_timer_hal_get_cycle_count() + SLEEP_TIMER_ALARM_TO_SLEEP_TICKS)) { (target_wakeup_tick < rtc_time_get() + SLEEP_TIMER_ALARM_TO_SLEEP_TICKS)) {
// Treat too short sleep duration setting as timer reject // Treat too short sleep duration setting as timer reject
return ESP_ERR_SLEEP_REJECT; return ESP_ERR_SLEEP_REJECT;
} }
@ -1850,7 +1893,6 @@ static uint32_t get_power_down_flags(void)
} }
#endif #endif
#ifdef CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32
s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option = ESP_PD_OPTION_OFF; s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option = ESP_PD_OPTION_OFF;
#endif #endif