Skip to content

RAK4631 companion-radio builds (USB/BLE/Ethernet) silently enter CLI Rescue mode on boards with no physical button #3400

Description

@ve7cbh

Subject: RAK4631 companion-radio builds (USB/BLE/Ethernet) silently enter CLI Rescue mode on boards with no physical button

Hi,

I ran into a connectivity bug building RAK_4631_companion_radio_ethernet (and confirmed it also affects _usb and _ble) for a WisBlock RAK4631 stack with GPS, LCD, Ethernet (RAK13800), and PoE — no physical pushbutton (only the reset button).

Symptom: The device accepts a connection at the transport level (BLE pairs, USB enumerates, TCP connects and I could even see the raw socket accept the data), but never responds to any companion protocol frame — not even CMD_APP_START. Client apps (I tested with Meshy, and confirmed with a hand-crafted raw frame + raw serial debug log) see a connection that just times out and gets dropped, with no error on the device side under normal builds.

Root cause: variants/rak4631/platformio.ini sets -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 for all three RAK_4631_companion_radio_* envs. examples/companion_radio/ui-new/UITask.cpp's handleLongPress() treats a long-press on either of those pins within the first 8 seconds of boot as a request to enter CLI Rescue mode (MyMesh::enterCLIRescue()). On hardware with no button physically wired to those pins, they float:

PIN_USER_BTN_ANA (31) is read with a bare analogRead(pin) < 20 threshold and no pull reference at all — a floating ADC input on the nRF52840 drifts easily below that.
PIN_USER_BTN (9) is at least configured INPUT_PULLUP, but still misreads as held on this hardware (possibly not a truly free GPIO on this WisBlock IO-slot pin layout — didn't fully trace the electrical cause).
Once _cli_rescue is set, MyMesh::loop() (examples/companion_radio/MyMesh.cpp, ~line 2232) calls checkCLIRescueCmd() instead of checkSerialInterface() — permanently, for the rest of that boot. Since checkSerialInterface() is the transport-agnostic entry point that drains MultiSerialInterface, this breaks USB, BLE, and Ethernet identically, regardless of which one you're trying to debug. The only visible symptom is a boot-time Serial.println("========= CLI Rescue ========="), which is invisible on the USB build specifically (Serial doubles as the companion channel there) and easy to miss elsewhere since nothing else logs it.

Workaround (confirmed working): removed PIN_USER_BTN/PIN_USER_BTN_ANA from all three RAK_4631_companion_radio_* envs. Confirmed via a manual CMD_APP_START → RESP_CODE_SELF_INFO round trip over raw TCP, and then a full working sync in Meshy over Ethernet, USB, and BLE.

Suggested upstream fixes (any of these would help):

Require a debounced, multi-sample confirmation before honoring a long-press as a rescue trigger, rather than a single analogRead() against a bare threshold with no pull reference.
Document, in the platformio.ini comments or board docs, which physical enclosure/button wiring the RAK_4631_companion_radio_* envs assume — they read as generic "any RAK4631" targets but silently require a specific button.
Log CLI Rescue entry somewhere visible across all transports (not just a Serial.println that's actively dangerous to rely on on the USB build), so this doesn't look like a dead/bricked device.
Consider not wiring PIN_USER_BTN_ANA to a WisBlock IO-slot pin without a way to detect whether anything's actually connected there.
Happy to open this as a GitHub issue/PR with the platformio.ini diff if useful.

Thanks for the project — really appreciate the work that went into it.

Activity

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

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