1 /*
2 * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "unity.h"
8 #include <sys/time.h>
9 #include <sys/param.h>
10 #include "esp_sleep.h"
11 #include "driver/rtc_io.h"
12 #include "freertos/FreeRTOS.h"
13 #include "freertos/task.h"
14 #include "freertos/semphr.h"
15 #include "soc/gpio_periph.h"
16 #include "hal/uart_types.h"
17 #include "hal/uart_ll.h"
18 #include "soc/rtc.h" // for wakeup trigger defines
19 #include "soc/rtc_periph.h" // for read rtc registers directly (cause)
20 #include "soc/soc.h" // for direct register read macros
21 #include "hal/rtc_cntl_ll.h"
22 #include "esp_newlib.h"
23 #include "test_utils.h"
24 #include "sdkconfig.h"
25 #include "esp_rom_uart.h"
26 #include "esp_rom_sys.h"
27 #include "esp_timer.h"
28
29 #if CONFIG_IDF_TARGET_ESP32
30 #include "esp32/clk.h"
31 #elif CONFIG_IDF_TARGET_ESP32S2
32 #include "esp32s2/clk.h"
33 #elif CONFIG_IDF_TARGET_ESP32S3
34 #include "esp32s3/clk.h"
35 #elif CONFIG_IDF_TARGET_ESP32C3
36 #include "esp32c3/clk.h"
37 #elif CONFIG_IDF_TARGET_ESP32H2
38 #include "esp32h2/clk.h"
39 #endif
40
41 #define ESP_EXT0_WAKEUP_LEVEL_LOW 0
42 #define ESP_EXT0_WAKEUP_LEVEL_HIGH 1
43
44 __attribute__((unused)) static struct timeval tv_start, tv_stop;
45
46 #ifndef CONFIG_FREERTOS_UNICORE
deep_sleep_task(void * arg)47 static void deep_sleep_task(void *arg)
48 {
49 esp_deep_sleep_start();
50 }
51
do_deep_sleep_from_app_cpu(void)52 static void do_deep_sleep_from_app_cpu(void)
53 {
54 xTaskCreatePinnedToCore(&deep_sleep_task, "ds", 2048, NULL, 5, NULL, 1);
55
56 // keep running some non-IRAM code
57 vTaskSuspendAll();
58
59 while (true) {
60 ;
61 }
62 }
63 #endif
64
65 TEST_CASE("wake up from deep sleep using timer", "[deepsleep][reset=DEEPSLEEP_RESET]")
66 {
67 esp_sleep_enable_timer_wakeup(2000000);
68 esp_deep_sleep_start();
69 }
70
71 TEST_CASE("light sleep followed by deep sleep", "[deepsleep][reset=DEEPSLEEP_RESET]")
72 {
73 esp_sleep_enable_timer_wakeup(1000000);
74 esp_light_sleep_start();
75 esp_deep_sleep_start();
76 }
77
78 TEST_CASE("wake up from light sleep using timer", "[deepsleep]")
79 {
80 esp_sleep_enable_timer_wakeup(2000000);
81 struct timeval tv_start, tv_stop;
82 gettimeofday(&tv_start, NULL);
83 esp_light_sleep_start();
84 gettimeofday(&tv_stop, NULL);
85 float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
86 (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
87 TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
88 }
89
test_light_sleep(void * arg)90 static void test_light_sleep(void* arg)
91 {
92 vTaskDelay(2);
93 for (int i = 0; i < 1000; ++i) {
94 printf("%d %d\n", xPortGetCoreID(), i);
95 fflush(stdout);
96 esp_light_sleep_start();
97 }
98 SemaphoreHandle_t done = (SemaphoreHandle_t) arg;
99 xSemaphoreGive(done);
100 vTaskDelete(NULL);
101 }
102
103 TEST_CASE("light sleep stress test", "[deepsleep]")
104 {
105 SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
106 esp_sleep_enable_timer_wakeup(1000);
107 xTaskCreatePinnedToCore(&test_light_sleep, "ls0", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
108 #if portNUM_PROCESSORS == 2
109 xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
110 #endif
111 xSemaphoreTake(done, portMAX_DELAY);
112 #if portNUM_PROCESSORS == 2
113 xSemaphoreTake(done, portMAX_DELAY);
114 #endif
115 vSemaphoreDelete(done);
116 }
117
timer_func(void * arg)118 static void timer_func(void* arg)
119 {
120 esp_rom_delay_us(50);
121 }
122
123 TEST_CASE("light sleep stress test with periodic esp_timer", "[deepsleep]")
124 {
125 SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
126 esp_sleep_enable_timer_wakeup(1000);
127 esp_timer_handle_t timer;
128 esp_timer_create_args_t config = {
129 .callback = &timer_func,
130 };
131 TEST_ESP_OK(esp_timer_create(&config, &timer));
132 esp_timer_start_periodic(timer, 500);
133 xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
134 #if portNUM_PROCESSORS == 2
135 xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
136 #endif
137 xSemaphoreTake(done, portMAX_DELAY);
138 #if portNUM_PROCESSORS == 2
139 xSemaphoreTake(done, portMAX_DELAY);
140 #endif
141 vSemaphoreDelete(done);
142 esp_timer_stop(timer);
143 esp_timer_delete(timer);
144 }
145
146
147 #if defined(CONFIG_ESP_SYSTEM_RTC_EXT_XTAL)
148 #define MAX_SLEEP_TIME_ERROR_US 200
149 #else
150 #define MAX_SLEEP_TIME_ERROR_US 100
151 #endif
152
153
154 TEST_CASE("light sleep duration is correct", "[deepsleep][ignore]")
155 {
156 // don't power down XTAL — powering it up takes different time on
157 // different boards
158 esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
159
160 // run one light sleep without checking timing, to warm up the cache
161 esp_sleep_enable_timer_wakeup(1000);
162 esp_light_sleep_start();
163
164 const int sleep_intervals_ms[] = {
165 1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 15,
166 20, 25, 50, 100, 200, 500,
167 };
168
169 const int sleep_intervals_count = sizeof(sleep_intervals_ms)/sizeof(sleep_intervals_ms[0]);
170 for (int i = 0; i < sleep_intervals_count; ++i) {
171 uint64_t sleep_time = sleep_intervals_ms[i] * 1000;
172 esp_sleep_enable_timer_wakeup(sleep_time);
173 for (int repeat = 0; repeat < 5; ++repeat) {
174 uint64_t start = esp_clk_rtc_time();
175 int64_t start_hs = esp_timer_get_time();
176 esp_light_sleep_start();
177 int64_t stop_hs = esp_timer_get_time();
178 uint64_t stop = esp_clk_rtc_time();
179
180 int diff_us = (int) (stop - start);
181 int diff_hs_us = (int) (stop_hs - start_hs);
182 printf("%lld %d\n", sleep_time, (int) (diff_us - sleep_time));
183 int32_t threshold = MAX(sleep_time / 100, MAX_SLEEP_TIME_ERROR_US);
184 TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_us);
185 TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_hs_us);
186 fflush(stdout);
187 }
188
189 vTaskDelay(10/portTICK_PERIOD_MS);
190 }
191 }
192
193
194 TEST_CASE("light sleep and frequency switching", "[deepsleep]")
195 {
196 #ifndef CONFIG_PM_ENABLE
197 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
198 uart_sclk_t clk_source = UART_SCLK_REF_TICK;
199 #else
200 uart_sclk_t clk_source = UART_SCLK_XTAL;
201 #endif
202 uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), clk_source);
203 uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE);
204 #endif
205
206 rtc_cpu_freq_config_t config_xtal, config_default;
207 rtc_clk_cpu_freq_get_config(&config_default);
208 rtc_clk_cpu_freq_mhz_to_config((int) rtc_clk_xtal_freq_get(), &config_xtal);
209
210 esp_sleep_enable_timer_wakeup(1000);
211 for (int i = 0; i < 1000; ++i) {
212 if (i % 2 == 0) {
213 rtc_clk_cpu_freq_set_config_fast(&config_xtal);
214 } else {
215 rtc_clk_cpu_freq_set_config_fast(&config_default);
216 }
217 printf("%d\n", i);
218 fflush(stdout);
219 esp_light_sleep_start();
220 }
221 }
222
223 #ifndef CONFIG_FREERTOS_UNICORE
224 TEST_CASE("enter deep sleep on APP CPU and wake up using timer", "[deepsleep][reset=DEEPSLEEP_RESET]")
225 {
226 esp_sleep_enable_timer_wakeup(2000000);
227 do_deep_sleep_from_app_cpu();
228 }
229 #endif
230
do_deep_sleep(void)231 static void do_deep_sleep(void)
232 {
233 esp_sleep_enable_timer_wakeup(100000);
234 esp_deep_sleep_start();
235 }
236
check_sleep_reset_and_sleep(void)237 static void check_sleep_reset_and_sleep(void)
238 {
239 TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
240 esp_sleep_enable_timer_wakeup(100000);
241 esp_deep_sleep_start();
242 }
243
check_sleep_reset(void)244 static void check_sleep_reset(void)
245 {
246 TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
247 }
248
249 TEST_CASE_MULTIPLE_STAGES("enter deep sleep more than once", "[deepsleep][reset=DEEPSLEEP_RESET,DEEPSLEEP_RESET,DEEPSLEEP_RESET]",
250 do_deep_sleep,
251 check_sleep_reset_and_sleep,
252 check_sleep_reset_and_sleep,
253 check_sleep_reset);
254
do_abort(void)255 static void do_abort(void)
256 {
257 abort();
258 }
259
check_abort_reset_and_sleep(void)260 static void check_abort_reset_and_sleep(void)
261 {
262 TEST_ASSERT_EQUAL(ESP_RST_PANIC, esp_reset_reason());
263 esp_sleep_enable_timer_wakeup(100000);
264 esp_deep_sleep_start();
265 }
266
267 TEST_CASE_MULTIPLE_STAGES("enter deep sleep after abort", "[deepsleep][reset=abort,SW_CPU_RESET,DEEPSLEEP_RESET]",
268 do_abort,
269 check_abort_reset_and_sleep,
270 check_sleep_reset);
271
272 static RTC_DATA_ATTR uint32_t s_wake_stub_var;
273
wake_stub(void)274 static RTC_IRAM_ATTR void wake_stub(void)
275 {
276 esp_default_wake_deep_sleep();
277 s_wake_stub_var = (uint32_t) &wake_stub;
278 }
279
prepare_wake_stub(void)280 static void prepare_wake_stub(void)
281 {
282 esp_set_deep_sleep_wake_stub(&wake_stub);
283 esp_sleep_enable_timer_wakeup(100000);
284 esp_deep_sleep_start();
285 }
286
check_wake_stub(void)287 static void check_wake_stub(void)
288 {
289 TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
290 TEST_ASSERT_EQUAL_HEX32((uint32_t) &wake_stub, s_wake_stub_var);
291 #if !CONFIG_IDF_TARGET_ESP32S3
292 /* ROM code clears wake stub entry address */
293 TEST_ASSERT_NULL(esp_get_deep_sleep_wake_stub());
294 #endif
295 }
296
297 TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub", "[deepsleep][reset=DEEPSLEEP_RESET]",
298 prepare_wake_stub,
299 check_wake_stub);
300
301
302 #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
303
304 /* Version of prepare_wake_stub() that sets up the deep sleep call while running
305 from RTC memory as stack, with a high frequency timer also writing RTC FAST
306 memory.
307
308 This is important because the ROM code (ESP32 & ESP32-S2) requires software
309 trigger a CRC calculation (done in hardware) for the entire RTC FAST memory
310 before going to deep sleep and if it's invalid then the stub is not
311 run. Also, while the CRC is being calculated the RTC FAST memory is not
312 accesible by the CPU (reads all zeros).
313 */
314
increment_rtc_memory_cb(void * arg)315 static void increment_rtc_memory_cb(void *arg)
316 {
317 static volatile RTC_FAST_ATTR unsigned counter;
318 counter++;
319 }
320
prepare_wake_stub_from_rtc(void)321 static void prepare_wake_stub_from_rtc(void)
322 {
323 /* RTC memory can be used as heap, however there is no API call that returns this as
324 a memory capability (as it's an implementation detail). So to test this we need to allocate
325 the stack statically.
326 */
327 #define STACK_SIZE 1500
328 #if CONFIG_IDF_TARGET_ESP32S3
329 uint8_t *sleep_stack = (uint8_t *)heap_caps_malloc(STACK_SIZE, MALLOC_CAP_RTCRAM);
330 TEST_ASSERT((uint32_t)sleep_stack >= SOC_RTC_DRAM_LOW && (uint32_t)sleep_stack < SOC_RTC_DRAM_HIGH);
331 #else
332 static RTC_FAST_ATTR uint8_t sleep_stack[STACK_SIZE];
333 #endif
334 static RTC_FAST_ATTR StaticTask_t sleep_task;
335
336 /* normally BSS like sleep_stack will be cleared on reset, but RTC memory is not cleared on
337 * wake from deep sleep. So to ensure unused stack is different if test is re-run without a full reset,
338 * fill with some random bytes
339 */
340 esp_fill_random(sleep_stack, STACK_SIZE);
341
342 /* to make things extra sure, start a periodic timer to write to RTC FAST RAM at high frequency */
343 const esp_timer_create_args_t timer_args = {
344 .callback = increment_rtc_memory_cb,
345 .arg = NULL,
346 .dispatch_method = ESP_TIMER_TASK,
347 .name = "Write RTC MEM"
348 };
349 esp_timer_handle_t timer;
350 ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer) );
351 ESP_ERROR_CHECK( esp_timer_start_periodic(timer, 200) );
352
353 printf("Creating test task with stack %p\n", sleep_stack);
354 TEST_ASSERT_NOT_NULL(xTaskCreateStatic( (void *)prepare_wake_stub, "sleep", STACK_SIZE, NULL,
355 UNITY_FREERTOS_PRIORITY, sleep_stack, &sleep_task));
356 vTaskDelay(1000 / portTICK_PERIOD_MS);
357 TEST_FAIL_MESSAGE("Should be asleep by now");
358 }
359
360 TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub from stack in RTC RAM", "[deepsleep][reset=DEEPSLEEP_RESET]",
361 prepare_wake_stub_from_rtc,
362 check_wake_stub);
363
364 #endif // CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
365
366 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
367
368 TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]")
369 {
370 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
371 ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13));
372 ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13));
373 ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
374 esp_deep_sleep_start();
375 }
376
377 TEST_CASE("wake up using ext0 (13 low)", "[deepsleep][ignore]")
378 {
379 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
380 ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
381 ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
382 ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_LOW));
383 esp_deep_sleep_start();
384 }
385
386 TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 high)", "[deepsleep][ignore]")
387 {
388 // This test needs external pulldown
389 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
390 ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH));
391 esp_deep_sleep_start();
392 }
393
394 TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 low)", "[deepsleep][ignore]")
395 {
396 // This test needs external pullup
397 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
398 ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW));
399 esp_deep_sleep_start();
400 }
401
402 TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 high)", "[deepsleep][ignore]")
403 {
404 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
405 ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13));
406 ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13));
407 ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
408 ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH));
409 esp_deep_sleep_start();
410 }
411
412 TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 low)", "[deepsleep][ignore]")
413 {
414 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
415 ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
416 ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
417 ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
418 ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW));
419 esp_deep_sleep_start();
420 }
421
get_time_ms(void)422 __attribute__((unused)) static float get_time_ms(void)
423 {
424 gettimeofday(&tv_stop, NULL);
425
426 float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
427 (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
428 return fabs(dt);
429 }
430
get_cause(void)431 __attribute__((unused)) static uint32_t get_cause(void)
432 {
433 uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, \
434 RTC_CNTL_WAKEUP_CAUSE);
435 return wakeup_cause;
436 }
437
438 #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
439 // Fails on S2 IDF-2903
440
441 // This test case verifies deactivation of trigger for wake up sources
442 TEST_CASE("disable source trigger behavior", "[deepsleep]")
443 {
444 float dt = 0;
445
446 printf("Setup timer and ext0 to wake up immediately from GPIO_13 \n");
447
448 // Setup ext0 configuration to wake up almost immediately
449 // The wakeup time is proportional to input capacitance * pullup resistance
450 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
451 ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
452 ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
453 ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
454
455 // Setup timer to wakeup with timeout
456 esp_sleep_enable_timer_wakeup(2000000);
457
458 // Save start time
459 gettimeofday(&tv_start, NULL);
460 esp_light_sleep_start();
461
462 dt = get_time_ms();
463 printf("Ext0 sleep time = %d \n", (int) dt);
464
465 // Check wakeup from Ext0 using time measurement because wakeup cause is
466 // not available in light sleep mode
467 TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
468
469 TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
470
471 // Disable Ext0 source. Timer source should be triggered
472 ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0));
473 printf("Disable ext0 trigger and leave timer active.\n");
474
475 gettimeofday(&tv_start, NULL);
476 esp_light_sleep_start();
477
478 dt = get_time_ms();
479 printf("Timer sleep time = %d \n", (int) dt);
480
481 TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
482
483 // Additionally check wakeup cause
484 TEST_ASSERT((get_cause() & RTC_TIMER_TRIG_EN) != 0);
485
486 // Disable timer source.
487 ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER));
488
489 // Setup ext0 configuration to wake up immediately
490 ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
491 ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
492 ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
493 ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
494
495 printf("Disable timer trigger to wake up from ext0 source.\n");
496
497 gettimeofday(&tv_start, NULL);
498 esp_light_sleep_start();
499
500 dt = get_time_ms();
501 printf("Ext0 sleep time = %d \n", (int) dt);
502
503 TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
504 TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
505
506 // Check error message when source is already disabled
507 esp_err_t err_code = esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
508 TEST_ASSERT(err_code == ESP_ERR_INVALID_STATE);
509
510 // Disable ext0 wakeup source, as this might interfere with other tests
511 ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0));
512 }
513 #endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
514
515 #endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
516
517 static RTC_DATA_ATTR struct timeval start;
trigger_deepsleep(void)518 static void trigger_deepsleep(void)
519 {
520 printf("Trigger deep sleep. Waiting for 10 sec ...\n");
521
522 // Simulate the dispersion of the calibration coefficients at start-up.
523 // Corrupt the calibration factor.
524 esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() / 2);
525 esp_set_time_from_rtc();
526
527 // Delay for time error accumulation.
528 vTaskDelay(10000/portTICK_RATE_MS);
529
530 // Save start time. Deep sleep.
531 gettimeofday(&start, NULL);
532 esp_sleep_enable_timer_wakeup(1000);
533 // In function esp_deep_sleep_start() uses function esp_sync_counters_rtc_and_frc()
534 // to prevent a negative time after wake up.
535 esp_deep_sleep_start();
536 }
537
check_time_deepsleep(void)538 static void check_time_deepsleep(void)
539 {
540 struct timeval stop;
541 soc_reset_reason_t reason = esp_rom_get_reset_reason(0);
542 TEST_ASSERT(reason == RESET_REASON_CORE_DEEP_SLEEP);
543 gettimeofday(&stop, NULL);
544 // Time dt_ms must in any case be positive.
545 int dt_ms = (stop.tv_sec - start.tv_sec) * 1000 + (stop.tv_usec - start.tv_usec) / 1000;
546 printf("delta time = %d \n", dt_ms);
547 TEST_ASSERT_MESSAGE(dt_ms > 0, "Time in deep sleep is negative");
548 }
549
550 TEST_CASE_MULTIPLE_STAGES("check a time after wakeup from deep sleep", "[deepsleep][reset=DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep);
551
552 #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
gpio_deepsleep_wakeup_config(void)553 static void gpio_deepsleep_wakeup_config(void)
554 {
555 gpio_config_t io_conf = {
556 .mode = GPIO_MODE_INPUT,
557 .pin_bit_mask = ((1ULL << 2) | (1ULL << 4))
558 };
559 ESP_ERROR_CHECK(gpio_config(&io_conf));
560 }
561
562 TEST_CASE("wake up using GPIO (2 or 4 high)", "[deepsleep][ignore]")
563 {
564 gpio_deepsleep_wakeup_config();
565 ESP_ERROR_CHECK(esp_deep_sleep_enable_gpio_wakeup(((1ULL << 2) | (1ULL << 4)) , ESP_GPIO_WAKEUP_GPIO_HIGH));
566 esp_deep_sleep_start();
567 }
568
569 TEST_CASE("wake up using GPIO (2 or 4 low)", "[deepsleep][ignore]")
570 {
571 gpio_deepsleep_wakeup_config();
572 ESP_ERROR_CHECK(esp_deep_sleep_enable_gpio_wakeup(((1ULL << 2) | (1ULL << 4)) , ESP_GPIO_WAKEUP_GPIO_LOW));
573 esp_deep_sleep_start();
574 }
575 #endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
576