forked from espressif/esp-idf
Merge branch 'feature/support_dump_sleep_context' into 'master'
feat(esp_hw_support): Supports recording key sleep parameters into user-specified structures for debug Closes FCS-1300 See merge request espressif/esp-idf!26359
This commit is contained in:
@@ -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
|
||||||
*
|
*
|
||||||
|
@@ -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"
|
||||||
@@ -198,8 +197,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;
|
||||||
@@ -209,6 +210,15 @@ 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 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");
|
||||||
@@ -578,14 +588,6 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
|||||||
bool deep_sleep = (mode == ESP_SLEEP_MODE_DEEP_SLEEP);
|
bool deep_sleep = (mode == ESP_SLEEP_MODE_DEEP_SLEEP);
|
||||||
bool should_skip_sleep = false;
|
bool should_skip_sleep = false;
|
||||||
|
|
||||||
#if CONFIG_ESP_SLEEP_DEBUG
|
|
||||||
// The following three logs are used to confirm whether the digital domain and modem are powered off.
|
|
||||||
// Some CI tests depend on these three logs and it is best not to modify them.
|
|
||||||
ESP_EARLY_LOGD(TAG, "pd_lags %lu", pd_flags);
|
|
||||||
ESP_EARLY_LOGD(TAG, "PMU_SLEEP_PD_TOP: %s", (pd_flags & PMU_SLEEP_PD_TOP) ? "True":"False");
|
|
||||||
ESP_EARLY_LOGD(TAG, "PMU_SLEEP_PD_MODEM: %s", (pd_flags & PMU_SLEEP_PD_MODEM) ? "True":"False");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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
|
#if SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
|
||||||
@@ -688,11 +690,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
|
||||||
@@ -722,6 +731,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();
|
||||||
@@ -766,8 +780,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);
|
||||||
@@ -826,7 +841,6 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
|||||||
|
|
||||||
// re-enable UART output
|
// re-enable UART output
|
||||||
resume_uarts();
|
resume_uarts();
|
||||||
s_lightsleep_cnt++;
|
|
||||||
return result ? ESP_ERR_SLEEP_REJECT : ESP_OK;
|
return result ? ESP_ERR_SLEEP_REJECT : ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1012,15 +1026,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();
|
||||||
|
|
||||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
|
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
|
||||||
@@ -1151,6 +1168,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;
|
||||||
@@ -1163,13 +1187,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.
|
||||||
@@ -1204,6 +1230,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1300,7 +1332,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;
|
||||||
}
|
}
|
||||||
@@ -1843,23 +1875,10 @@ 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
|
||||||
|
|
||||||
const __attribute__((unused)) char *option_str[] = {DRAM_STR("OFF"), DRAM_STR("ON"), DRAM_STR("AUTO(OFF)") /* Auto works as OFF */};
|
|
||||||
/* This function is called from a critical section, log with ESP_EARLY_LOGD. */
|
|
||||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
|
||||||
ESP_EARLY_LOGD(TAG, "RTC_PERIPH: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option]);
|
|
||||||
#endif
|
|
||||||
#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD
|
|
||||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_MEM: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option]);
|
|
||||||
#endif
|
|
||||||
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
|
||||||
ESP_EARLY_LOGD(TAG, "RTC_FAST_MEM: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Prepare flags based on the selected options
|
// Prepare flags based on the selected options
|
||||||
uint32_t pd_flags = 0;
|
uint32_t pd_flags = 0;
|
||||||
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
||||||
|
Reference in New Issue
Block a user