test_sleep.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. #include "unity.h"
  2. #include <sys/time.h>
  3. #include <sys/param.h>
  4. #include "esp_sleep.h"
  5. #include "esp_clk.h"
  6. #include "driver/rtc_io.h"
  7. #include "soc/gpio_reg.h"
  8. #include "soc/rtc.h"
  9. #include "soc/uart_reg.h"
  10. #include "rom/uart.h"
  11. #include "freertos/FreeRTOS.h"
  12. #include "freertos/task.h"
  13. #include "freertos/semphr.h"
  14. #include "soc/rtc.h" // for wakeup trigger defines
  15. #include "soc/rtc_cntl_reg.h" // for read rtc registers directly (cause)
  16. #include "soc/soc.h" // for direct register read macros
  17. #include "rom/rtc.h"
  18. #include "esp_newlib.h"
  19. #include "test_utils.h"
  20. #include "sdkconfig.h"
  21. #define ESP_EXT0_WAKEUP_LEVEL_LOW 0
  22. #define ESP_EXT0_WAKEUP_LEVEL_HIGH 1
  23. static struct timeval tv_start, tv_stop;
  24. #ifndef CONFIG_FREERTOS_UNICORE
  25. static void deep_sleep_task(void *arg)
  26. {
  27. esp_deep_sleep_start();
  28. }
  29. static void do_deep_sleep_from_app_cpu()
  30. {
  31. xTaskCreatePinnedToCore(&deep_sleep_task, "ds", 2048, NULL, 5, NULL, 1);
  32. // keep running some non-IRAM code
  33. vTaskSuspendAll();
  34. while (true) {
  35. ;
  36. }
  37. }
  38. #endif
  39. TEST_CASE("wake up from deep sleep using timer", "[deepsleep][reset=DEEPSLEEP_RESET]")
  40. {
  41. esp_sleep_enable_timer_wakeup(2000000);
  42. esp_deep_sleep_start();
  43. }
  44. TEST_CASE("light sleep followed by deep sleep", "[deepsleep][reset=DEEPSLEEP_RESET]")
  45. {
  46. esp_sleep_enable_timer_wakeup(1000000);
  47. esp_light_sleep_start();
  48. esp_deep_sleep_start();
  49. }
  50. TEST_CASE("wake up from light sleep using timer", "[deepsleep]")
  51. {
  52. esp_sleep_enable_timer_wakeup(2000000);
  53. struct timeval tv_start, tv_stop;
  54. gettimeofday(&tv_start, NULL);
  55. esp_light_sleep_start();
  56. gettimeofday(&tv_stop, NULL);
  57. float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
  58. (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
  59. TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
  60. }
  61. static void test_light_sleep(void* arg)
  62. {
  63. vTaskDelay(2);
  64. for (int i = 0; i < 1000; ++i) {
  65. printf("%d %d\n", xPortGetCoreID(), i);
  66. fflush(stdout);
  67. esp_light_sleep_start();
  68. }
  69. SemaphoreHandle_t done = (SemaphoreHandle_t) arg;
  70. xSemaphoreGive(done);
  71. vTaskDelete(NULL);
  72. }
  73. TEST_CASE("light sleep stress test", "[deepsleep]")
  74. {
  75. SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
  76. esp_sleep_enable_timer_wakeup(1000);
  77. xTaskCreatePinnedToCore(&test_light_sleep, "ls0", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
  78. #if portNUM_PROCESSORS == 2
  79. xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
  80. #endif
  81. xSemaphoreTake(done, portMAX_DELAY);
  82. #if portNUM_PROCESSORS == 2
  83. xSemaphoreTake(done, portMAX_DELAY);
  84. #endif
  85. vSemaphoreDelete(done);
  86. }
  87. TEST_CASE("light sleep stress test with periodic esp_timer", "[deepsleep]")
  88. {
  89. void timer_func(void* arg)
  90. {
  91. ets_delay_us(50);
  92. }
  93. SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
  94. esp_sleep_enable_timer_wakeup(1000);
  95. esp_timer_handle_t timer;
  96. esp_timer_create_args_t config = {
  97. .callback = &timer_func,
  98. };
  99. TEST_ESP_OK(esp_timer_create(&config, &timer));
  100. esp_timer_start_periodic(timer, 500);
  101. xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
  102. #if portNUM_PROCESSORS == 2
  103. xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
  104. #endif
  105. xSemaphoreTake(done, portMAX_DELAY);
  106. #if portNUM_PROCESSORS == 2
  107. xSemaphoreTake(done, portMAX_DELAY);
  108. #endif
  109. vSemaphoreDelete(done);
  110. esp_timer_stop(timer);
  111. esp_timer_delete(timer);
  112. }
  113. #ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
  114. #define MAX_SLEEP_TIME_ERROR_US 200
  115. #else
  116. #define MAX_SLEEP_TIME_ERROR_US 100
  117. #endif
  118. TEST_CASE("light sleep duration is correct", "[deepsleep][ignore]")
  119. {
  120. // don't power down XTAL — powering it up takes different time on
  121. // different boards
  122. esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
  123. // run one light sleep without checking timing, to warm up the cache
  124. esp_sleep_enable_timer_wakeup(1000);
  125. esp_light_sleep_start();
  126. const int sleep_intervals_ms[] = {
  127. 1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 15,
  128. 20, 25, 50, 100, 200, 500,
  129. };
  130. const int sleep_intervals_count = sizeof(sleep_intervals_ms)/sizeof(sleep_intervals_ms[0]);
  131. for (int i = 0; i < sleep_intervals_count; ++i) {
  132. uint64_t sleep_time = sleep_intervals_ms[i] * 1000;
  133. esp_sleep_enable_timer_wakeup(sleep_time);
  134. for (int repeat = 0; repeat < 5; ++repeat) {
  135. uint64_t start = esp_clk_rtc_time();
  136. int64_t start_hs = esp_timer_get_time();
  137. esp_light_sleep_start();
  138. int64_t stop_hs = esp_timer_get_time();
  139. uint64_t stop = esp_clk_rtc_time();
  140. int diff_us = (int) (stop - start);
  141. int diff_hs_us = (int) (stop_hs - start_hs);
  142. printf("%lld %d\n", sleep_time, (int) (diff_us - sleep_time));
  143. int32_t threshold = MAX(sleep_time / 100, MAX_SLEEP_TIME_ERROR_US);
  144. TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_us);
  145. TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_hs_us);
  146. fflush(stdout);
  147. }
  148. vTaskDelay(10/portTICK_PERIOD_MS);
  149. }
  150. }
  151. TEST_CASE("light sleep and frequency switching", "[deepsleep]")
  152. {
  153. #ifndef CONFIG_PM_ENABLE
  154. const int uart_clk_freq = REF_CLK_FREQ;
  155. CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON);
  156. uart_div_modify(CONFIG_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_CONSOLE_UART_BAUDRATE);
  157. #endif
  158. rtc_cpu_freq_config_t config_xtal, config_default;
  159. rtc_clk_cpu_freq_get_config(&config_default);
  160. rtc_clk_cpu_freq_mhz_to_config((int) rtc_clk_xtal_freq_get(), &config_xtal);
  161. esp_sleep_enable_timer_wakeup(1000);
  162. for (int i = 0; i < 1000; ++i) {
  163. if (i % 2 == 0) {
  164. rtc_clk_cpu_freq_set_config_fast(&config_xtal);
  165. } else {
  166. rtc_clk_cpu_freq_set_config_fast(&config_default);
  167. }
  168. printf("%d\n", i);
  169. fflush(stdout);
  170. esp_light_sleep_start();
  171. }
  172. }
  173. #ifndef CONFIG_FREERTOS_UNICORE
  174. TEST_CASE("enter deep sleep on APP CPU and wake up using timer", "[deepsleep][reset=DEEPSLEEP_RESET]")
  175. {
  176. esp_sleep_enable_timer_wakeup(2000000);
  177. do_deep_sleep_from_app_cpu();
  178. }
  179. #endif
  180. static void do_deep_sleep()
  181. {
  182. esp_sleep_enable_timer_wakeup(100000);
  183. esp_deep_sleep_start();
  184. }
  185. static void check_sleep_reset_and_sleep()
  186. {
  187. TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
  188. esp_sleep_enable_timer_wakeup(100000);
  189. esp_deep_sleep_start();
  190. }
  191. static void check_sleep_reset()
  192. {
  193. TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
  194. }
  195. TEST_CASE_MULTIPLE_STAGES("enter deep sleep more than once", "[deepsleep][reset=DEEPSLEEP_RESET,DEEPSLEEP_RESET,DEEPSLEEP_RESET]",
  196. do_deep_sleep,
  197. check_sleep_reset_and_sleep,
  198. check_sleep_reset_and_sleep,
  199. check_sleep_reset);
  200. static void do_abort()
  201. {
  202. abort();
  203. }
  204. static void check_abort_reset_and_sleep()
  205. {
  206. TEST_ASSERT_EQUAL(ESP_RST_PANIC, esp_reset_reason());
  207. esp_sleep_enable_timer_wakeup(100000);
  208. esp_deep_sleep_start();
  209. }
  210. TEST_CASE_MULTIPLE_STAGES("enter deep sleep after abort", "[deepsleep][reset=abort,SW_CPU_RESET,DEEPSLEEP_RESET]",
  211. do_abort,
  212. check_abort_reset_and_sleep,
  213. check_sleep_reset);
  214. static RTC_DATA_ATTR uint32_t s_wake_stub_var;
  215. static RTC_IRAM_ATTR void wake_stub()
  216. {
  217. esp_default_wake_deep_sleep();
  218. s_wake_stub_var = (uint32_t) &wake_stub;
  219. }
  220. static void prepare_wake_stub()
  221. {
  222. esp_set_deep_sleep_wake_stub(&wake_stub);
  223. esp_sleep_enable_timer_wakeup(100000);
  224. esp_deep_sleep_start();
  225. }
  226. static void check_wake_stub()
  227. {
  228. TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
  229. TEST_ASSERT_EQUAL_HEX32((uint32_t) &wake_stub, s_wake_stub_var);
  230. /* ROM code clears wake stub entry address */
  231. TEST_ASSERT_NULL(esp_get_deep_sleep_wake_stub());
  232. }
  233. TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub", "[deepsleep][reset=DEEPSLEEP_RESET]",
  234. prepare_wake_stub,
  235. check_wake_stub);
  236. TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]")
  237. {
  238. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  239. ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13));
  240. ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13));
  241. ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
  242. esp_deep_sleep_start();
  243. }
  244. TEST_CASE("wake up using ext0 (13 low)", "[deepsleep][ignore]")
  245. {
  246. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  247. ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
  248. ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
  249. ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_LOW));
  250. esp_deep_sleep_start();
  251. }
  252. TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 high)", "[deepsleep][ignore]")
  253. {
  254. // This test needs external pulldown
  255. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  256. ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH));
  257. esp_deep_sleep_start();
  258. }
  259. TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 low)", "[deepsleep][ignore]")
  260. {
  261. // This test needs external pullup
  262. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  263. ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW));
  264. esp_deep_sleep_start();
  265. }
  266. TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 high)", "[deepsleep][ignore]")
  267. {
  268. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  269. ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13));
  270. ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13));
  271. ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
  272. ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH));
  273. esp_deep_sleep_start();
  274. }
  275. TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 low)", "[deepsleep][ignore]")
  276. {
  277. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  278. ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
  279. ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
  280. ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
  281. ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW));
  282. esp_deep_sleep_start();
  283. }
  284. static float get_time_ms(void)
  285. {
  286. gettimeofday(&tv_stop, NULL);
  287. float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
  288. (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
  289. return fabs(dt);
  290. }
  291. static uint32_t get_cause()
  292. {
  293. uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, \
  294. RTC_CNTL_WAKEUP_CAUSE);
  295. return wakeup_cause;
  296. }
  297. // This test case verifies deactivation of trigger for wake up sources
  298. TEST_CASE("disable source trigger behavior", "[deepsleep]")
  299. {
  300. float dt = 0;
  301. printf("Setup timer and ext0 to wake up immediately from GPIO_13 \n");
  302. // Setup ext0 configuration to wake up almost immediately
  303. // The wakeup time is proportional to input capacitance * pullup resistance
  304. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  305. ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
  306. ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
  307. ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
  308. // Setup timer to wakeup with timeout
  309. esp_sleep_enable_timer_wakeup(2000000);
  310. // Save start time
  311. gettimeofday(&tv_start, NULL);
  312. esp_light_sleep_start();
  313. dt = get_time_ms();
  314. printf("Ext0 sleep time = %d \n", (int) dt);
  315. // Check wakeup from Ext0 using time measurement because wakeup cause is
  316. // not available in light sleep mode
  317. TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
  318. TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
  319. // Disable Ext0 source. Timer source should be triggered
  320. ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0));
  321. printf("Disable ext0 trigger and leave timer active.\n");
  322. gettimeofday(&tv_start, NULL);
  323. esp_light_sleep_start();
  324. dt = get_time_ms();
  325. printf("Timer sleep time = %d \n", (int) dt);
  326. TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
  327. // Additionally check wakeup cause
  328. TEST_ASSERT((get_cause() & RTC_TIMER_TRIG_EN) != 0);
  329. // Disable timer source.
  330. ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER));
  331. // Setup ext0 configuration to wake up immediately
  332. ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
  333. ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
  334. ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
  335. ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
  336. printf("Disable timer trigger to wake up from ext0 source.\n");
  337. gettimeofday(&tv_start, NULL);
  338. esp_light_sleep_start();
  339. dt = get_time_ms();
  340. printf("Ext0 sleep time = %d \n", (int) dt);
  341. TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
  342. TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
  343. // Check error message when source is already disabled
  344. esp_err_t err_code = esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
  345. TEST_ASSERT(err_code == ESP_ERR_INVALID_STATE);
  346. }
  347. static RTC_DATA_ATTR struct timeval start;
  348. static void trigger_deepsleep(void)
  349. {
  350. printf("Trigger deep sleep. Waiting for 10 sec ...\n");
  351. // Simulate the dispersion of the calibration coefficients at start-up.
  352. // Corrupt the calibration factor.
  353. esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() / 2);
  354. esp_set_time_from_rtc();
  355. // Delay for time error accumulation.
  356. vTaskDelay(10000/portTICK_RATE_MS);
  357. // Save start time. Deep sleep.
  358. gettimeofday(&start, NULL);
  359. esp_sleep_enable_timer_wakeup(1000);
  360. // In function esp_deep_sleep_start() uses function esp_sync_counters_rtc_and_frc()
  361. // to prevent a negative time after wake up.
  362. esp_deep_sleep_start();
  363. }
  364. static void check_time_deepsleep(void)
  365. {
  366. struct timeval stop;
  367. RESET_REASON reason = rtc_get_reset_reason(0);
  368. TEST_ASSERT(reason == DEEPSLEEP_RESET);
  369. gettimeofday(&stop, NULL);
  370. // Time dt_ms must in any case be positive.
  371. int dt_ms = (stop.tv_sec - start.tv_sec) * 1000 + (stop.tv_usec - start.tv_usec) / 1000;
  372. printf("delta time = %d \n", dt_ms);
  373. TEST_ASSERT_MESSAGE(dt_ms > 0, "Time in deep sleep is negative");
  374. }
  375. TEST_CASE_MULTIPLE_STAGES("check a time after wakeup from deep sleep", "[deepsleep][reset=DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep);