Merge branch 'bugfix/fix_hang_during_sleep_process' into 'master'

bugfix: fix hang on pd_top sleep process

Closes AEG-582

See merge request espressif/esp-idf!23634
This commit is contained in:
Jiang Jiang Jian 2023-05-31 17:23:08 +08:00
commit d89919999e
9 changed files with 265 additions and 69 deletions

View File

@ -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);
/**
* @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
*/

View File

@ -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 */
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) &&
!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);
}

View File

@ -22,7 +22,9 @@
#include "esp_private/sleep_cpu.h"
#include "sdkconfig.h"
#if !SOC_PMU_SUPPORTED
#if SOC_PMU_SUPPORTED
#include "esp_private/esp_pmu.h"
#else
#include "hal/rtc_hal.h"
#endif
@ -449,10 +451,7 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi
frame->tdata1 = RV_READ_CSR(tdata1);
frame->tdata2 = RV_READ_CSR(tdata2);
frame->tcontrol = RV_READ_CSR(tcontrol);
frame->pmpcfg0 = RV_READ_CSR(pmpcfg0);
frame->pmpcfg1 = RV_READ_CSR(pmpcfg1);
frame->pmpcfg2 = RV_READ_CSR(pmpcfg2);
frame->pmpcfg3 = RV_READ_CSR(pmpcfg3);
frame->pmpaddr0 = RV_READ_CSR(pmpaddr0);
frame->pmpaddr1 = RV_READ_CSR(pmpaddr1);
frame->pmpaddr2 = RV_READ_CSR(pmpaddr2);
@ -469,6 +468,45 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi
frame->pmpaddr13 = RV_READ_CSR(pmpaddr13);
frame->pmpaddr14 = RV_READ_CSR(pmpaddr14);
frame->pmpaddr15 = RV_READ_CSR(pmpaddr15);
frame->pmpcfg0 = RV_READ_CSR(pmpcfg0);
frame->pmpcfg1 = RV_READ_CSR(pmpcfg1);
frame->pmpcfg2 = RV_READ_CSR(pmpcfg2);
frame->pmpcfg3 = RV_READ_CSR(pmpcfg3);
#if SOC_CPU_HAS_PMA
frame->pmaaddr0 = RV_READ_CSR(CSR_PMAADDR(0));
frame->pmaaddr1 = RV_READ_CSR(CSR_PMAADDR(1));
frame->pmaaddr2 = RV_READ_CSR(CSR_PMAADDR(2));
frame->pmaaddr3 = RV_READ_CSR(CSR_PMAADDR(3));
frame->pmaaddr4 = RV_READ_CSR(CSR_PMAADDR(4));
frame->pmaaddr5 = RV_READ_CSR(CSR_PMAADDR(5));
frame->pmaaddr6 = RV_READ_CSR(CSR_PMAADDR(6));
frame->pmaaddr7 = RV_READ_CSR(CSR_PMAADDR(7));
frame->pmaaddr8 = RV_READ_CSR(CSR_PMAADDR(8));
frame->pmaaddr9 = RV_READ_CSR(CSR_PMAADDR(9));
frame->pmaaddr10 = RV_READ_CSR(CSR_PMAADDR(10));
frame->pmaaddr11 = RV_READ_CSR(CSR_PMAADDR(11));
frame->pmaaddr12 = RV_READ_CSR(CSR_PMAADDR(12));
frame->pmaaddr13 = RV_READ_CSR(CSR_PMAADDR(13));
frame->pmaaddr14 = RV_READ_CSR(CSR_PMAADDR(14));
frame->pmaaddr15 = RV_READ_CSR(CSR_PMAADDR(15));
frame->pmacfg0 = RV_READ_CSR(CSR_PMACFG(0));
frame->pmacfg1 = RV_READ_CSR(CSR_PMACFG(1));
frame->pmacfg2 = RV_READ_CSR(CSR_PMACFG(2));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(3));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(4));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(5));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(6));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(7));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(8));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(9));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(10));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(11));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(12));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(13));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(14));
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(15));
#endif // SOC_CPU_HAS_PMA
frame->utvec = RV_READ_CSR(utvec);
frame->ustatus = RV_READ_CSR(ustatus);
@ -498,10 +536,6 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(RvCoreNonCriticalSleepFra
RV_WRITE_CSR(tdata1, frame->tdata1);
RV_WRITE_CSR(tdata2, frame->tdata2);
RV_WRITE_CSR(tcontrol, frame->tcontrol);
RV_WRITE_CSR(pmpcfg0, frame->pmpcfg0);
RV_WRITE_CSR(pmpcfg1, frame->pmpcfg1);
RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2);
RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3);
RV_WRITE_CSR(pmpaddr0, frame->pmpaddr0);
RV_WRITE_CSR(pmpaddr1, frame->pmpaddr1);
RV_WRITE_CSR(pmpaddr2, frame->pmpaddr2);
@ -518,6 +552,45 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(RvCoreNonCriticalSleepFra
RV_WRITE_CSR(pmpaddr13,frame->pmpaddr13);
RV_WRITE_CSR(pmpaddr14,frame->pmpaddr14);
RV_WRITE_CSR(pmpaddr15,frame->pmpaddr15);
RV_WRITE_CSR(pmpcfg0, frame->pmpcfg0);
RV_WRITE_CSR(pmpcfg1, frame->pmpcfg1);
RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2);
RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3);
#if SOC_CPU_HAS_PMA
RV_WRITE_CSR(CSR_PMAADDR(0), frame->pmaaddr0);
RV_WRITE_CSR(CSR_PMAADDR(1), frame->pmaaddr1);
RV_WRITE_CSR(CSR_PMAADDR(2), frame->pmaaddr2);
RV_WRITE_CSR(CSR_PMAADDR(3), frame->pmaaddr3);
RV_WRITE_CSR(CSR_PMAADDR(4), frame->pmaaddr4);
RV_WRITE_CSR(CSR_PMAADDR(5), frame->pmaaddr5);
RV_WRITE_CSR(CSR_PMAADDR(6), frame->pmaaddr6);
RV_WRITE_CSR(CSR_PMAADDR(7), frame->pmaaddr7);
RV_WRITE_CSR(CSR_PMAADDR(8), frame->pmaaddr8);
RV_WRITE_CSR(CSR_PMAADDR(9), frame->pmaaddr9);
RV_WRITE_CSR(CSR_PMAADDR(10),frame->pmaaddr10);
RV_WRITE_CSR(CSR_PMAADDR(11),frame->pmaaddr11);
RV_WRITE_CSR(CSR_PMAADDR(12),frame->pmaaddr12);
RV_WRITE_CSR(CSR_PMAADDR(13),frame->pmaaddr13);
RV_WRITE_CSR(CSR_PMAADDR(14),frame->pmaaddr14);
RV_WRITE_CSR(CSR_PMAADDR(15),frame->pmaaddr15);
RV_WRITE_CSR(CSR_PMACFG(0), frame->pmacfg0);
RV_WRITE_CSR(CSR_PMACFG(1), frame->pmacfg1);
RV_WRITE_CSR(CSR_PMACFG(2), frame->pmacfg2);
RV_WRITE_CSR(CSR_PMACFG(3), frame->pmacfg3);
RV_WRITE_CSR(CSR_PMACFG(4), frame->pmacfg4);
RV_WRITE_CSR(CSR_PMACFG(5), frame->pmacfg5);
RV_WRITE_CSR(CSR_PMACFG(6), frame->pmacfg6);
RV_WRITE_CSR(CSR_PMACFG(7), frame->pmacfg7);
RV_WRITE_CSR(CSR_PMACFG(8), frame->pmacfg8);
RV_WRITE_CSR(CSR_PMACFG(9), frame->pmacfg9);
RV_WRITE_CSR(CSR_PMACFG(10), frame->pmacfg10);
RV_WRITE_CSR(CSR_PMACFG(11), frame->pmacfg11);
RV_WRITE_CSR(CSR_PMACFG(12), frame->pmacfg12);
RV_WRITE_CSR(CSR_PMACFG(13), frame->pmacfg13);
RV_WRITE_CSR(CSR_PMACFG(14), frame->pmacfg14);
RV_WRITE_CSR(CSR_PMACFG(15), frame->pmacfg15);
#endif //SOC_CPU_HAS_PMA
RV_WRITE_CSR(utvec, frame->utvec);
RV_WRITE_CSR(ustatus, frame->ustatus);
@ -612,7 +685,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
}
#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),

