diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index e0d8037870..67b9bfc707 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -141,24 +141,34 @@ menu "Hardware Settings" This option provides a software workaround for this issue. Configure to isolate all GPIO pins in sleep state. - config ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY - int "Extra delay in deep sleep wake stub (in us)" - depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3 - default 2000 + config ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY + int "Extra delay (in us) after flash powerdown sleep wakeup to wait flash ready" + default 2000 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3 + default 0 range 0 5000 help - When the chip exits deep sleep, the CPU and the flash chip are powered on - at the same time. CPU will run deep sleep stub first, and then - proceed to load code from flash. Some flash chips need sufficient - time to pass between power on and first read operation. By default, - without any extra delay, this time is approximately 900us, although + When the chip exits sleep, the CPU and the flash chip are powered on at the same time. + CPU will run rom code (deepsleep) or ram code (lightsleep) first, and then load or execute + code from flash. + + Some flash chips need sufficient time to pass between power on and first read operation. + By default, without any extra delay, this time is approximately 900us, although some flash chip types need more than that. - By default extra delay is set to 2000us. When optimizing startup time + (!!! Please adjust this value according to the Data Sheet of SPI Flash used in your project.) + In Flash Data Sheet, the parameters that define the Flash ready timing after power-up (minimum + time from Vcc(min) to CS activeare) usually named tVSL in ELECTRICAL CHARACTERISTICS chapter, + and the configuration value here should be: + ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY = tVSL - 900 + + For esp32 and esp32s3, the default extra delay is set to 2000us. When optimizing startup time for applications which require it, this value may be reduced. - If you are seeing "flash read err, 1000" message printed to the - console after deep sleep reset, try increasing this value. + If you are seeing "flash read err, 1000" message printed to the console after deep sleep reset + on esp32, or triggered RTC_WDT/LP_WDT after lightsleep wakeup, try increasing this value. + (For esp32, the delay will be executed in both deep sleep and light sleep wake up flow. + For chips after esp32, the delay will be executed only in light sleep flow, the delay + controlled by the EFUSE_FLASH_TPUW in ROM will be executed in deepsleep wake up flow.) config ESP_SLEEP_CACHE_SAFE_ASSERTION bool "Check the cache safety of the sleep wakeup code in sleep process" 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 3420e9afdf..1d8d2c309b 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -291,6 +291,11 @@ void pmu_init(void); */ void pmu_sleep_enable_hp_sleep_sysclk(bool enable); +/** + * Get the time overhead used by regdma to work on the retention link during the hardware wake-up process + * @return regdma time cost during hardware wake-up stage in microseconds + */ +uint32_t pmu_sleep_get_wakup_retention_cost(void); #endif //#if SOC_PMU_SUPPORTED diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index faa6a4d008..9628cc794f 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -286,3 +286,8 @@ void pmu_sleep_enable_hp_sleep_sysclk(bool enable) { pmu_ll_hp_set_icg_sysclk_enable(PMU_instance()->hal->dev, HP(SLEEP), enable); } + +uint32_t pmu_sleep_get_wakup_retention_cost(void) +{ + return PMU_REGDMA_S2A_WORK_TIME_US; +} diff --git a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h index 0938e058b8..75e1f99ff2 100644 --- a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h @@ -44,6 +44,8 @@ extern "C" { #define PMU_HP_XPD_DEEPSLEEP 0 #define PMU_LP_DRVB_DEEPSLEEP 0 +#define PMU_REGDMA_S2A_WORK_TIME_US 480 + #define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12 #define PMU_LP_DBIAS_DEEPSLEEP_0V7 23 @@ -456,7 +458,7 @@ typedef struct pmu_sleep_machine_constant { .power_supply_wait_time_us = 2, \ .power_up_wait_time_us = 2, \ .regdma_s2m_work_time_us = 172, \ - .regdma_s2a_work_time_us = 480, \ + .regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_US, \ .regdma_m2a_work_time_us = 278, \ .regdma_a2s_work_time_us = 382, \ .regdma_rf_on_work_time_us = 70, \ diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index 1f39dd0a7f..75a170d6a4 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -228,3 +228,8 @@ bool pmu_sleep_finish(void) { return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev); } + +uint32_t pmu_sleep_get_wakup_retention_cost(void) +{ + return PMU_REGDMA_S2A_WORK_TIME_US; +} diff --git a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h index 824ccb9db7..50f55ed258 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h @@ -41,6 +41,8 @@ extern "C" { #define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1 #define PMU_LP_DBIAS_LIGHTSLEEP_0V7 6 +#define PMU_REGDMA_S2A_WORK_TIME_US 0 + // FOR DEEPSLEEP #define PMU_HP_XPD_DEEPSLEEP 0 #define PMU_LP_DRVB_DEEPSLEEP 7 @@ -438,7 +440,7 @@ typedef struct pmu_sleep_machine_constant { .analog_wait_time_us = 154, \ .power_supply_wait_time_us = 2, \ .power_up_wait_time_us = 2, \ - .regdma_s2a_work_time_us = 0, \ + .regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_US, \ .regdma_a2s_work_time_us = 0, \ .xtal_wait_stable_time_us = 250, \ .pll_wait_stable_time_us = 1 \ diff --git a/components/esp_hw_support/sdkconfig.rename.esp32 b/components/esp_hw_support/sdkconfig.rename.esp32 index 91bac13a64..058f851538 100644 --- a/components/esp_hw_support/sdkconfig.rename.esp32 +++ b/components/esp_hw_support/sdkconfig.rename.esp32 @@ -21,7 +21,8 @@ CONFIG_SPIRAM_SUPPORT CONFIG_SPIRAM CONFIG_ESP32_SPIRAM_SUPPORT CONFIG_SPIRAM CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP -CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY CONFIG_ESP32_XTAL_FREQ_26 CONFIG_XTAL_FREQ_26 CONFIG_ESP32_XTAL_FREQ_40 CONFIG_XTAL_FREQ_40 diff --git a/components/esp_hw_support/sdkconfig.rename.esp32s3 b/components/esp_hw_support/sdkconfig.rename.esp32s3 index 77e595a907..39a3d34cca 100644 --- a/components/esp_hw_support/sdkconfig.rename.esp32s3 +++ b/components/esp_hw_support/sdkconfig.rename.esp32s3 @@ -10,4 +10,5 @@ CONFIG_ESP32S3_RTC_XTAL_CAL_RETRY CONFIG_RTC_XTAL_CAL_RE CONFIG_ESP32S3_SPIRAM_SUPPORT CONFIG_SPIRAM -CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 309c7f8379..6ee69d336a 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -110,8 +110,8 @@ // If light sleep time is less than that, don't power down flash #define FLASH_PD_MIN_SLEEP_TIME_US 2000 -// Time from VDD_SDIO power up to first flash read in ROM code -#define VDD_SDIO_POWERUP_TO_FLASH_READ_US 700 +// Default waiting time for the software to wait for Flash ready after waking up from sleep +#define ESP_SLEEP_WAIT_FLASH_READY_DEFAULT_DELAY_US 700 // Cycles for RTC Timer clock source (internal oscillator) calibrate #define RTC_CLK_SRC_CAL_CYCLES (10) @@ -160,12 +160,6 @@ #define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ) #endif -#if CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY -#define DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY -#else -#define DEEP_SLEEP_WAKEUP_DELAY 0 -#endif - // Minimal amount of time we can sleep for #define LIGHT_SLEEP_MIN_TIME_US 200 @@ -362,13 +356,16 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) _DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG) | DPORT_PRO_CACHE_MMU_IA_CLR); _DPORT_REG_WRITE(DPORT_PRO_CACHE_CTRL1_REG, _DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG) & (~DPORT_PRO_CACHE_MMU_IA_CLR)); -#if DEEP_SLEEP_WAKEUP_DELAY > 0 +#if CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY > 0 // ROM code has not started yet, so we need to set delay factor // used by esp_rom_delay_us first. ets_update_cpu_frequency_rom(ets_get_detected_xtal_freq() / 1000000); - // This delay is configured in menuconfig, it can be used to give - // the flash chip some time to become ready. - esp_rom_delay_us(DEEP_SLEEP_WAKEUP_DELAY); + // Time from VDD_SDIO power up to first flash read in ROM code is 700 us, + // for some flash chips is not sufficient, this delay is configured in menuconfig, + // it can be used to give the flash chip some extra time to become ready. + // For later chips, we have EFUSE_FLASH_TPUW field to configure it and do + // this delay in the ROM. + esp_rom_delay_us(CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY); #endif #elif CONFIG_IDF_TARGET_ESP32S2 REG_SET_BIT(EXTMEM_CACHE_DBG_INT_ENA_REG, EXTMEM_CACHE_DBG_EN); @@ -1045,6 +1042,18 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, // If SPI flash was powered down, wait for it to become ready if (pd_flags & RTC_SLEEP_PD_VDDSDIO) { +#if SOC_PM_SUPPORT_TOP_PD + if (pd_flags & PMU_SLEEP_PD_TOP) { + uint32_t flash_ready_hw_waited_time_us = pmu_sleep_get_wakup_retention_cost(); + uint32_t flash_ready_sw_waited_time_us = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / MHZ); + uint32_t flash_ready_waited_time_us = flash_ready_hw_waited_time_us + flash_ready_sw_waited_time_us; + if (flash_enable_time_us > flash_ready_waited_time_us){ + flash_enable_time_us -= flash_ready_waited_time_us; + } else { + flash_enable_time_us = 0; + } + } +#endif // Wait for the flash chip to start up esp_rom_delay_us(flash_enable_time_us); } @@ -1157,12 +1166,9 @@ esp_err_t esp_light_sleep_start(void) + rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_slp_cycles + RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES, s_config.rtc_clk_cal_period); #endif -#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-6930 - const uint32_t flash_enable_time_us = 0; -#else // Decide if VDD_SDIO needs to be powered down; // If it needs to be powered down, adjust sleep time. - const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US + DEEP_SLEEP_WAKEUP_DELAY; + const uint32_t flash_enable_time_us = ESP_SLEEP_WAIT_FLASH_READY_DEFAULT_DELAY_US + CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY; /** * If VDD_SDIO power domain is requested to be turned off, bit `RTC_SLEEP_PD_VDDSDIO` @@ -1201,7 +1207,6 @@ esp_err_t esp_light_sleep_start(void) } } } -#endif periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in); diff --git a/tools/ldgen/samples/sdkconfig b/tools/ldgen/samples/sdkconfig index a43ae9db5d..602129ddc2 100644 --- a/tools/ldgen/samples/sdkconfig +++ b/tools/ldgen/samples/sdkconfig @@ -184,7 +184,7 @@ CONFIG_RTC_CLK_SRC_INT_RC=y CONFIG_RTC_CLK_SRC_EXT_CRYS= CONFIG_RTC_CLK_CAL_CYCLES=1024 CONFIG_RTC_XTAL_BOOTSTRAP_CYCLES=100 -CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 CONFIG_XTAL_FREQ_40=y CONFIG_XTAL_FREQ_26= CONFIG_XTAL_FREQ_AUTO=