1515#include "esp_private/sleep_cpu.h"
1616#include "esp_private/esp_sleep_internal.h"
1717#include "esp_private/esp_pmu.h"
18+ #if !SOC_LIGHT_SLEEP_SUPPORTED
19+ #include "esp_private/gptimer.h"
20+ #include "esp_private/sleep_retention.h"
21+ #include "hal/timer_ll.h"
22+ #include "hal/wdt_hal.h"
23+ #endif
24+
25+ #if CONFIG_GPTIMER_ISR_IRAM_SAFE
26+ #define TEST_ALARM_CALLBACK_ATTR IRAM_ATTR
27+ #else
28+ #define TEST_ALARM_CALLBACK_ATTR
29+ #endif // CONFIG_GPTIMER_ISR_IRAM_SAFE
1830
19- static bool test_gptimer_alarm_stop_callback (gptimer_handle_t timer , const gptimer_alarm_event_data_t * edata , void * user_data )
31+ static TEST_ALARM_CALLBACK_ATTR bool test_gptimer_alarm_stop_callback (gptimer_handle_t timer , const gptimer_alarm_event_data_t * edata , void * user_data )
2032{
2133 TaskHandle_t task_handle = (TaskHandle_t )user_data ;
2234 BaseType_t high_task_wakeup ;
@@ -25,6 +37,62 @@ static bool test_gptimer_alarm_stop_callback(gptimer_handle_t timer, const gptim
2537 return high_task_wakeup == pdTRUE ;
2638}
2739
40+ /**
41+ * @brief This function abstracts the behavior of performing the Backup-Reset-Restore process on the specified
42+ * Timer group and is used as a helper function to test the retention function of the driver.
43+ * If light-sleep feature is supported, this function will enter and exit a real light sleep or PD_TOP
44+ * light sleep. Otherwise, it will trigger retention by software and reset the timer module to simulate
45+ * a light-sleep in/out process to verify the driver's support for GPTimer sleep retention.
46+ *
47+ * @param timer Timer handle to be reset, created by `gptimer_new_timer()`
48+ * @param back_up_before_sleep Whether to back up GPTimer registers before sleep
49+ */
50+ static void test_gptimer_survival_after_sleep_helper (gptimer_handle_t timer , bool back_up_before_sleep )
51+ {
52+ #if SOC_LIGHT_SLEEP_SUPPORTED
53+ esp_sleep_context_t sleep_ctx ;
54+ esp_sleep_set_sleep_context (& sleep_ctx );
55+ printf ("go to light sleep for 2 seconds\r\n" );
56+ #if ESP_SLEEP_POWER_DOWN_CPU
57+ TEST_ESP_OK (sleep_cpu_configure (true));
58+ #endif
59+ TEST_ESP_OK (esp_sleep_enable_timer_wakeup (2 * 1000 * 1000 ));
60+ TEST_ESP_OK (esp_light_sleep_start ());
61+
62+ printf ("Waked up! Let's see if GPTimer driver can still work...\r\n" );
63+ #if ESP_SLEEP_POWER_DOWN_CPU
64+ TEST_ESP_OK (sleep_cpu_configure (false));
65+ #endif
66+
67+ printf ("check if the sleep happened as expected\r\n" );
68+ TEST_ASSERT_EQUAL (0 , sleep_ctx .sleep_request_result );
69+ #if SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
70+ if (back_up_before_sleep ) {
71+ // Verify that when GPTimer retention is configured and sleep is requested,
72+ // the TOP power domain should be allowed to power down.
73+ TEST_ASSERT_EQUAL (PMU_SLEEP_PD_TOP , sleep_ctx .sleep_flags & PMU_SLEEP_PD_TOP );
74+ } else {
75+ // Verify that when GPTimer retention is not configured and sleep is requested, the TOP power
76+ // domain should not be allowed to power down to ensure the peripheral context is not lost.
77+ TEST_ASSERT_EQUAL (0 , sleep_ctx .sleep_flags & PMU_SLEEP_PD_TOP );
78+ }
79+ #endif
80+ esp_sleep_set_sleep_context (NULL );
81+ #elif SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
82+ if (back_up_before_sleep ) {
83+ printf ("Back up the timer group context in use and then reset it\r\n" );
84+ sleep_retention_do_extra_retention (true);
85+
86+ int group_id ;
87+ gptimer_get_group_id (timer , & group_id );
88+ _timer_ll_reset_register (group_id );
89+
90+ printf ("Reset done! Let's restore its context and see if its driver can still work...\r\n" );
91+ sleep_retention_do_extra_retention (false);
92+ }
93+ #endif
94+ }
95+
2896/**
2997 * @brief Test the GPTimer driver can still work after light sleep
3098 *
@@ -67,28 +135,7 @@ static void test_gptimer_sleep_retention(bool back_up_before_sleep)
67135 // Note: don't enable the gptimer before going to sleep, ensure no power management lock is acquired by it
68136 TEST_ESP_OK (gptimer_disable (timer ));
69137
70- esp_sleep_context_t sleep_ctx ;
71- esp_sleep_set_sleep_context (& sleep_ctx );
72- printf ("go to light sleep for 2 seconds\r\n" );
73- #if ESP_SLEEP_POWER_DOWN_CPU
74- TEST_ESP_OK (sleep_cpu_configure (true));
75- #endif
76- TEST_ESP_OK (esp_sleep_enable_timer_wakeup (2 * 1000 * 1000 ));
77- TEST_ESP_OK (esp_light_sleep_start ());
78-
79- printf ("Waked up! Let's see if GPTimer driver can still work...\r\n" );
80- #if ESP_SLEEP_POWER_DOWN_CPU
81- TEST_ESP_OK (sleep_cpu_configure (false));
82- #endif
83-
84- printf ("check if the sleep happened as expected\r\n" );
85- TEST_ASSERT_EQUAL (0 , sleep_ctx .sleep_request_result );
86- #if SOC_TIMER_SUPPORT_SLEEP_RETENTION
87- if (back_up_before_sleep ) {
88- TEST_ASSERT_EQUAL (PMU_SLEEP_PD_TOP , sleep_ctx .sleep_flags & PMU_SLEEP_PD_TOP );
89- }
90- #endif
91- esp_sleep_set_sleep_context (NULL );
138+ test_gptimer_survival_after_sleep_helper (timer , back_up_before_sleep );
92139
93140 uint64_t count_value_after_sleep = 0 ;
94141 TEST_ESP_OK (gptimer_get_raw_count (timer , & count_value_after_sleep ));
0 commit comments