Skip to content

Heltec V4-R8 wakes from hibernate within seconds since v1.17.0 — radio left in RX with DIO1 armed as wakeup #3165

Description

@notbucki

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

  1. 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".
  2. 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)).
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions