diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index fe3021a830..03a85ea5a5 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -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 */ diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index f990464c80..a2f28c4c52 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -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); } diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c index 948d5a99d2..1bc2037d6d 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -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), diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b097bb37df..95c6e82868 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -124,6 +124,9 @@ #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) + #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) @@ -222,7 +225,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 @@ -474,6 +477,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); + bool should_skip_sleep = false; if (deep_sleep) { flush_uarts(); @@ -590,6 +594,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, @@ -608,7 +613,10 @@ 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; + } } #if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND @@ -617,66 +625,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 @@ -1124,7 +1133,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) { @@ -1132,12 +1141,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 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 + // When pd_top is supported, light_sleep will flush uart, and the sleep overhead time will become an unpredictable value, + // 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 + 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 diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index dbb21c28f0..2de22f3e45 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -124,13 +124,20 @@ 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 use ESP_PM_NO_LIGHT_SLEEP to protect your UART transmission, fflush the stdout + after printing, or increase FREERTOS_IDLE_TIME_BEFORE_SLEEP threshold in menuconfig. + config PM_UPDATE_CCOMPARE_HLI_WORKAROUND bool default y if PM_ENABLE && BTDM_CTRL_HLI diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 13343f48f4..9b7f6e608a 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -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 diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 6c915d3d65..5be1dcde8a 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -262,6 +262,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 diff --git a/components/riscv/include/riscv/csr.h b/components/riscv/include/riscv/csr.h index 2d889d1a20..e5762c9e7e 100644 --- a/components/riscv/include/riscv/csr.h +++ b/components/riscv/include/riscv/csr.h @@ -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) diff --git a/components/riscv/include/riscv/rvsleep-frames.h b/components/riscv/include/riscv/rvsleep-frames.h index 929d581c62..b4d00f9440 100644 --- a/components/riscv/include/riscv/rvsleep-frames.h +++ b/components/riscv/include/riscv/rvsleep-frames.h @@ -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)