View File

@ -124,6 +124,17 @@
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
#endif
// Actually costs 80us, using the fastest slow clock 150K calculation takes about 16 ticks
#define SLEEP_TIMER_ALARM_TO_SLEEP_TICKS (16)
#if SOC_PM_SUPPORT_TOP_PD
// IDF console uses 8 bits data mode without parity, so each char occupy 8(data)+1(start)+1(stop)=10bits
#define UART_FLUSH_US_PER_CHAR (10*1000*1000 / CONFIG_ESP_CONSOLE_UART_BAUDRATE)
#define CONCATENATE_HELPER(x, y) (x##y)
#define CONCATENATE(x, y) CONCATENATE_HELPER(x, y)
#define CONSOLE_UART_DEV (&CONCATENATE(UART, CONFIG_ESP_CONSOLE_UART_NUM))
#endif
#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
#ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
@ -224,7 +235,7 @@ static void ext0_wakeup_prepare(void);
#if SOC_PM_SUPPORT_EXT1_WAKEUP
static void ext1_wakeup_prepare(void);
#endif
static void timer_wakeup_prepare(void);
static esp_err_t timer_wakeup_prepare(void);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
static void touch_wakeup_prepare(void);
#endif
@ -476,19 +487,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 deep sleep, wait for the contents of UART FIFO to be sent.
bool deep_sleep = (mode == ESP_SLEEP_MODE_DEEP_SLEEP);
if (deep_sleep) {
flush_uarts();
} else {
#if SOC_PM_SUPPORT_TOP_PD
if (pd_flags & PMU_SLEEP_PD_TOP) {
flush_uarts();
} else
#endif
{
suspend_uarts();
}
}
bool should_skip_sleep = false;
#if SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
//Keep the RTC8M_CLK on if RTC clock is rc_fast_d256.
@ -512,6 +511,18 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
rtc_clk_cpu_freq_get_config(&cpu_freq_config);
rtc_clk_cpu_freq_set_xtal();
// Deep sleep UART prepare
/* flush_uart should be as late as possible, because the later the flush,
the shorter the time overhead of entering sleep caused by blocking,
and blocking after frequency switching can also reduce the power consumption
during the active state.*/
/* ext/gpio deepsleep wakeup prepare will change GPIO configure,
we need to flush uart before it */
if (deep_sleep) {
flush_uarts();
}
#if SOC_PM_SUPPORT_EXT0_WAKEUP
// Configure pins for external wakeup
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
@ -585,6 +596,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
}
// 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,
@ -603,7 +615,32 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
// Configure timer wakeup
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;
}
}
// Light sleep UART prepare
if (!deep_sleep) {
#if SOC_PM_SUPPORT_TOP_PD
if (pd_flags & PMU_SLEEP_PD_TOP) {
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) &&
// s_config.sleep_duration here has been compensated in timer_wakeup_prepare,
// +2 is for cover the last charactor flush time and timer alarm to sleep request time(no more than 80us)
(s_config.sleep_duration < (UART_LL_FIFO_DEF_LEN - uart_ll_get_txfifo_len(CONSOLE_UART_DEV) + 2) * UART_FLUSH_US_PER_CHAR)) {
result = ESP_ERR_SLEEP_REJECT;
should_skip_sleep = true;
} else {
/* Only flush the uart_num configured to console, the transmission integrity of
other uarts is guaranteed by the UART driver */
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
}
} else
#endif
{
suspend_uarts();
}
}
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
@ -612,66 +649,67 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
}
#endif
uint32_t result;
if (deep_sleep) {
if (!should_skip_sleep) {
if (deep_sleep) {
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
esp_sleep_isolate_digital_gpio();
esp_sleep_isolate_digital_gpio();
#endif
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
esp_set_deep_sleep_wake_stub_default_entry();
// Enter Deep Sleep
esp_set_deep_sleep_wake_stub_default_entry();
// Enter Deep Sleep
#if SOC_PMU_SUPPORTED
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);
#else
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
#endif
#else
#if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
/* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */
/* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */
#if SOC_RTC_FAST_MEM_SUPPORTED
set_rtc_memory_crc();
set_rtc_memory_crc();
#endif
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
#else
/* Otherwise, need to call the dedicated soc function for this */
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
/* Otherwise, need to call the dedicated soc function for this */
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
#endif
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
} else {
} else {
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
In order to avoid the leakage of the SPI cs pin, hold it here */
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
In order to avoid the leakage of the SPI cs pin, hold it here */
#if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND)
if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) {
rtcio_ll_force_hold_enable(SPI_CS0_GPIO_NUM);
}
if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) {
rtcio_ll_force_hold_enable(SPI_CS0_GPIO_NUM);
}
#endif
#if SOC_PM_CPU_RETENTION_BY_SW
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 {
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
}
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 {
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
}
#else
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
#endif
/* Unhold the SPI CS pin */
/* Unhold the SPI CS pin */
#if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND)
if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) {
rtcio_ll_force_hold_disable(SPI_CS0_GPIO_NUM);
}
if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) {
rtcio_ll_force_hold_disable(SPI_CS0_GPIO_NUM);
}
#endif
}
}
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
rtc_sleep_systimer_enable(true);
}
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
rtc_sleep_systimer_enable(true);
}
#endif
}
// Restore CPU frequency
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
@ -1122,7 +1160,7 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
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;
if (sleep_duration < 0) {
@ -1130,12 +1168,24 @@ static void timer_wakeup_prepare(void)
}
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
lp_timer_hal_set_alarm_target(0, s_config.rtc_ticks_at_sleep_start + ticks);
#else
rtc_hal_set_wakeup_timer(s_config.rtc_ticks_at_sleep_start + ticks);
#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)) {
// Treat too short sleep duration setting as timer reject
return ESP_ERR_SLEEP_REJECT;
}
#endif
lp_timer_hal_set_alarm_target(0, target_wakeup_tick);
#else
rtc_hal_set_wakeup_timer(target_wakeup_tick);
#endif
s_config.sleep_duration = sleep_duration;
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3

