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
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
bool "Allow to enable internal pull-up/downs for the Deep-Sleep wakeup IOs"
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
*/
@ -13,6 +13,23 @@ extern "C" {
#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
*

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
*/
@ -83,7 +83,6 @@
#include "esp32c2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/rtc.h"
#include "hal/lp_timer_hal.h"
#include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h"
@ -196,8 +195,10 @@ typedef struct {
uint32_t ext0_trigger_level : 1;
uint32_t ext0_rtc_gpio_num : 5;
#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_trigger_mode : 8;
#endif
uint32_t sleep_time_adjustment;
uint32_t ccount_ticks_record;
uint32_t sleep_time_overhead_out;
@ -207,6 +208,17 @@ typedef struct {
} 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 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) {
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
esp_err_t result;
#if SOC_PMU_SUPPORTED
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,
deep_sleep), deep_sleep);
#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) {
result = ESP_ERR_SLEEP_REJECT;
} 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 !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
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);
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);
} else {
} else
#endif
{
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);
@ -1063,15 +1088,18 @@ esp_err_t esp_light_sleep_start(void)
*/
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();
#endif
uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count();
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_TIME_START, (void *)0);
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);
#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();
// 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
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 ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && (final_sleep_duration_us <= min_sleep_duration_us)) {
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);
// 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();
#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);
#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.
* 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);
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;
}
@ -1307,7 +1350,7 @@ static esp_err_t timer_wakeup_prepare(int64_t sleep_duration)
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// Last timer wake-up validity check
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
return ESP_ERR_SLEEP_REJECT;
}
@ -1850,7 +1893,6 @@ static uint32_t get_power_down_flags(void)
}
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option = ESP_PD_OPTION_OFF;
#endif