[deep_sleep] feed watchdog in deep sleep (#17516)

This commit is contained in:
tomaszduda23
2026-07-13 09:19:23 +12:00
committed by Jesse Hills
parent eb0848d538
commit 312f6f2049
@@ -1,13 +1,36 @@
#include "deep_sleep_component.h"
#ifdef USE_ZEPHYR
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include "esphome/core/wake.h"
#include <zephyr/sys/poweroff.h>
#include <algorithm>
namespace esphome::deep_sleep {
static const char *const TAG = "deep_sleep";
// The Zephyr watchdog has a short window (2s, or 10s with Zigbee) and
// WDT_OPT_PAUSE_IN_SLEEP only pauses it during true hardware sleep — not while a
// radio thread (e.g. the Zigbee stack) keeps the CPU busy in k_sem_take(). Feed
// it at least this often while waiting so it does not reset the device.
static const uint32_t WDT_FEED_INTERVAL_MS = 1000;
static bool wakeable_delay_feed_wdt(uint32_t ms) {
while (ms > 0) {
const uint32_t step = std::min(ms, WDT_FEED_INTERVAL_MS);
esphome::internal::wakeable_delay(step);
esphome::arch_feed_wdt();
if (esphome::wake_request_take()) {
return true;
}
if (ms != UINT32_MAX) {
ms -= step;
}
}
return false;
}
optional<uint32_t> DeepSleepComponent::get_run_duration_() const { return this->run_duration_; }
void DeepSleepComponent::dump_config_platform_() {}
@@ -15,8 +38,9 @@ void DeepSleepComponent::dump_config_platform_() {}
bool DeepSleepComponent::prepare_to_sleep_() { return true; }
void DeepSleepComponent::deep_sleep_() {
bool woke = false;
if (this->sleep_duration_.has_value()) {
esphome::internal::wakeable_delay(static_cast<uint32_t>(*this->sleep_duration_ / 1000));
woke = wakeable_delay_feed_wdt(static_cast<uint32_t>(*this->sleep_duration_ / 1000));
} else {
#ifndef USE_ZIGBEE
// the device can be woken up through one of the following signals:
@@ -29,10 +53,9 @@ void DeepSleepComponent::deep_sleep_() {
// The system is reset when it wakes up from System OFF mode.
sys_poweroff();
#else
esphome::internal::wakeable_delay(UINT32_MAX);
woke = wakeable_delay_feed_wdt(UINT32_MAX);
#endif
}
const bool woke = esphome::wake_request_take();
if (woke) {
ESP_LOGD(TAG, "Woken up by another thread");
} else {