From cd3105bb8321c12e78907ce35f0114a4f550631b Mon Sep 17 00:00:00 2001 From: Laurent Meunier Date: Thu, 19 Sep 2019 10:03:50 +0200 Subject: [PATCH 1/2] SysTimer should let deep sleep happen When next SysTimer wake-up is scheduler far enough, always consider that deep sleep may be entered and program an early wake-up. So that even if deep sleep is only allowed some time later, it can be entered. If not doing this, then the deep sleep would be prevented by SysTimer itself and may not be entered at all. This has been proved to happen in a simple blinly example. --- platform/source/SysTimer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/source/SysTimer.cpp b/platform/source/SysTimer.cpp index 452ccfe327e..fc063133e81 100644 --- a/platform/source/SysTimer.cpp +++ b/platform/source/SysTimer.cpp @@ -115,10 +115,9 @@ void SysTimer::set_wake_time(uint64_t at) sleep_manager_lock_deep_sleep(); } - /* If deep sleep is unlocked, and we have enough time, let's go for it */ + /* If we have enough time for deep sleep, let's consider we may enter it */ if (MBED_CONF_TARGET_DEEP_SLEEP_LATENCY > 0 && - ticks_to_sleep > MBED_CONF_TARGET_DEEP_SLEEP_LATENCY && - sleep_manager_can_deep_sleep()) { + ticks_to_sleep > MBED_CONF_TARGET_DEEP_SLEEP_LATENCY) { /* Schedule the wake up interrupt early, allowing for the deep sleep latency */ _wake_early = true; insert_absolute(wake_time - MBED_CONF_TARGET_DEEP_SLEEP_LATENCY * US_IN_TICK); From 9858b161d6199de25139914fea0cd5b41fa357a8 Mon Sep 17 00:00:00 2001 From: Laurent Meunier Date: Thu, 19 Sep 2019 13:32:37 +0200 Subject: [PATCH 2/2] SysTimer deep sleep: Add local lock check and update comments Suggested-by: @kjbracey-arm Replace the sleep_manager_can_deep_sleep() with !_deep_sleep_locked. Indeed, if we know we've taken the lock because we're using us_ticker, no need to do the early wake. Updated comments accordingly. --- platform/source/SysTimer.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/platform/source/SysTimer.cpp b/platform/source/SysTimer.cpp index fc063133e81..0803849e25d 100644 --- a/platform/source/SysTimer.cpp +++ b/platform/source/SysTimer.cpp @@ -114,17 +114,21 @@ void SysTimer::set_wake_time(uint64_t at) _deep_sleep_locked = true; sleep_manager_lock_deep_sleep(); } - - /* If we have enough time for deep sleep, let's consider we may enter it */ + /* Consider whether we will need early or precise wake-up */ if (MBED_CONF_TARGET_DEEP_SLEEP_LATENCY > 0 && - ticks_to_sleep > MBED_CONF_TARGET_DEEP_SLEEP_LATENCY) { - /* Schedule the wake up interrupt early, allowing for the deep sleep latency */ + ticks_to_sleep > MBED_CONF_TARGET_DEEP_SLEEP_LATENCY && + !_deep_sleep_locked) { + /* If there is deep sleep latency, but we still have enough time, + * and we haven't blocked deep sleep ourselves, + * allow for that latency by requesting early wake-up. + * Actual sleep may or may not be deep, depending on other actors. + */ _wake_early = true; insert_absolute(wake_time - MBED_CONF_TARGET_DEEP_SLEEP_LATENCY * US_IN_TICK); } else { - /* Otherwise, we'll set up for shallow sleep at the precise time. - * To make absolutely sure it's shallow so we don't incur the latency, - * take our own lock, to avoid a race on a thread unlocking it. + /* Otherwise, set up to wake at the precise time. + * If there is a deep sleep latency, ensure that we're holding the lock so the sleep + * is shallow. (If there is no deep sleep latency, we're fine with it being deep). */ _wake_early = false; if (MBED_CONF_TARGET_DEEP_SLEEP_LATENCY > 0 && !_deep_sleep_locked) {