mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
bugfix: treat too short sleep duration as sleep reject by software
This commit is contained in:
parent
756b5f628d
commit
5c74093300
@ -234,6 +234,12 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp);
|
|||||||
*/
|
*/
|
||||||
uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
|
uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finish sleep process settings and get sleep reject status
|
||||||
|
* @return return sleep reject status
|
||||||
|
*/
|
||||||
|
bool pmu_sleep_finish(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize PMU related power/clock/digital parameters and functions
|
* @brief Initialize PMU related power/clock/digital parameters and functions
|
||||||
*/
|
*/
|
||||||
|
@ -278,10 +278,16 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
|
|||||||
/* Start entry into sleep mode */
|
/* Start entry into sleep mode */
|
||||||
pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev);
|
pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev);
|
||||||
|
|
||||||
|
/* In pd_cpu lightsleep and deepsleep mode, we never get here */
|
||||||
while (!pmu_ll_hp_is_sleep_wakeup(PMU_instance()->hal->dev) &&
|
while (!pmu_ll_hp_is_sleep_wakeup(PMU_instance()->hal->dev) &&
|
||||||
!pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
|
!pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return pmu_sleep_finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pmu_sleep_finish(void)
|
||||||
|
{
|
||||||
|
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
#include "esp_private/sleep_cpu.h"
|
#include "esp_private/sleep_cpu.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if !SOC_PMU_SUPPORTED
|
#if SOC_PMU_SUPPORTED
|
||||||
|
#include "esp_private/esp_pmu.h"
|
||||||
|
#else
|
||||||
#include "hal/rtc_hal.h"
|
#include "hal/rtc_hal.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -683,7 +685,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ESP_OK;
|
return pmu_sleep_finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||||
|
@ -124,6 +124,9 @@
|
|||||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Actually costs 80us, using the fastest slow clock 150K calculation takes about 16 ticks
|
||||||
|
#define SLEEP_TIMER_ALARM_TO_SLEEP_TICKS (16)
|
||||||
|
|
||||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
|
#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
|
||||||
#ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL
|
#ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL
|
||||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
|
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
|
||||||
@ -224,7 +227,7 @@ static void ext0_wakeup_prepare(void);
|
|||||||
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
||||||
static void ext1_wakeup_prepare(void);
|
static void ext1_wakeup_prepare(void);
|
||||||
#endif
|
#endif
|
||||||
static void timer_wakeup_prepare(void);
|
static esp_err_t timer_wakeup_prepare(void);
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||||
static void touch_wakeup_prepare(void);
|
static void touch_wakeup_prepare(void);
|
||||||
#endif
|
#endif
|
||||||
@ -476,6 +479,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
|
|||||||
// For light sleep, suspend UART output — it will resume after wakeup.
|
// For light sleep, suspend UART output — it will resume after wakeup.
|
||||||
// For deep sleep, wait for the contents of UART FIFO to be sent.
|
// For deep sleep, wait for the contents of UART FIFO to be sent.
|
||||||
bool deep_sleep = (mode == ESP_SLEEP_MODE_DEEP_SLEEP);
|
bool deep_sleep = (mode == ESP_SLEEP_MODE_DEEP_SLEEP);
|
||||||
|
bool should_skip_sleep = false;
|
||||||
|
|
||||||
if (deep_sleep) {
|
if (deep_sleep) {
|
||||||
flush_uarts();
|
flush_uarts();
|
||||||
@ -585,6 +589,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enter sleep
|
// Enter sleep
|
||||||
|
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, pd_flags, s_config.sleep_time_adjustment,
|
||||||
@ -603,7 +608,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
|
|||||||
|
|
||||||
// Configure timer wakeup
|
// Configure timer wakeup
|
||||||
if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) {
|
if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) {
|
||||||
timer_wakeup_prepare();
|
if (timer_wakeup_prepare() != ESP_OK) {
|
||||||
|
result = ESP_ERR_SLEEP_REJECT;
|
||||||
|
should_skip_sleep = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||||
@ -612,7 +620,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t result;
|
if (!should_skip_sleep) {
|
||||||
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();
|
||||||
@ -672,6 +680,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
|
|||||||
rtc_sleep_systimer_enable(true);
|
rtc_sleep_systimer_enable(true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Restore CPU frequency
|
// Restore CPU frequency
|
||||||
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
|
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
|
||||||
@ -1122,7 +1131,7 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timer_wakeup_prepare(void)
|
static esp_err_t timer_wakeup_prepare(void)
|
||||||
{
|
{
|
||||||
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 (sleep_duration < 0) {
|
if (sleep_duration < 0) {
|
||||||
@ -1130,12 +1139,23 @@ static void timer_wakeup_prepare(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t ticks = rtc_time_us_to_slowclk(sleep_duration, s_config.rtc_clk_cal_period);
|
int64_t ticks = rtc_time_us_to_slowclk(sleep_duration, s_config.rtc_clk_cal_period);
|
||||||
|
int64_t target_wakeup_tick = s_config.rtc_ticks_at_sleep_start + ticks;
|
||||||
|
|
||||||
#if SOC_LP_TIMER_SUPPORTED
|
#if SOC_LP_TIMER_SUPPORTED
|
||||||
lp_timer_hal_set_alarm_target(0, s_config.rtc_ticks_at_sleep_start + ticks);
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
#else
|
// When pd_top is supported, light_sleep will flush uart, and the sleep overhead time will become an unpredictable value,
|
||||||
rtc_hal_set_wakeup_timer(s_config.rtc_ticks_at_sleep_start + ticks);
|
// here is the 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)) {
|
||||||
|
// Treat too short sleep duration setting as timer reject
|
||||||
|
return ESP_ERR_SLEEP_REJECT;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
lp_timer_hal_set_alarm_target(0, target_wakeup_tick);
|
||||||
|
#else
|
||||||
|
rtc_hal_set_wakeup_timer(target_wakeup_tick);
|
||||||
|
#endif
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
@ -156,6 +156,7 @@ static const char* s_mode_names[] = {
|
|||||||
"APB_MAX",
|
"APB_MAX",
|
||||||
"CPU_MAX"
|
"CPU_MAX"
|
||||||
};
|
};
|
||||||
|
static uint32_t s_light_sleep_counts, s_light_sleep_reject_counts;
|
||||||
#endif // WITH_PROFILING
|
#endif // WITH_PROFILING
|
||||||
|
|
||||||
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
|
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
|
||||||
@ -612,7 +613,13 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
|
|||||||
/* Enter sleep */
|
/* Enter sleep */
|
||||||
ESP_PM_TRACE_ENTER(SLEEP, core_id);
|
ESP_PM_TRACE_ENTER(SLEEP, core_id);
|
||||||
int64_t sleep_start = esp_timer_get_time();
|
int64_t sleep_start = esp_timer_get_time();
|
||||||
esp_light_sleep_start();
|
if (esp_light_sleep_start() != ESP_OK){
|
||||||
|
#ifdef WITH_PROFILING
|
||||||
|
s_light_sleep_reject_counts++;
|
||||||
|
} else {
|
||||||
|
s_light_sleep_counts++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
int64_t slept_us = esp_timer_get_time() - sleep_start;
|
int64_t slept_us = esp_timer_get_time() - sleep_start;
|
||||||
ESP_PM_TRACE_EXIT(SLEEP, core_id);
|
ESP_PM_TRACE_EXIT(SLEEP, core_id);
|
||||||
|
|
||||||
@ -652,6 +659,9 @@ void esp_pm_impl_dump_stats(FILE* out)
|
|||||||
pm_time_t last_mode_change_time = s_last_mode_change_time;
|
pm_time_t last_mode_change_time = s_last_mode_change_time;
|
||||||
pm_mode_t cur_mode = s_mode;
|
pm_mode_t cur_mode = s_mode;
|
||||||
pm_time_t now = pm_get_time();
|
pm_time_t now = pm_get_time();
|
||||||
|
bool light_sleep_en = s_light_sleep_en;
|
||||||
|
uint32_t light_sleep_counts = s_light_sleep_counts;
|
||||||
|
uint32_t light_sleep_reject_counts = s_light_sleep_reject_counts;
|
||||||
portEXIT_CRITICAL_ISR(&s_switch_lock);
|
portEXIT_CRITICAL_ISR(&s_switch_lock);
|
||||||
|
|
||||||
time_in_mode[cur_mode] += now - last_mode_change_time;
|
time_in_mode[cur_mode] += now - last_mode_change_time;
|
||||||
@ -659,7 +669,7 @@ void esp_pm_impl_dump_stats(FILE* out)
|
|||||||
fprintf(out, "\nMode stats:\n");
|
fprintf(out, "\nMode stats:\n");
|
||||||
fprintf(out, "%-8s %-10s %-10s %-10s\n", "Mode", "CPU_freq", "Time(us)", "Time(%)");
|
fprintf(out, "%-8s %-10s %-10s %-10s\n", "Mode", "CPU_freq", "Time(us)", "Time(%)");
|
||||||
for (int i = 0; i < PM_MODE_COUNT; ++i) {
|
for (int i = 0; i < PM_MODE_COUNT; ++i) {
|
||||||
if (i == PM_MODE_LIGHT_SLEEP && !s_light_sleep_en) {
|
if (i == PM_MODE_LIGHT_SLEEP && !light_sleep_en) {
|
||||||
/* don't display light sleep mode if it's not enabled */
|
/* don't display light sleep mode if it's not enabled */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -670,6 +680,10 @@ void esp_pm_impl_dump_stats(FILE* out)
|
|||||||
time_in_mode[i],
|
time_in_mode[i],
|
||||||
(int) (time_in_mode[i] * 100 / now));
|
(int) (time_in_mode[i] * 100 / now));
|
||||||
}
|
}
|
||||||
|
if (light_sleep_en){
|
||||||
|
fprintf(out, "\nSleep stats:\n");
|
||||||
|
fprintf(out, "light_sleep_counts:%ld light_sleep_reject_counts:%ld\n", light_sleep_counts, light_sleep_reject_counts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // WITH_PROFILING
|
#endif // WITH_PROFILING
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user