Describe the bug
Hibernating a Heltec V4-R8 companion no longer sticks: a few seconds after
entering hibernate the device boots up again on its own. It affects the
official v1.17.0 heltec_v4_r8_companion_radio_ble build as well as current
dev. Builds predating v1.17.0 (e.g. Heltec's temporary factory build) are
not affected.
The wake-ups correlate with LoRa traffic: the device reboots as soon as the
next packet is received on the configured frequency.
Root cause
- c644720 ("uitask: screen and radio poweroff moved to board") removed
radio_driver.powerOff() from UITask::shutdown(). The deleted comment
said it was "still necessary until all boards are refactored to use
poweroff".
- The generic
ESP32Board::enterDeepSleep() was refactored accordingly — it
puts the radio to sleep and clears all wakeup sources
(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL)).
HeltecV4R8Board however overrides enterDeepSleep() with its
wake-on-LoRa variant: the FEM stays in RX
(loRaFEMControl.setRxModeEnableWhenMCUSleep()) and EXT1 wakeup is armed
on P_LORA_DIO_1 (ESP_EXT1_WAKEUP_ANY_HIGH) — and
HeltecV4R8Board::powerOff() simply calls that override.
Since c644720 nothing puts the SX1262 to sleep on this code path, so in
"hibernate" the radio keeps receiving and the next incoming packet raises
DIO1 → EXT1 wake → the device boots (BD_STARTUP_RX_PACKET).
Before c644720 the UI's radio_driver.powerOff() masked the issue: a
sleeping radio never raises DIO1, so the armed wake source stayed silent.
That is why pre-1.17.0 builds hibernate correctly with the identical board
code.
Suggested fix
Keep the wake-on-LoRa enterDeepSleep() for its intended use, but make
powerOff() shut the FEM down and use the base deep sleep (radio to sleep,
no wakeup sources armed):
void HeltecV4R8Board::powerOff() {
loRaFEMControl.setSleepModeEnable();
digitalWrite(P_LORA_PA_POWER, LOW);
rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CSD);
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
ESP32Board::enterDeepSleep(0);
}
(LoRaFEMControl::init() already releases the RTC holds on the next boot, so
the wake path needs no changes.)
We are running a local build with this patch; will report back once it is
confirmed on the device.
Possibly affected as well
Other variants override enterDeepSleep() without ever touching
radio_driver — worth auditing for the same pattern (not verified, and the
nRF52 ones may use a different shutdown path): heltec_rc32,
meshnology_w12, thinknode_m7, thinknode_m9.
Environment
- Heltec WiFi LoRa 32 V4-R8 (OLED SKU, ESP32-S3)
heltec_v4_r8_companion_radio_ble, v1.17.0 release and current dev
- Reproduced with active mesh traffic on EU 869.618 MHz
Describe the bug
Hibernating a Heltec V4-R8 companion no longer sticks: a few seconds after
entering hibernate the device boots up again on its own. It affects the
official v1.17.0
heltec_v4_r8_companion_radio_blebuild as well as currentdev. Builds predating v1.17.0 (e.g. Heltec's temporary factory build) arenot affected.
The wake-ups correlate with LoRa traffic: the device reboots as soon as the
next packet is received on the configured frequency.
Root cause
radio_driver.powerOff()fromUITask::shutdown(). The deleted commentsaid it was "still necessary until all boards are refactored to use
poweroff".
ESP32Board::enterDeepSleep()was refactored accordingly — itputs the radio to sleep and clears all wakeup sources
(
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL)).HeltecV4R8Boardhowever overridesenterDeepSleep()with itswake-on-LoRa variant: the FEM stays in RX
(
loRaFEMControl.setRxModeEnableWhenMCUSleep()) and EXT1 wakeup is armedon
P_LORA_DIO_1(ESP_EXT1_WAKEUP_ANY_HIGH) — andHeltecV4R8Board::powerOff()simply calls that override.Since c644720 nothing puts the SX1262 to sleep on this code path, so in
"hibernate" the radio keeps receiving and the next incoming packet raises
DIO1 → EXT1 wake → the device boots (
BD_STARTUP_RX_PACKET).Before c644720 the UI's
radio_driver.powerOff()masked the issue: asleeping radio never raises DIO1, so the armed wake source stayed silent.
That is why pre-1.17.0 builds hibernate correctly with the identical board
code.
Suggested fix
Keep the wake-on-LoRa
enterDeepSleep()for its intended use, but makepowerOff()shut the FEM down and use the base deep sleep (radio to sleep,no wakeup sources armed):
(
LoRaFEMControl::init()already releases the RTC holds on the next boot, sothe wake path needs no changes.)
We are running a local build with this patch; will report back once it is
confirmed on the device.
Possibly affected as well
Other variants override
enterDeepSleep()without ever touchingradio_driver— worth auditing for the same pattern (not verified, and thenRF52 ones may use a different shutdown path):
heltec_rc32,meshnology_w12,thinknode_m7,thinknode_m9.Environment
heltec_v4_r8_companion_radio_ble, v1.17.0 release and current dev