diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 7cc0ddbe56..03cc73d750 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -102,7 +102,7 @@ menu "ESP System Settings" default y if IDF_TARGET_ESP32H4 default y if IDF_TARGET_ESP32C6 default n if IDF_TARGET_ESP32H2 # IDF-5667 & IDF-6847 - depends on !IDF_TARGET_ESP32C2 + depends on SOC_RTC_FAST_MEM_SUPPORTED config ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP bool "Enable RTC fast memory for dynamic allocations" diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index 659892177b..74c8750bf7 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -553,10 +553,10 @@ static void trigger_deepsleep(void) if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { // NVS partition was truncated and needs to be erased // Retry nvs_flash_init - ESP_ERROR_CHECK(nvs_flash_erase()); + TEST_ESP_OK(nvs_flash_erase()); err = nvs_flash_init(); } - ESP_ERROR_CHECK(err); + TEST_ESP_OK(err); nvs_handle_t nvs_handle; err = nvs_open("storage", NVS_READWRITE, &nvs_handle); @@ -579,12 +579,12 @@ static void trigger_deepsleep(void) // Save start time. Deep sleep. gettimeofday(&start, NULL); - ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "start_sec", start.tv_sec)); - ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "start_usec", start.tv_usec)); - ESP_ERROR_CHECK(nvs_commit(nvs_handle)); + TEST_ESP_OK(nvs_set_i32(nvs_handle, "start_sec", start.tv_sec)); + TEST_ESP_OK(nvs_set_i32(nvs_handle, "start_usec", start.tv_usec)); + TEST_ESP_OK(nvs_commit(nvs_handle)); nvs_close(nvs_handle); // Deinit NVS to prevent Unity from complaining "The test leaked too much memory" - ESP_ERROR_CHECK(nvs_flash_deinit()); + TEST_ESP_OK(nvs_flash_deinit()); esp_sleep_enable_timer_wakeup(1000); // In function esp_deep_sleep_start() uses function esp_sync_timekeeping_timers() @@ -601,10 +601,10 @@ static void check_time_deepsleep(void) if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { // NVS partition was truncated and needs to be erased // Retry nvs_flash_init - ESP_ERROR_CHECK(nvs_flash_erase()); + TEST_ESP_OK(nvs_flash_erase()); err = nvs_flash_init(); } - ESP_ERROR_CHECK(err); + TEST_ESP_OK(err); nvs_handle_t nvs_handle; err = nvs_open("storage", NVS_READWRITE, &nvs_handle); @@ -615,11 +615,11 @@ static void check_time_deepsleep(void) } // Get start time of deep sleep - ESP_ERROR_CHECK(nvs_get_i32(nvs_handle, "start_sec", (int32_t *)&start.tv_sec)); - ESP_ERROR_CHECK(nvs_get_i32(nvs_handle, "start_usec", (int32_t *)&start.tv_usec)); + TEST_ESP_OK(nvs_get_i32(nvs_handle, "start_sec", (int32_t *)&start.tv_sec)); + TEST_ESP_OK(nvs_get_i32(nvs_handle, "start_usec", (int32_t *)&start.tv_usec)); nvs_close(nvs_handle); // Deinit NVS to prevent Unity from complaining "The test leaked too much memory" - ESP_ERROR_CHECK(nvs_flash_deinit()); + TEST_ESP_OK(nvs_flash_deinit()); // Reset must be caused by deep sleep soc_reset_reason_t reason = esp_rom_get_reset_reason(0); diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 9068f4550e..94f013d152 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -40,9 +40,9 @@ examples/system/console/basic: examples/system/deep_sleep: disable: - - if: IDF_TARGET in ["esp32c2", "esp32h2"] + - if: IDF_TARGET in ["esp32h2"] temporary: true - reason: target(s) not supported yet # IDF-5432 / IDF-6268 + reason: target(s) not supported yet # IDF-6268 examples/system/deep_sleep_wake_stub: disable: diff --git a/examples/system/deep_sleep/README.md b/examples/system/deep_sleep/README.md index a57e61f2ee..dc1443740b 100644 --- a/examples/system/deep_sleep/README.md +++ b/examples/system/deep_sleep/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | # Deep Sleep Example diff --git a/examples/system/deep_sleep/main/deep_sleep_example_main.c b/examples/system/deep_sleep/main/deep_sleep_example_main.c index b8e60afc6e..8ef6f77c35 100644 --- a/examples/system/deep_sleep/main/deep_sleep_example_main.c +++ b/examples/system/deep_sleep/main/deep_sleep_example_main.c @@ -21,6 +21,14 @@ #include "esp_log.h" #include "driver/rtc_io.h" #include "soc/rtc.h" +#include "nvs_flash.h" +#include "nvs.h" + +#if SOC_RTC_FAST_MEM_SUPPORTED +static RTC_DATA_ATTR struct timeval sleep_enter_time; +#else +static struct timeval sleep_enter_time; +#endif #if SOC_TOUCH_SENSOR_SUPPORTED #include "soc/sens_periph.h" @@ -36,8 +44,6 @@ #endif #endif -static RTC_DATA_ATTR struct timeval sleep_enter_time; - #ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP #if CONFIG_IDF_TARGET_ESP32 #define TOUCH_THRESH_NO_USE 0 @@ -47,6 +53,35 @@ static void calibrate_touch_pad(touch_pad_t pad); void app_main(void) { + /** + * Prefer to use RTC mem instead of NVS to save the deep sleep enter time, unless the chip + * does not support RTC mem(such as esp32c2). Because the time overhead of NVS will cause + * the recorded deep sleep enter time to be not very accurate. + */ +#if !SOC_RTC_FAST_MEM_SUPPORTED + // Initialize NVS + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + // NVS partition was truncated and needs to be erased + // Retry nvs_flash_init + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); + + nvs_handle_t nvs_handle; + err = nvs_open("storage", NVS_READWRITE, &nvs_handle); + if (err != ESP_OK) { + printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } else { + printf("Open NVS done\n"); + } + + // Get deep sleep enter time + nvs_get_i32(nvs_handle, "slp_enter_sec", (int32_t *)&sleep_enter_time.tv_sec); + nvs_get_i32(nvs_handle, "slp_enter_usec", (int32_t *)&sleep_enter_time.tv_usec); +#endif + struct timeval now; gettimeofday(&now, NULL); int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; @@ -226,8 +261,19 @@ void app_main(void) #endif printf("Entering deep sleep\n"); + + // get deep sleep enter time gettimeofday(&sleep_enter_time, NULL); +#if !SOC_RTC_FAST_MEM_SUPPORTED + // record deep sleep enter time via nvs + ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "slp_enter_sec", sleep_enter_time.tv_sec)); + ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "slp_enter_usec", sleep_enter_time.tv_usec)); + ESP_ERROR_CHECK(nvs_commit(nvs_handle)); + nvs_close(nvs_handle); +#endif + + // enter deep sleep esp_deep_sleep_start(); } diff --git a/examples/system/deep_sleep/pytest_deep_sleep.py b/examples/system/deep_sleep/pytest_deep_sleep.py index 098158672f..0ab6dc4068 100644 --- a/examples/system/deep_sleep/pytest_deep_sleep.py +++ b/examples/system/deep_sleep/pytest_deep_sleep.py @@ -12,7 +12,7 @@ touch_wake_up_support = ['esp32', 'esp32s2'] CONFIGS = [ pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]), - pytest.param('basic', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32c3, pytest.mark.esp32c6]), + pytest.param('basic', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32c3, pytest.mark.esp32c6, pytest.mark.esp32c2]), ] @@ -60,7 +60,9 @@ def test_deep_sleep(dut: Dut) -> None: # This line indicates that the CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP option set in sdkconfig.defaults # has correctly allowed skipping verification on wakeup - dut.expect_exact('boot: Fast booting app from partition', timeout=2) + # Note: this feature depends on rtc mem + if dut.app.sdkconfig.get('SOC_RTC_MEM_SUPPORTED') is True: + dut.expect_exact('boot: Fast booting app from partition', timeout=2) # Check that it measured 2xxxxms in deep sleep, i.e at least 20 seconds: dut.expect(r'Wake up from timer. Time spent in deep sleep: 2\d{4}ms', timeout=2) diff --git a/examples/system/light_sleep/README.md b/examples/system/light_sleep/README.md index b29415c4f1..15af3fe6f7 100644 --- a/examples/system/light_sleep/README.md +++ b/examples/system/light_sleep/README.md @@ -15,6 +15,11 @@ The example enables the following wakeup sources: The example also prints time spent in light sleep mode to illustrate that timekeeping continues while the chip is in light sleep. +Note: If you find that the bottom current measured by running this example is larger than what is declared on the datasheet, you can try the following methods: + +- configure the CPU to be powered down via menuconfig(not all esp series support this feature) +- configure the SPI Flash to be powered down via menuconfig + ## How to Use Example ### Hardware Required diff --git a/examples/wifi/power_save/sdkconfig.defaults b/examples/wifi/power_save/sdkconfig.defaults index 774d706160..cb1a0a7317 100644 --- a/examples/wifi/power_save/sdkconfig.defaults +++ b/examples/wifi/power_save/sdkconfig.defaults @@ -12,3 +12,5 @@ CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL=y CONFIG_PM_SLP_DISABLE_GPIO=y # Enable wifi sleep iram optimization CONFIG_ESP_WIFI_SLP_IRAM_OPT=y +# Use 1000Hz freertos tick to lower sleep time threshold +CONFIG_FREERTOS_HZ=1000