From e109c5f998c60d7756bf551e4a719ab0e725d2b1 Mon Sep 17 00:00:00 2001 From: jingli Date: Wed, 13 Jul 2022 21:10:17 +0800 Subject: [PATCH 1/5] esp32c2: support rtc time feature depend on rtc memory, since c2 does not have rtc memory --- components/esp_hw_support/esp_clk.c | 44 +++++++++-- components/esp_hw_support/intr_alloc.c | 9 +-- .../esp_hw_support/port/esp32c2/rtc_sleep.c | 79 ------------------- components/esp_hw_support/sleep_modes.c | 7 +- components/esp_rom/include/esp32c2/rom/rtc.h | 18 +++-- .../port/soc/esp32c2/reset_reason.c | 10 +-- .../hal/esp32c2/include/hal/clk_tree_ll.h | 21 +++++ 7 files changed, 80 insertions(+), 108 deletions(-) diff --git a/components/esp_hw_support/esp_clk.c b/components/esp_hw_support/esp_clk.c index 3073b4aafc..0b90ef7cf1 100644 --- a/components/esp_hw_support/esp_clk.c +++ b/components/esp_hw_support/esp_clk.c @@ -49,8 +49,9 @@ extern uint32_t g_ticks_per_us_app; static portMUX_TYPE s_esp_rtc_time_lock = portMUX_INITIALIZER_UNLOCKED; -// TODO: IDF-4239 +#if SOC_RTC_FAST_MEM_SUPPORTED static RTC_NOINIT_ATTR uint64_t s_esp_rtc_time_us, s_rtc_last_ticks; +#endif inline static int IRAM_ATTR s_get_cpu_freq_mhz(void) { @@ -91,18 +92,18 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us) uint64_t esp_rtc_get_time_us(void) { -#if !SOC_RTC_FAST_MEM_SUPPORTED - //IDF-3901 - return 0; -#endif portENTER_CRITICAL_SAFE(&s_esp_rtc_time_lock); const uint32_t cal = esp_clk_slowclk_cal_get(); +#if SOC_RTC_FAST_MEM_SUPPORTED if (cal == 0) { s_esp_rtc_time_us = 0; s_rtc_last_ticks = 0; } const uint64_t rtc_this_ticks = rtc_time_get(); const uint64_t ticks = rtc_this_ticks - s_rtc_last_ticks; +#else + const uint64_t ticks = rtc_time_get(); +#endif /* RTC counter result is up to 2^48, calibration factor is up to 2^24, * for a 32kHz clock. We need to calculate (assuming no overflow): * (ticks * cal) >> RTC_CLK_CAL_FRACT @@ -118,10 +119,16 @@ uint64_t esp_rtc_get_time_us(void) const uint64_t ticks_high = ticks >> 32; const uint64_t delta_time_us = ((ticks_low * cal) >> RTC_CLK_CAL_FRACT) + ((ticks_high * cal) << (32 - RTC_CLK_CAL_FRACT)); +#if SOC_RTC_FAST_MEM_SUPPORTED s_esp_rtc_time_us += delta_time_us; s_rtc_last_ticks = rtc_this_ticks; portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); return s_esp_rtc_time_us; +#else + uint64_t esp_rtc_time_us = delta_time_us + clk_ll_rtc_slow_load_rtc_fix_us(); + portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); + return esp_rtc_time_us; +#endif } void esp_clk_slowclk_cal_set(uint32_t new_cal) @@ -130,7 +137,34 @@ void esp_clk_slowclk_cal_set(uint32_t new_cal) /* To force monotonic time values even when clock calibration value changes, * we adjust esp_rtc_time */ +#if SOC_RTC_FAST_MEM_SUPPORTED esp_rtc_get_time_us(); +#else + portENTER_CRITICAL_SAFE(&s_esp_rtc_time_lock); + uint32_t old_cal = clk_ll_rtc_slow_load_cal(); + if (old_cal != 0) { + /** + * The logic of time correction is: + * old_rtc_us = ticks * old_cal >> RTC_CLK_CAL_FRACT + old_fix_us + * new_rtc_us = ticks * new_cal >> RTC_CLK_CAL_FRACT + new_fix_us + * + * Keep "old_rtc_us == new_rtc_us" to make time monotonically increasing, + * then we can get new_fix_us: + * new_fix_us = (ticks * old_cal >> RTC_CLK_CAL_FRACT + old_fix_us) - (ticks * new_cal >> RTC_CLK_CAL_FRACT) + */ + uint64_t ticks = rtc_time_get(); + const uint64_t ticks_low = ticks & UINT32_MAX; + const uint64_t ticks_high = ticks >> 32; + uint64_t old_fix_us = clk_ll_rtc_slow_load_rtc_fix_us(); + uint64_t new_fix_us; + + old_fix_us += ((ticks_low * old_cal) >> RTC_CLK_CAL_FRACT) + ((ticks_high * old_cal) << (32 - RTC_CLK_CAL_FRACT)); + new_fix_us = ((ticks_low * new_cal) >> RTC_CLK_CAL_FRACT) + ((ticks_high * new_cal) << (32 - RTC_CLK_CAL_FRACT)); + new_fix_us = old_fix_us - new_fix_us; + clk_ll_rtc_slow_store_rtc_fix_us(new_fix_us); + } + portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); +#endif // SOC_RTC_FAST_MEM_SUPPORTED #endif // CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER clk_ll_rtc_slow_store_cal(new_cal); } diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index c3fc56b0d8..40434232ed 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -490,14 +490,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre //ToDo: if we are to allow placing interrupt handlers into the 0x400c0000—0x400c2000 region, //we need to make sure the interrupt is connected to the CPU0. //CPU1 does not have access to the RTC fast memory through this region. - if ((flags & ESP_INTR_FLAG_IRAM) - && handler - && !esp_ptr_in_iram(handler) -#if SOC_RTC_FAST_MEM_SUPPORTED - // IDF-3901. - && !esp_ptr_in_rtc_iram_fast(handler) -#endif - ) { + if ((flags & ESP_INTR_FLAG_IRAM) && handler && !esp_ptr_in_iram(handler) && !esp_ptr_in_rtc_iram_fast(handler)) { return ESP_ERR_INVALID_ARG; } diff --git a/components/esp_hw_support/port/esp32c2/rtc_sleep.c b/components/esp_hw_support/port/esp32c2/rtc_sleep.c index 50ccd67bc7..74a7f135e4 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c2/rtc_sleep.c @@ -177,85 +177,6 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp return rtc_sleep_finish(lslp_mem_inf_fpu); } -#define STR2(X) #X -#define STR(X) STR2(X) - -uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) -{ - REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt); - WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt); - - SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, - RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR); - - /* Calculate RTC Fast Memory CRC (for wake stub) & go to deep sleep - - Because we may be running from RTC memory as stack, we can't easily call any - functions to do this (as registers will spill to stack, corrupting the CRC). - - Instead, load all the values we need into registers then use register ops only to calculate - the CRC value, write it to the RTC CRC value register, and immediately go into deep sleep. - */ - - /* Values used to set the SYSTEM_RTC_FASTMEM_CONFIG_REG value */ - const unsigned CRC_START_ADDR = 0; - const unsigned CRC_LEN = 0x7ff; - - asm volatile( - /* Start CRC calculation */ - "sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN - "or t0, %1, %2\n" - "sw t0, 0(%0)\n" // set RTC_MEM_CRC_START - - /* Wait for the CRC calculation to finish */ - ".Lwaitcrc:\n" - "fence\n" - "lw t0, 0(%0)\n" - "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n" - "and t0, t0, t1\n" - "beqz t0, .Lwaitcrc\n" - "not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START - "and t0, t0, %2\n" - "sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START - "fence\n" - "not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged - - /* Store the calculated value in RTC_MEM_CRC_REG */ - "lw t0, 0(%3)\n" - "sw t0, 0(%4)\n" - "fence\n" - - /* Set register bit to go into deep sleep */ - "lw t0, 0(%5)\n" - "or t0, t0, %6\n" - "sw t0, 0(%5)\n" - "fence\n" - - /* Wait for sleep reject interrupt (never finishes if successful) */ - ".Lwaitsleep:" - "fence\n" - "lw t0, 0(%7)\n" - "and t0, t0, %8\n" - "beqz t0, .Lwaitsleep\n" - - : - : - "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0 - "r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S) - | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1 - "r" (SYSTEM_RTC_MEM_CRC_START), // %2 - "r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3 - "r" (RTC_MEMORY_CRC_REG), // %4 - "r" (RTC_CNTL_STATE0_REG), // %5 - "r" (RTC_CNTL_SLEEP_EN), // %6 - "r" (RTC_CNTL_INT_RAW_REG), // %7 - "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8 - : "t0", "t1" // working registers - ); - - return rtc_sleep_finish(0); -} - static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) { /* In deep sleep mode, we never get here */ diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 138aa8ec98..6e8d02822e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -210,6 +210,7 @@ static void touch_wakeup_prepare(void); static void esp_deep_sleep_wakeup_prepare(void); #endif +#if SOC_RTC_FAST_MEM_SUPPORTED #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY static RTC_FAST_ATTR esp_deep_sleep_wake_stub_fn_t wake_stub_fn_handler = NULL; @@ -282,6 +283,7 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) } void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void); +#endif // SOC_RTC_FAST_MEM_SUPPORTED void esp_deep_sleep(uint64_t time_in_us) { @@ -519,8 +521,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) #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 !CONFIG_IDF_TARGET_ESP32C2 - // RTC has no rtc memory, IDF-3901 +#if SOC_RTC_FAST_MEM_SUPPORTED set_rtc_memory_crc(); #endif result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu); @@ -575,10 +576,12 @@ void IRAM_ATTR esp_deep_sleep_start(void) // record current RTC time s_config.rtc_ticks_at_sleep_start = rtc_time_get(); +#if SOC_RTC_FAST_MEM_SUPPORTED // Configure wake stub if (esp_get_deep_sleep_wake_stub() == NULL) { esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); } +#endif // SOC_RTC_FAST_MEM_SUPPORTED // Decide which power domains can be powered down uint32_t pd_flags = get_power_down_flags(); diff --git a/components/esp_rom/include/esp32c2/rom/rtc.h b/components/esp_rom/include/esp32c2/rom/rtc.h index 910792a29a..14897efd5a 100644 --- a/components/esp_rom/include/esp32c2/rom/rtc.h +++ b/components/esp_rom/include/esp32c2/rom/rtc.h @@ -45,29 +45,35 @@ extern "C" { * ************************************************************************************* * RTC store registers usage - * RTC_CNTL_STORE0_REG Reserved + * RTC_CNTL_STORE0_REG RTC fix us, high 32 bits * RTC_CNTL_STORE1_REG RTC_SLOW_CLK calibration value * RTC_CNTL_STORE2_REG Boot time, low word * RTC_CNTL_STORE3_REG Boot time, high word * RTC_CNTL_STORE4_REG External XTAL frequency * RTC_CNTL_STORE5_REG APB bus frequency - * RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY - * RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC + * RTC_CNTL_STORE6_REG rtc reset cause + * RTC_CNTL_STORE7_REG RTC fix us, low 32 bits ************************************************************************************* + * + * Since esp32c2 does not support RTC fast mem, so use RTC store regs to record rtc time: + * + * |------------------------|----------------------------------------| + * | RTC_CNTL_STORE0_REG | RTC_CNTL_STORE7_REG | + * | rtc_fix_us(MSB) | rtc_fix_us(LSB) | + * |------------------------|----------------------------------------| */ +#define RTC_FIX_US_HIGH_REG RTC_CNTL_STORE0_REG #define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG #define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG #define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG #define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG #define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG -#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG #define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG -#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG +#define RTC_FIX_US_LOW_REG RTC_CNTL_STORE7_REG #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. - typedef enum { AWAKE = 0, //> 32); +} + +/** + * @brief Load the rtc_fix_ticks from RTC storage register + * + * @return The value used to correct the time obtained from the rtc timer when the calibration value changes + */ +static inline uint64_t clk_ll_rtc_slow_load_rtc_fix_us(void) +{ + return REG_READ(RTC_FIX_US_LOW_REG) | ((uint64_t)REG_READ(RTC_FIX_US_HIGH_REG) << 32); +} + #ifdef __cplusplus } #endif From 2da8497358aaf25b8074ee76ff56dac628dd7294 Mon Sep 17 00:00:00 2001 From: jingli Date: Wed, 1 Feb 2023 20:26:15 +0800 Subject: [PATCH 2/5] UT/esp32c2: reenable rtc clk calibration compensation UT --- components/esp_hw_support/test/test_rtc_clk.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/esp_hw_support/test/test_rtc_clk.c b/components/esp_hw_support/test/test_rtc_clk.c index 3911ad0571..54242db441 100644 --- a/components/esp_hw_support/test/test_rtc_clk.c +++ b/components/esp_hw_support/test/test_rtc_clk.c @@ -349,8 +349,6 @@ TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_ #endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -//IDF-5060 TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]") { int64_t t1 = esp_rtc_get_time_us(); @@ -432,4 +430,3 @@ static void check_time_deepsleep_2(void) TEST_CASE_MULTIPLE_STAGES("Test rtc clk calibration compensation across deep sleep", "[rtc_clk][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep_1, check_time_deepsleep_2); #endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) From eb27e688fb6cb5288467e843d02dd4a26556c86b Mon Sep 17 00:00:00 2001 From: jingli Date: Wed, 1 Feb 2023 16:37:04 +0800 Subject: [PATCH 3/5] UT/esp32c2: reenable pm and sleep related UT --- components/esp_pm/test/test_pm.c | 3 - components/esp_system/test/CMakeLists.txt | 3 +- components/esp_system/test/test_sleep.c | 86 ++++++++++++++----- .../rtc_8md256/main/test_rtc_8md256.c | 4 - .../test_apps/rtc_8md256/pytest_rtc_8md256.py | 2 +- examples/system/.build-test-rules.yml | 6 -- examples/system/light_sleep/README.md | 4 +- .../main/light_sleep_example_main.c | 6 ++ .../system/light_sleep/pytest_light_sleep.py | 4 +- 9 files changed, 79 insertions(+), 39 deletions(-) diff --git a/components/esp_pm/test/test_pm.c b/components/esp_pm/test/test_pm.c index ca4b913f99..76c0f1c14e 100644 --- a/components/esp_pm/test/test_pm.c +++ b/components/esp_pm/test/test_pm.c @@ -268,8 +268,6 @@ TEST_CASE("Can wake up from automatic light sleep by GPIO", "[pm][ignore]") #endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) #endif //CONFIG_ULP_COPROC_TYPE_FSM -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -//IDF-5053 typedef struct { int delay_us; int result; @@ -390,7 +388,6 @@ TEST_CASE("esp_timer produces correct delays with light sleep", "[pm]") #undef NUM_INTERVALS } -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) static void timer_cb1(void *arg) { diff --git a/components/esp_system/test/CMakeLists.txt b/components/esp_system/test/CMakeLists.txt index f9dbdc04cf..2f98628ec8 100644 --- a/components/esp_system/test/CMakeLists.txt +++ b/components/esp_system/test/CMakeLists.txt @@ -1,7 +1,8 @@ set(requires "unity" "test_utils" "driver" - "esp_timer") + "esp_timer" + "nvs_flash") set(excludes "test_ipc_isr.c" "test_ipc_isr.S" diff --git a/components/esp_system/test/test_sleep.c b/components/esp_system/test/test_sleep.c index 1a9e2d4df0..655e0b322a 100644 --- a/components/esp_system/test/test_sleep.c +++ b/components/esp_system/test/test_sleep.c @@ -28,6 +28,8 @@ #include "esp_timer.h" #include "esp_private/esp_clk.h" #include "esp_random.h" +#include "nvs_flash.h" +#include "nvs.h" #define ESP_EXT0_WAKEUP_LEVEL_LOW 0 #define ESP_EXT0_WAKEUP_LEVEL_HIGH 1 @@ -64,8 +66,6 @@ TEST_CASE("enter deep sleep on APP CPU and wake up using timer", "[deepsleep][re } #endif -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -//IDF-5131 TEST_CASE("wake up from deep sleep using timer", "[deepsleep][reset=DEEPSLEEP_RESET]") { esp_sleep_enable_timer_wakeup(2000000); @@ -79,7 +79,6 @@ TEST_CASE("light sleep followed by deep sleep", "[deepsleep][reset=DEEPSLEEP_RES esp_deep_sleep_start(); } -//IDF-5053 TEST_CASE("wake up from light sleep using timer", "[deepsleep]") { esp_sleep_enable_timer_wakeup(2000000); @@ -91,7 +90,6 @@ TEST_CASE("wake up from light sleep using timer", "[deepsleep]") (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f; TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt); } -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) //NOTE: Explained in IDF-1445 | MR !14996 #if !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384) @@ -232,8 +230,6 @@ TEST_CASE("light sleep and frequency switching", "[deepsleep]") } } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -//IDF-5131 static void do_deep_sleep(void) { esp_sleep_enable_timer_wakeup(100000); @@ -275,6 +271,7 @@ TEST_CASE_MULTIPLE_STAGES("enter deep sleep after abort", "[deepsleep][reset=abo check_abort_reset_and_sleep, check_sleep_reset); +#if SOC_RTC_FAST_MEM_SUPPORTED static RTC_DATA_ATTR uint32_t s_wake_stub_var; static RTC_IRAM_ATTR void wake_stub(void) @@ -300,12 +297,10 @@ static void check_wake_stub(void) #endif } - TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub", "[deepsleep][reset=DEEPSLEEP_RESET]", prepare_wake_stub, check_wake_stub); - -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) +#endif // SOC_RTC_FAST_MEM_SUPPORTED #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP @@ -374,9 +369,7 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub from stack in RTC RAM", "[dee #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED - -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -//IDF-5131 +#if SOC_PM_SUPPORT_EXT_WAKEUP TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]") { ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); @@ -430,8 +423,7 @@ TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 low)", "[deepsleep][igno ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW)); esp_deep_sleep_start(); } - -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) +#endif // SOC_PM_SUPPORT_EXT_WAKEUP __attribute__((unused)) static float get_time_ms(void) { @@ -528,11 +520,30 @@ TEST_CASE("disable source trigger behavior", "[deepsleep]") #endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -//IDF-5131 -static RTC_DATA_ATTR struct timeval start; static void trigger_deepsleep(void) { + struct timeval start; + + // Use NVS instead of RTC mem to store the start time of deep sleep + // Beacuse not all esp chips support RTC mem(such as esp32c2) + // 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("Done\n"); + } + printf("Trigger deep sleep. Waiting for 10 sec ...\n"); // Simulate the dispersion of the calibration coefficients at start-up. @@ -545,6 +556,14 @@ 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)); + nvs_close(nvs_handle); + // Deinit NVS to prevent Unity from complaining "The test leaked too much memory" + ESP_ERROR_CHECK(nvs_flash_deinit()); + esp_sleep_enable_timer_wakeup(1000); // In function esp_deep_sleep_start() uses function esp_sync_timekeeping_timers() // to prevent a negative time after wake up. @@ -553,11 +572,39 @@ static void trigger_deepsleep(void) static void check_time_deepsleep(void) { - struct timeval stop; + struct timeval start, stop; + + // 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("Done\n"); + } + + // 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)); + nvs_close(nvs_handle); + // Deinit NVS to prevent Unity from complaining "The test leaked too much memory" + ESP_ERROR_CHECK(nvs_flash_deinit()); + + // Reset must be caused by deep sleep soc_reset_reason_t reason = esp_rom_get_reset_reason(0); TEST_ASSERT(reason == RESET_REASON_CORE_DEEP_SLEEP); - gettimeofday(&stop, NULL); + // Time dt_ms must in any case be positive. + gettimeofday(&stop, NULL); int dt_ms = (stop.tv_sec - start.tv_sec) * 1000 + (stop.tv_usec - start.tv_usec) / 1000; printf("delta time = %d \n", dt_ms); TEST_ASSERT_MESSAGE(dt_ms > 0, "Time in deep sleep is negative"); @@ -589,4 +636,3 @@ TEST_CASE("wake up using GPIO (2 or 4 low)", "[deepsleep][ignore]") esp_deep_sleep_start(); } #endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) diff --git a/components/esp_system/test_apps/rtc_8md256/main/test_rtc_8md256.c b/components/esp_system/test_apps/rtc_8md256/main/test_rtc_8md256.c index 902f8423bd..3831015833 100644 --- a/components/esp_system/test_apps/rtc_8md256/main/test_rtc_8md256.c +++ b/components/esp_system/test_apps/rtc_8md256/main/test_rtc_8md256.c @@ -16,9 +16,6 @@ #include "soc/soc_caps.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -//IDF-5131 - static const char TAG[] = "rtc_8m"; static void test_deepsleep(bool force_rtc_periph) @@ -40,7 +37,6 @@ TEST_CASE("Can use 8MD256 as RTC clock source in deepsleep", "[pm]") { test_deepsleep(false); } -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) static void test_lightsleep(bool force_rtc_periph) { diff --git a/components/esp_system/test_apps/rtc_8md256/pytest_rtc_8md256.py b/components/esp_system/test_apps/rtc_8md256/pytest_rtc_8md256.py index 8410d9a5a5..a19fa858e2 100644 --- a/components/esp_system/test_apps/rtc_8md256/pytest_rtc_8md256.py +++ b/components/esp_system/test_apps/rtc_8md256/pytest_rtc_8md256.py @@ -19,11 +19,11 @@ def deepsleep_test(dut: Dut, case_name: str) -> None: dut.expect(r'rst:.*\(%s\)' % reset_reason, timeout=10) -# IDF-5131 @pytest.mark.esp32 @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c3 +@pytest.mark.esp32c2 @pytest.mark.generic def test_rtc_8md256_deepsleep(dut: Dut) -> None: deepsleep_test(dut, '"Can use 8MD256 as RTC clock source in deepsleep"') diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index e1d33c807b..b55c9caec5 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -90,12 +90,6 @@ examples/system/ipc/ipc_isr: temporary: true reason: the other targets are not tested yet -examples/system/light_sleep: - disable: - - if: IDF_TARGET == "esp32c2" - temporary: true - reason: target esp32c2 is not supported yet - examples/system/ota/advanced_https_ota: disable_test: - if: IDF_TARGET == "esp32c2" diff --git a/examples/system/light_sleep/README.md b/examples/system/light_sleep/README.md index 1a24c4ebce..94d57c3236 100644 --- a/examples/system/light_sleep/README.md +++ b/examples/system/light_sleep/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | # Light Sleep Example diff --git a/examples/system/light_sleep/main/light_sleep_example_main.c b/examples/system/light_sleep/main/light_sleep_example_main.c index fccb36883f..ebd6047533 100644 --- a/examples/system/light_sleep/main/light_sleep_example_main.c +++ b/examples/system/light_sleep/main/light_sleep_example_main.c @@ -54,8 +54,14 @@ static void light_sleep_task(void *args) wakeup_reason = "other"; break; } +#if CONFIG_NEWLIB_NANO_FORMAT + /* printf in newlib-nano does not support %ll format, causing example test fail */ + printf("Returned from light sleep, reason: %s, t=%d ms, slept for %d ms\n", + wakeup_reason, (int) (t_after_us / 1000), (int) ((t_after_us - t_before_us) / 1000)); +#else printf("Returned from light sleep, reason: %s, t=%lld ms, slept for %lld ms\n", wakeup_reason, t_after_us / 1000, (t_after_us - t_before_us) / 1000); +#endif if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_GPIO) { /* Waiting for the gpio inactive, or the chip will continously trigger wakeup*/ example_wait_gpio_inactive(); diff --git a/examples/system/light_sleep/pytest_light_sleep.py b/examples/system/light_sleep/pytest_light_sleep.py index 4b0fc8c9a7..bbdbad0f92 100644 --- a/examples/system/light_sleep/pytest_light_sleep.py +++ b/examples/system/light_sleep/pytest_light_sleep.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging @@ -8,11 +8,11 @@ import pytest from pytest_embedded import Dut -# IDF-5053 @pytest.mark.esp32 @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c3 +@pytest.mark.esp32c2 @pytest.mark.generic def test_light_sleep(dut: Dut) -> None: From ac47b093f6274e78153d05626a6f2f4cf0aec1b6 Mon Sep 17 00:00:00 2001 From: jingli Date: Thu, 2 Feb 2023 20:41:11 +0800 Subject: [PATCH 4/5] esp32c2/rtc: fix 8md256 as rtc slow clk not work properly during deep sleep --- components/esp_hw_support/port/esp32c2/rtc_sleep.c | 2 +- components/soc/esp32c2/include/soc/rtc.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/port/esp32c2/rtc_sleep.c b/components/esp_hw_support/port/esp32c2/rtc_sleep.c index 74a7f135e4..7b1030c6d4 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c2/rtc_sleep.c @@ -72,7 +72,7 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_ out_config->dbg_atten_monitor = RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT; out_config->bias_sleep_monitor = RTC_CNTL_BIASSLP_MONITOR_DEFAULT; - out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT; + out_config->dbg_atten_slp = !(sleep_flags & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP : RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT; out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT; out_config->pd_cur_monitor = RTC_CNTL_PD_CUR_MONITOR_DEFAULT; out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT; diff --git a/components/soc/esp32c2/include/soc/rtc.h b/components/soc/esp32c2/include/soc/rtc.h index 1725ac3dcb..a46887711c 100644 --- a/components/soc/esp32c2/include/soc/rtc.h +++ b/components/soc/esp32c2/include/soc/rtc.h @@ -104,6 +104,7 @@ set sleep_init default param #define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT 5 #define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP 0 #define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT 15 +#define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP 0 #define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT 0 #define RTC_CNTL_BIASSLP_MONITOR_DEFAULT 0 #define RTC_CNTL_BIASSLP_SLEEP_ON 0 From 99c6be712dfe926f22d0a5c8694c7ad92c986881 Mon Sep 17 00:00:00 2001 From: jingli Date: Mon, 13 Feb 2023 17:01:13 +0800 Subject: [PATCH 5/5] ci: fix ci error --- .gitlab/ci/target-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 2262bc30c6..04dacd9f4a 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -990,7 +990,7 @@ UT_S2_SDSPI: UT_C2: extends: .unit_test_esp32c2_template - parallel: 22 + parallel: 23 tags: - ESP32C2_IDF - UT_T1_1