Skip to content

Implement cold sleep for onboard SX1262 on RAK4630 when 13302 booster board is installed and report sleep state - #3241

Open
agessaman wants to merge 2 commits into
meshcore-dev:devfrom
agessaman:feat/rak4631-13302-onboard-radio-sleep
Open

Implement cold sleep for onboard SX1262 on RAK4630 when 13302 booster board is installed and report sleep state#3241
agessaman wants to merge 2 commits into
meshcore-dev:devfrom
agessaman:feat/rak4631-13302-onboard-radio-sleep

Conversation

@agessaman

Copy link
Copy Markdown
Contributor

feat(rak3401): cold-sleep the RAK4631's onboard SX1262 on RAK13302 builds

A RAK4631 core paired with a RAK13302 leaves the core's own SX1262 powered but never initialized—it idles in STDBY_RC for the life of the board. Firmware can't cut its supply (P1.05 is the RF switch rail, not the radio's), so this brings it up on its own pins just long enough to issue a cold sleep, before std_init() repins SPI onto the RAK13302.

Gated behind RAK4631_ONBOARD_SX1262_SLEEP and exposed through seven RAK_4631_13302_* envs. RAK_3401_*` builds are untouched.

Verified on RAK19007 + RAK4631 + RAK13302

  • begin=0 sleep=0 — chip present, cold sleep accepted
  • 5/5 reboots repeatable; no spurious wake across a 40 min soak
  • RAK13302 unaffected: device_errors=0x0000, TX and RX both confirmed
  • RAK3401 artifact unchanged (preprocessed compiler input byte-identical)
  • All seven envs build

Not verified

The current saving is datasheet-derived, not measured: 600 µA STDBY_RC → 160 nA cold sleep. That's ~0.5 mA at a 5 V input, below what was resolvable here—the WisBlock LiPo charger dominates any USB-input reading. No current reduction is claimed.

Notes

  • The sleep doesn't survive an MCU reset (GPIOs revert, NSS falls, chip wakes); the helper re-sleeps it each boot, so it's self-healing.
  • BUSY reads low in STDBY_RC and high while asleep, making the state observable—without it a failed sleep would be silent.

A RAK4631 core paired with a RAK13302 leaves the core's own SX1262
powered but never initialized, idling in STDBY_RC for the life of the
board. Firmware cannot cut its supply -- P1.05 is the RF switch rail,
not the radio's -- so bring it up on its own pins just long enough to
issue a cold sleep, before std_init() repins SPI onto the RAK13302.

Gated behind RAK4631_ONBOARD_SX1262_SLEEP and exposed through seven
RAK_4631_13302_* envs, so RAK_3401_* artifacts are unchanged.

The sleep is issued regardless of what begin() returns: Module::init()
runs first, so SPI stays usable even if TCXO calibration fails. NSS is
then held high, since the SX1262 wakes on an NSS falling edge.

Verified on RAK19007 + RAK4631 + RAK13302: begin=0 sleep=0, RAK13302
init clean (device_errors=0x0000), TX and RX both confirmed. The
current saving itself is derived from the datasheet (600 uA STDBY_RC
-> 160 nA cold sleep) and is not measured.
BUSY is driven low in STDBY_RC and high while asleep, so reading it either
side of the sleep gives a non-invasive readback of the state the chip was
found in and the state it was left in. Confirmed on hardware.

This is what makes the sleep observable at all. The only other symptom of
a failed sleep is ~600 uA, which is below what an inline USB meter can
resolve, so without this a regression would be silent.

It immediately earned itself: busy_before reads 0 on every boot, showing
the cold sleep does not survive an MCU reset. GPIOs revert to input during
reset, NSS stops being driven high, and the falling edge wakes the chip.
The helper re-sleeps it, so this is self-healing, but it means the chip is
never found already asleep.
@agessaman
agessaman marked this pull request as ready for review August 19, 2026 19:54
@agessaman

Copy link
Copy Markdown
Contributor Author

I implemented this with new envs for discoverability—a user with a 4631 wouldn't necessarily go looking for a 3401 firmware and know that it would work. But it could be implemented as a conditional check on the RAK3401 initialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant