ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
deep_sleep_zephyr.cpp
Go to the documentation of this file.
2#ifdef USE_ZEPHYR
3#include "esphome/core/hal.h"
4#include "esphome/core/log.h"
5#include "esphome/core/wake.h"
6#include <zephyr/sys/poweroff.h>
7#include <algorithm>
8
9namespace esphome::deep_sleep {
10
11static const char *const TAG = "deep_sleep";
12
13// The Zephyr watchdog has a short window (2s, or 10s with Zigbee) and
14// WDT_OPT_PAUSE_IN_SLEEP only pauses it during true hardware sleep — not while a
15// radio thread (e.g. the Zigbee stack) keeps the CPU busy in k_sem_take(). Feed
16// it at least this often while waiting so it does not reset the device.
17static const uint32_t WDT_FEED_INTERVAL_MS = 1000;
18
19static bool wakeable_delay_feed_wdt(uint32_t ms) {
20 while (ms > 0) {
21 const uint32_t step = std::min(ms, WDT_FEED_INTERVAL_MS);
24 if (esphome::wake_request_take()) {
25 return true;
26 }
27 if (ms != UINT32_MAX) {
28 ms -= step;
29 }
30 }
31 return false;
32}
33
34optional<uint32_t> DeepSleepComponent::get_run_duration_() const { return this->run_duration_; }
35
37
38bool DeepSleepComponent::prepare_to_sleep_() { return true; }
39
41 bool woke = false;
42 if (this->sleep_duration_.has_value()) {
43 woke = wakeable_delay_feed_wdt(static_cast<uint32_t>(*this->sleep_duration_ / 1000));
44 } else {
45#ifndef USE_ZIGBEE
46 // the device can be woken up through one of the following signals:
47 // - The DETECT signal, optionally generated by the GPIO peripheral.
48 // - The ANADETECT signal, optionally generated by the LPCOMP module.
49 // - The SENSE signal, optionally generated by the NFC module to wake-on-field.
50 // - Detecting a valid USB voltage on the VBUS pin (VBUS,DETECT).
51 // - A reset.
52 //
53 // The system is reset when it wakes up from System OFF mode.
54 sys_poweroff();
55#else
56 woke = wakeable_delay_feed_wdt(UINT32_MAX);
57#endif
58 }
59 if (woke) {
60 ESP_LOGD(TAG, "Woken up by another thread");
61 } else {
62 ESP_LOGD(TAG, "Timeout expired (normal sleep)");
63 }
64}
65
67 if (this->sleep_duration_.has_value()) {
68 return false;
69 }
70#ifdef USE_ZIGBEE
71 return false;
72#else
73 return true;
74#endif
75}
76
77} // namespace esphome::deep_sleep
78
79#endif
optional< uint32_t > get_run_duration_() const
void ESPHOME_ALWAYS_INLINE wakeable_delay(uint32_t ms)
Host wakeable_delay uses select() over the registered fds — defined in wake_host.cpp.
void arch_feed_wdt()
Definition hal.cpp:53
static void uint32_t
Platform-specific main loop wake primitives.