mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 20:54:32 +02:00
Merge branch 'feature/esp_timer_with_skip_unhandled_events_does_not_wake_up' into 'master'
esp_timer: A timer with skip_unhandled_events won't wake up in light sleep mode See merge request espressif/esp-idf!13219
This commit is contained in:
@@ -622,7 +622,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
|
||||
int core_id = xPortGetCoreID();
|
||||
if (!should_skip_light_sleep(core_id)) {
|
||||
/* Calculate how much we can sleep */
|
||||
int64_t next_esp_timer_alarm = esp_timer_get_next_alarm();
|
||||
int64_t next_esp_timer_alarm = esp_timer_get_next_alarm_for_wake_up();
|
||||
int64_t now = esp_timer_get_time();
|
||||
int64_t time_until_next_alarm = next_esp_timer_alarm - now;
|
||||
int64_t wakeup_delay_us = portTICK_PERIOD_MS * 1000LL * xExpectedIdleTime;
|
||||
|
@@ -360,6 +360,42 @@ TEST_CASE("esp_timer produces correct delays with light sleep", "[pm]")
|
||||
#undef NUM_INTERVALS
|
||||
}
|
||||
|
||||
static void timer_cb1(void *arg)
|
||||
{
|
||||
++*((int*) arg);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_timer with SKIP_UNHANDLED_EVENTS does not wake up CPU from sleep", "[pm]")
|
||||
{
|
||||
int count_calls = 0;
|
||||
int timer_interval_ms = 50;
|
||||
|
||||
const esp_timer_create_args_t timer_args = {
|
||||
.name = "timer_cb1",
|
||||
.arg = &count_calls,
|
||||
.callback = &timer_cb1,
|
||||
.skip_unhandled_events = true,
|
||||
};
|
||||
esp_timer_handle_t periodic_timer;
|
||||
esp_timer_create(&timer_args, &periodic_timer);
|
||||
TEST_ESP_OK(esp_timer_start_periodic(periodic_timer, timer_interval_ms * 1000));
|
||||
|
||||
light_sleep_enable();
|
||||
|
||||
const unsigned count_delays = 5;
|
||||
unsigned i = count_delays;
|
||||
while (i-- > 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
TEST_ASSERT_INT_WITHIN(1, count_delays, count_calls);
|
||||
|
||||
light_sleep_disable();
|
||||
|
||||
TEST_ESP_OK(esp_timer_stop(periodic_timer));
|
||||
TEST_ESP_OK(esp_timer_dump(stdout));
|
||||
TEST_ESP_OK(esp_timer_delete(periodic_timer));
|
||||
}
|
||||
|
||||
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
|
@@ -195,6 +195,13 @@ int64_t esp_timer_get_time(void);
|
||||
*/
|
||||
int64_t esp_timer_get_next_alarm(void);
|
||||
|
||||
/**
|
||||
* @brief Get the timestamp when the next timeout is expected to occur skipping those which have skip_unhandled_events flag
|
||||
* @return Timestamp of the nearest timer event, in microseconds.
|
||||
* The timebase is the same as for the values returned by esp_timer_get_time.
|
||||
*/
|
||||
int64_t esp_timer_get_next_alarm_for_wake_up(void);
|
||||
|
||||
/**
|
||||
* @brief Dump the list of timers to a stream
|
||||
*
|
||||
|
@@ -598,3 +598,26 @@ int64_t IRAM_ATTR esp_timer_get_next_alarm(void)
|
||||
}
|
||||
return next_alarm;
|
||||
}
|
||||
|
||||
int64_t IRAM_ATTR esp_timer_get_next_alarm_for_wake_up(void)
|
||||
{
|
||||
int64_t next_alarm = INT64_MAX;
|
||||
for (esp_timer_dispatch_t dispatch_method = ESP_TIMER_TASK; dispatch_method < ESP_TIMER_MAX; ++dispatch_method) {
|
||||
timer_list_lock(dispatch_method);
|
||||
esp_timer_handle_t it;
|
||||
LIST_FOREACH(it, &s_timers[dispatch_method], list_entry) {
|
||||
if (it == NULL) {
|
||||
break;
|
||||
}
|
||||
// timers with the SKIP_UNHANDLED_EVENTS flag do not want to wake up CPU from a sleep mode.
|
||||
if ((it->flags & FL_SKIP_UNHANDLED_EVENTS) == 0) {
|
||||
if (next_alarm > it->alarm) {
|
||||
next_alarm = it->alarm;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer_list_unlock(dispatch_method);
|
||||
}
|
||||
return next_alarm;
|
||||
}
|
||||
|
@@ -368,6 +368,7 @@ menu "FreeRTOS"
|
||||
|
||||
Note that timers created using esp_timer APIs may prevent the system from
|
||||
entering sleep mode, even when no tasks need to run.
|
||||
To skip unnecessary wake-up initialize a timer with the "skip_unhandled_events" option as true.
|
||||
|
||||
If disabled, automatic light sleep support will be disabled.
|
||||
|
||||
|
@@ -82,6 +82,8 @@ you can use the `skip_unhandled_events` option during :cpp:func:`esp_timer_creat
|
||||
When the `skip_unhandled_events` is true, if a periodic timer expires one or more times during light sleep
|
||||
then only one callback is called on wake.
|
||||
|
||||
Using the `skip_unhandled_events` option with `automatic light sleep` (see :doc:`Power Management APIs <power_management>`) helps to reduce the consumption of the system when it is in light sleep. The duration of light sleep is also determined by esp_timers. Timers with `skip_unhandled_events` option will not wake up the system.
|
||||
|
||||
Handling callbacks
|
||||
------------------
|
||||
|
||||
|
@@ -87,6 +87,8 @@ If none of the locks are acquired, and light sleep is enabled in a call to :cpp:
|
||||
|
||||
Light sleep duration will be chosen to wake up the chip before the nearest event (task being unblocked, or timer elapses).
|
||||
|
||||
To skip unnecessary wake-up you can consider initializing an esp_timer with the `skip_unhandled_events` option as true. Timers with this flag will not wake up the system and it helps to reduce consumption.
|
||||
|
||||
|
||||
Dynamic Frequency Scaling and Peripheral Drivers
|
||||
------------------------------------------------
|
||||
|
Reference in New Issue
Block a user