Files
2026-08-28 13:48:53 +02:00

104 lines
5.9 KiB
Plaintext

# ESP32 system power management — light sleep between events.
#
# AUTO-ENABLED for repeater builds on the DIO1-wake-capable Heltec boards; see
# the allowlist block in CMakeLists.txt for who qualifies and why the others
# must not. Passing it by hand is still supported for testing another board:
#
# west build -b heltec_wifi_lora32_v3/esp32s3/procpu zephcore --pristine -- \
# -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/pm_esp32.conf"
#
# CONSOLE BEHAVIOUR — helpers/pm_esp32_console.c does two things without which
# light sleep makes a node unusable: it flushes the console UART before every
# sleep (Zephyr's PM path does not, so lines would be cut mid-character), and
# it blocks sleep for ZEPHCORE_PM_BOOT_AWAKE_MS (default 10 min) after boot so
# there is a guaranteed window to configure the node. AFTER THAT WINDOW THE USB
# CLI STOPS ANSWERING: nothing arms a UART wake source, so typed characters are
# dropped. Connecting a terminal usually resets the board (the USB bridge
# drives EN from DTR) which re-arms the window — but a terminal that does not
# toggle DTR needs a manual power cycle. Remote admin over LoRa is unaffected.
#
# Only Heltec V3 actually consoles on uart0. V4, V4.3 and Wireless Tracker V2
# choose usb_serial in board.overlay, and the uart0 reroute in
# boards/common/esp32s3_usb.overlay is companion-only, so a REPEATER build of
# those boards has a USB Serial/JTAG console. The flush above then targets a
# peripheral that is not their console and is inert, and the USJ peripheral
# drops off the bus in light sleep with no wake source in the HAL. Net effect
# on those three: no USB CLI at all after the boot window, rather than a CLI
# that merely ignores keystrokes. This is accepted so the boards stay in the
# field exercising light sleep — see the allowlist block in CMakeLists.txt.
#
# WiFi builds hold a pm_policy lock and never light-sleep at all — the OTA
# session takes one for its duration (adapters/ota/wifi_ota.c) and an uplink or
# observer station takes one permanently (adapters/wifi/ZephyrWiFiStation.c).
#
# What it buys: Espressif parts have no equivalent of the nRF52's "idle at
# microamps in WFI" — WAITI gates the core clock but leaves PLL, peripherals
# and RAM powered, so an idle ESP32 sits in the tens of mA. Light sleep is
# sub-mA. On a repeater that is the difference between the MCU dominating the
# power budget and the radio dominating it.
#
# REPEATERS ONLY. Do not pair this with a companion build. The Espressif HCI
# driver (drivers/bluetooth/hci/hci_esp32.c) takes no pm_policy locks, so
# nothing stops the SoC light-sleeping mid-advertising or mid-connection; the
# NXP driver does take them, Espressif's does not. repeater.conf sets
# CONFIG_BT=n, which removes the problem rather than papering over it.
#
# BOARD REQUIREMENT — DIO1 must be an RTC-capable GPIO. On ESP32-S3
# esp_sleep_is_valid_wakeup_gpio() reduces to RTC_GPIO_IS_VALID_GPIO(), i.e.
# GPIO 0-21. A board wiring DIO1 above that CANNOT wake on a received packet:
#
# OK heltec_wifi_lora32_v3 / v4 / v43, heltec_wireless_tracker(_v2)
# -> DIO1 = GPIO14
# NOT OK xiao_esp32s3 (GPIO39), station_g2 (GPIO48), thinknode_m9 (GPIO42),
# lilygo_tlora_c6 (GPIO23, outside the C6's LP range 0-7)
# N/A ttgo_lora32 -> SX127x; patch 0003 arms DIO1 in the sx126x driver
# only, so nothing marks the pin as a wake source at all
#
# On a NOT-OK board the driver logs "Pin N is not wakeup capable" at boot and
# the node will light-sleep straight through inbound packets while looking
# excellent on a current meter. Check that log line before trusting any
# measurement.
#
# PAD HOLD — light sleep powers down RTC_PERIPH, so every RTC-capable pad
# (GPIO 0-21, which is all of them on these boards) loses its level unless
# held. The paired overlay holds the SX1262 NSS and RESET; without that, a
# floating NSS lets the sleeping radio clock garbage into its own retention
# RAM and the node transmits ~30 dB down until the next reboot. The overlay
# hardcodes NSS GPIO8 / RESET GPIO12 / &spi2 — verify a new board matches
# before adding it to the allowlist below.
#
# Also required and supplied by the paired pm_esp32.overlay:
# - &rtc_timer enabled. soc/espressif/common/power.c refuses to sleep without
# it, logging "Sleep skipped. Make sure '&rtc_timer' is enabled as a wakeup
# source." — i.e. CONFIG_PM=y alone silently does nothing.
# - &gpio0 as a wakeup-source, so the driver's PM resume hook calls
# esp_sleep_enable_gpio_wakeup().
# And patches/zephyr/0003 marks DIO1 itself with GPIO_INT_WAKEUP.
#
# Kernel time is safe across sleep: the Xtensa/ESP32 timer drivers implement
# the LPM hooks (esp32_lptim_hook_on_lpm_entry/exit) that read the RTC counter
# and announce elapsed ticks, so k_uptime_get() and every maintenance deadline
# stay correct.
#
# NOT YET VALIDATED ON HARDWARE — and it is now auto-enabled, so this is the
# first thing to check if an allowlisted board misbehaves. Verify in this
# order: (1) no "not wakeup capable" line at boot, (2) the node still receives
# packets, (3) only then measure current. A deaf repeater is the expected
# failure and it is not obvious from the outside. To rule it out on a suspect
# unit, rebuild with -DCONFIG_PM=n.
CONFIG_PM=y
# The RTC timer is a COUNTER driver. Enabling the DT node alone is not enough:
# without the counter subsystem drivers/counter is never built, no device
# object is emitted, and power.c's DEVICE_DT_GET_OR_NULL(rtc_timer) fails to
# link ("undefined reference to __device_dts_ord_NN"). COUNTER_RTC_ESP32 is
# then default y off the enabled DT node.
CONFIG_COUNTER=y
# System-managed device PM stays off. prj.conf pins it off globally so that
# turning on CONFIG_PM cannot silently start suspending devices from the idle
# thread — that is the trap that historically killed GPS. Device suspends stay
# explicit (pm_device_action_run from the main thread).
CONFIG_PM_DEVICE_SYSTEM_MANAGED=n