From 6faa289df21a967b71123cc764011533af51846f Mon Sep 17 00:00:00 2001 From: Jody Bentley Date: Tue, 23 Jun 2026 19:54:42 -0400 Subject: [PATCH] companion_radio: tear down QSPI peripheral when its init fails (fixes #2827) On nRF52 BLE companion builds, a failed external-flash init left BLE completely dead: the node never advertised on the Elecrow ThinkNode M6 on any firmware version, even though the same unit runs fine over LoRa and pairs over BLE under other firmware. Root cause: when nrfx_qspi_init() fails (the M6 returns NRFX_ERROR_TIMEOUT / 0xBAD0007 during QSPI activation), it has already enabled the QSPI peripheral and enabled QSPI_IRQn in the NVIC at priority 0 (reserved for the SoftDevice), and it does not clean any of that up before returning. The very next step, the SoftDevice enable in Bluefruit.begin(), then fails (returns false) and every later BLE call reports NRF_ERROR_SOFTDEVICE_NOT_ENABLED, so the node never advertises. USB companion builds are unaffected because they never enable the SoftDevice. Fix: on the QSPIFlash.begin() failure path, disable QSPI_IRQn and power the QSPI peripheral back down before continuing. This only runs on the failure path, so boards whose QSPI init succeeds are unaffected, and BLE now comes up cleanly even when the external flash is absent or fails to initialize. Validated on a ThinkNode M6: with the QSPI init still timing out, the SoftDevice now enables, the node advertises, and the MeshCore app pairs and exchanges frames. --- examples/companion_radio/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index ef9b6bfca4..cd08fe558b 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -139,6 +139,18 @@ void setup() { if (!QSPIFlash.begin()) { // debug output might not be available at this point, might be too early. maybe should fall back to InternalFS here? MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: failed to initialize"); + #if defined(NRF52_PLATFORM) + // A failed QSPI init (e.g. nrfx_qspi_init() returning NRFX_ERROR_TIMEOUT) + // leaves the QSPI peripheral enabled and QSPI_IRQn enabled in the NVIC + // (at priority 0, which is reserved for the SoftDevice) and does NOT clean + // up after itself. That poisons the subsequent SoftDevice enable + // (Bluefruit.begin()), so on BLE builds the node never advertises (#2827). + // Tear the peripheral down so the SoftDevice can start cleanly. + NVIC_DisableIRQ(QSPI_IRQn); + NVIC_ClearPendingIRQ(QSPI_IRQn); + NRF_QSPI->TASKS_DEACTIVATE = 1; + NRF_QSPI->ENABLE = 0; + #endif } else { MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: initialized successfully"); }