mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
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:
commit
d89919999e
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user