View File

@ -138,13 +138,19 @@ menu "Power Management"
context of the necessary hardware for FreeRTOS to run, it will need at least 4.55 KB free heap
at sleep time. Otherwise sleep will not power down the peripherals.
Note: Please use this option with caution, the current IDF does not support the retention of
Note1: Please use this option with caution, the current IDF does not support the retention of
all peripherals. When the digital peripherals are powered off and a sleep and wake-up is completed,
the peripherals that have not saved the running context are equivalent to performing a reset.
!!! Please confirm the peripherals used in your application and their sleep retention support status
before enabling this option, peripherals sleep retention driver support status is tracked in
power_management.rst
Note2: When this option is enabled simultaneously with FREERTOS_USE_TICKLESS_IDLE, since the UART will
be powered down, the uart FIFO will be flushed before sleep to avoid data loss, however, this has the
potential to block the sleep process and cause the wakeup time to be skipped, which will cause the tick
of freertos to not be compensated correctly when returning from sleep and cause the system to crash.
To avoid this, you can increase FREERTOS_IDLE_TIME_BEFORE_SLEEP threshold in menuconfig.
config PM_UPDATE_CCOMPARE_HLI_WORKAROUND
bool
default y if PM_ENABLE && BTDM_CTRL_HLI

View File

@ -156,6 +156,7 @@ static const char* s_mode_names[] = {
"APB_MAX",
"CPU_MAX"
};
static uint32_t s_light_sleep_counts, s_light_sleep_reject_counts;
#endif // WITH_PROFILING
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
@ -612,7 +613,13 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
/* Enter sleep */
ESP_PM_TRACE_ENTER(SLEEP, core_id);
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;
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_mode_t cur_mode = s_mode;
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);
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, "%-8s %-10s %-10s %-10s\n", "Mode", "CPU_freq", "Time(us)", "Time(%)");
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 */
continue;
}
@ -670,6 +680,10 @@ void esp_pm_impl_dump_stats(FILE* out)
time_in_mode[i],
(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

View File

@ -271,6 +271,9 @@ menu "FreeRTOS"
# Minimal value is 2 because of a check in FreeRTOS.h (search configEXPECTED_IDLE_TIME_BEFORE_SLEEP)
help
FreeRTOS will enter light sleep mode if no tasks need to run for this number of ticks.
You can enable PM_PROFILING feature in esp_pm components and dump the sleep status with
esp_pm_dump_locks, if the proportion of rejected sleeps is too high, please increase
this value to improve scheduling efficiency
endmenu # Kernel

View File

@ -49,6 +49,9 @@ extern "C" {
#define CSR_PMACFG0 0xBC0
#define CSR_PMAADDR0 0xBD0
#define CSR_PMACFG(i) (CSR_PMACFG0 + (i))
#define CSR_PMAADDR(i) (CSR_PMAADDR0 + (i))
#define PMA_EN BIT(0)
#define PMA_R BIT(4)
#define PMA_W BIT(3)

View File

@ -117,10 +117,6 @@ STRUCT_BEGIN
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA1, tdata1)
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA2, tdata2)
STRUCT_FIELD (long, 4, RV_SLP_CTX_TCONTROL, tcontrol)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG0, pmpcfg0)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG1, pmpcfg1)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR0, pmpaddr0)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR1, pmpaddr1)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR2, pmpaddr2)
@ -137,6 +133,45 @@ STRUCT_BEGIN
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR13, pmpaddr13)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR14, pmpaddr14)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR15, pmpaddr15)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG0, pmpcfg0)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG1, pmpcfg1)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3)
#if SOC_CPU_HAS_PMA
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR0, pmaaddr0)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR1, pmaaddr1)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR2, pmaaddr2)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR3, pmaaddr3)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR4, pmaaddr4)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR5, pmaaddr5)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR6, pmaaddr6)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR7, pmaaddr7)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR8, pmaaddr8)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR9, pmaaddr9)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR10, pmaaddr10)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR11, pmaaddr11)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR12, pmaaddr12)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR13, pmaaddr13)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR14, pmaaddr14)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR15, pmaaddr15)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG0, pmacfg0)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG1, pmacfg1)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG2, pmacfg2)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG3, pmacfg3)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG4, pmacfg4)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG5, pmacfg5)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG6, pmacfg6)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG7, pmacfg7)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG8, pmacfg8)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG9, pmacfg9)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG10, pmacfg10)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG11, pmacfg11)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG12, pmacfg12)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG13, pmacfg13)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG14, pmacfg14)
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG15, pmacfg15)
#endif // SOC_CPU_HAS_PMA
STRUCT_FIELD (long, 4, RV_SLP_CTX_UTVEC, utvec)
STRUCT_FIELD (long, 4, RV_SLP_CTX_USTATUS, ustatus)