diff --git a/.gitignore b/.gitignore index a0ad5f6ea9..e65b723081 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ compile_commands.json .venv/ venv/ platformio.local.ini +Pipfile diff --git a/boards/nrf52840_s140_v6.ld b/boards/nrf52840_s140_v6.ld index 6dad975b0d..e4150be8fd 100644 --- a/boards/nrf52840_s140_v6.ld +++ b/boards/nrf52840_s140_v6.ld @@ -33,6 +33,13 @@ SECTIONS KEEP(*(.fs_data)) PROVIDE(__stop_fs_data = .); } > RAM + + .noinit (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.noinit)) + . = ALIGN(4); + } > RAM } INSERT AFTER .data; INCLUDE "nrf52_common.ld" diff --git a/boards/nrf52840_s140_v6_extrafs.ld b/boards/nrf52840_s140_v6_extrafs.ld index 352610679e..b78118aca3 100644 --- a/boards/nrf52840_s140_v6_extrafs.ld +++ b/boards/nrf52840_s140_v6_extrafs.ld @@ -33,6 +33,13 @@ SECTIONS KEEP(*(.fs_data)) PROVIDE(__stop_fs_data = .); } > RAM + + .noinit (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.noinit)) + . = ALIGN(4); + } > RAM } INSERT AFTER .data; INCLUDE "nrf52_common.ld" diff --git a/boards/nrf52840_s140_v7.ld b/boards/nrf52840_s140_v7.ld index 6aaeb4034f..16b04f523a 100644 --- a/boards/nrf52840_s140_v7.ld +++ b/boards/nrf52840_s140_v7.ld @@ -33,6 +33,13 @@ SECTIONS KEEP(*(.fs_data)) PROVIDE(__stop_fs_data = .); } > RAM + + .noinit (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.noinit)) + . = ALIGN(4); + } > RAM } INSERT AFTER .data; INCLUDE "nrf52_common.ld" diff --git a/boards/nrf52840_s140_v7_extrafs.ld b/boards/nrf52840_s140_v7_extrafs.ld index 5956183aa3..c5755ed974 100644 --- a/boards/nrf52840_s140_v7_extrafs.ld +++ b/boards/nrf52840_s140_v7_extrafs.ld @@ -33,6 +33,13 @@ SECTIONS KEEP(*(.fs_data)) PROVIDE(__stop_fs_data = .); } > RAM + + .noinit (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.noinit)) + . = ALIGN(4); + } > RAM } INSERT AFTER .data; INCLUDE "nrf52_common.ld" diff --git a/docs/cli_commands.md b/docs/cli_commands.md index 66a9b77afe..1a66953291 100644 --- a/docs/cli_commands.md +++ b/docs/cli_commands.md @@ -1124,3 +1124,20 @@ region save **Note:** Returns an error on boards without power management support. --- + +#### View the last radio initialisation status +**Usage:** `get radio.init_status` + +--- + +#### View the radio initialisation attempt count +**Usage:** `get radio.init_attempts` + +--- + +#### View compact boot diagnostics +**Usage:** `get diag.boot` + +**Note:** Returns current and previous reset-retained boot diagnostics. `cur_sd` and `prev_sd` are raw shutdown/fault markers, including low voltage, boot protection, user shutdown, and radio initialisation failure. + +--- diff --git a/docs/nrf52_power_management.md b/docs/nrf52_power_management.md index 6d97f2c306..c2bb074c11 100644 --- a/docs/nrf52_power_management.md +++ b/docs/nrf52_power_management.md @@ -31,6 +31,7 @@ Shutdown reason codes (stored in GPREGRET2): | 0x4C | LOW_VOLTAGE | Runtime low voltage threshold reached | | 0x55 | USER | User requested powerOff() | | 0x42 | BOOT_PROTECT | Boot voltage protection triggered | +| 0x52 | RADIO_INIT_FAIL | Radio initialisation failed before startup completed | ## Supported Boards @@ -185,12 +186,15 @@ Power management status can be queried via the CLI: | `get pwrmgt.source` | Returns current power source - "battery" or "external" (5V/USB power) | | `get pwrmgt.bootreason` | Returns reset and shutdown reason strings | | `get pwrmgt.bootmv` | Returns boot voltage in millivolts | +| `get diag.boot` | Returns current and previous reset-retained boot/radio diagnostics | On boards without power management enabled, all commands except `get pwrmgt.support` return: ``` ERROR: Power management not supported ``` +`get diag.boot` includes raw current and previous boot records. The shutdown fields include all `GPREGRET2` markers, not only radio initialisation failure, so low-voltage and boot-protection context is preserved when diagnosing reset loops. The previous slot is retained across MCU resets where RAM is preserved; it is not a flash-backed history and may be lost after a complete power loss. + ## Debug Output When `MESH_DEBUG=1` is enabled, the power management module outputs: diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index ef9b6bfca4..4715a09b63 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -1,5 +1,6 @@ #include // needed for PlatformIO #include +#include #include "MyMesh.h" // Believe it or not, this std C function is busted on some platforms! @@ -129,7 +130,11 @@ void setup() { } #endif - if (!radio_init()) { halt(); } + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_INIT_ENTERED); + if (!radio_init()) { + MESH_DEBUG_PRINTLN("Radio init failed!"); + radioInitRebootAfterFault(board, RADIO_INIT_FAULT_RADIO_INIT_FAIL); + } fast_rng.begin(radio_driver.getRngSeed()); diff --git a/examples/kiss_modem/main.cpp b/examples/kiss_modem/main.cpp index 7fbcaed127..86c13b86f9 100644 --- a/examples/kiss_modem/main.cpp +++ b/examples/kiss_modem/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "KissModem.h" #if defined(NRF52_PLATFORM) @@ -76,8 +77,10 @@ void onGetStats(uint32_t* rx, uint32_t* tx, uint32_t* errors) { void setup() { board.begin(); + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_INIT_ENTERED); if (!radio_init()) { - halt(); + MESH_DEBUG_PRINTLN("Radio init failed!"); + radioInitRebootAfterFault(board, RADIO_INIT_FAULT_RADIO_INIT_FAIL); } radio_driver.begin(); diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 2ce056f521..5f2f12bc53 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -1,5 +1,6 @@ #include // needed for PlatformIO #include +#include #include "MyMesh.h" @@ -48,9 +49,10 @@ void setup() { } #endif + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_INIT_ENTERED); if (!radio_init()) { MESH_DEBUG_PRINTLN("Radio init failed!"); - halt(); + radioInitRebootAfterFault(board, RADIO_INIT_FAULT_RADIO_INIT_FAIL); } fast_rng.begin(radio_driver.getRngSeed()); diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index a3798b2175..3e4188144c 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -1,5 +1,6 @@ #include // needed for PlatformIO #include +#include #include "MyMesh.h" @@ -33,7 +34,11 @@ void setup() { } #endif - if (!radio_init()) { halt(); } + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_INIT_ENTERED); + if (!radio_init()) { + MESH_DEBUG_PRINTLN("Radio init failed!"); + radioInitRebootAfterFault(board, RADIO_INIT_FAULT_RADIO_INIT_FAIL); + } fast_rng.begin(radio_driver.getRngSeed()); diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index d50667368c..473f359b01 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -1,5 +1,6 @@ #include // needed for PlatformIO #include +#include #if defined(NRF52_PLATFORM) #include @@ -560,7 +561,11 @@ void setup() { board.begin(); - if (!radio_init()) { halt(); } + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_INIT_ENTERED); + if (!radio_init()) { + MESH_DEBUG_PRINTLN("Radio init failed!"); + radioInitRebootAfterFault(board, RADIO_INIT_FAULT_RADIO_INIT_FAIL); + } fast_rng.begin(radio_driver.getRngSeed()); diff --git a/examples/simple_sensor/main.cpp b/examples/simple_sensor/main.cpp index cace67a08c..a598ac1c0e 100644 --- a/examples/simple_sensor/main.cpp +++ b/examples/simple_sensor/main.cpp @@ -1,4 +1,5 @@ #include "SensorMesh.h" +#include #ifdef DISPLAY_CLASS #include "UITask.h" @@ -66,7 +67,11 @@ void setup() { } #endif - if (!radio_init()) { halt(); } + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_INIT_ENTERED); + if (!radio_init()) { + MESH_DEBUG_PRINTLN("Radio init failed!"); + radioInitRebootAfterFault(board, RADIO_INIT_FAULT_RADIO_INIT_FAIL); + } fast_rng.begin(radio_driver.getRngSeed()); diff --git a/src/helpers/AutoDiscoverRTCClock.cpp b/src/helpers/AutoDiscoverRTCClock.cpp index a310539bc7..805adeaed4 100644 --- a/src/helpers/AutoDiscoverRTCClock.cpp +++ b/src/helpers/AutoDiscoverRTCClock.cpp @@ -2,6 +2,7 @@ #include "RTClib.h" #include #include "RTC_RX8130CE.h" +#include "RadioInitDiagnostics.h" static RTC_DS3231 rtc_3231; static bool ds3231_success = false; @@ -27,6 +28,8 @@ bool AutoDiscoverRTCClock::i2c_probe(TwoWire& wire, uint8_t addr) { } void AutoDiscoverRTCClock::begin(TwoWire& wire) { + radioInitSetBootStage(RADIO_BOOT_STAGE_RTC_BEGIN_ENTERED); + #if !defined(DISABLE_DS3231_PROBE) if (i2c_probe(wire, DS3231_ADDRESS)) { ds3231_success = rtc_3231.begin(&wire); @@ -51,6 +54,8 @@ void AutoDiscoverRTCClock::begin(TwoWire& wire) { rtc_8130_success = true; MESH_DEBUG_PRINTLN("RX8130CE: Initialized"); } + + radioInitSetBootStage(RADIO_BOOT_STAGE_RTC_BEGIN_RETURNED); } uint32_t AutoDiscoverRTCClock::getCurrentTime() { diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index b78ad6ebd6..575fc5b2c1 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -3,6 +3,7 @@ #include "TxtDataHelpers.h" #include "AdvertDataHelpers.h" #include "TxtDataHelpers.h" +#include "RadioInitDiagnostics.h" #include #ifndef BRIDGE_MAX_BAUD @@ -926,6 +927,24 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep #else strcpy(reply, "ERROR: Power management not supported"); #endif + } else if (memcmp(config, "radio.init_status", 17) == 0) { + sprintf(reply, "> %d", (int)g_last_radio_init_status); + } else if (memcmp(config, "radio.init_attempts", 19) == 0) { + sprintf(reply, "> %u", (unsigned)g_radio_init_attempts); + } else if (memcmp(config, "diag.boot", 9) == 0) { + RadioInitBootRecord cur = radioInitCurrentBootRecord(); + RadioInitBootRecord prev = radioInitPreviousBootRecord(); + sprintf(reply, "> cur_rr=0x%08lX cur_sd=0x%02X cur_st=0x%02X cur_radio=%d cur_att=%u prev_rr=0x%08lX prev_sd=0x%02X prev_st=0x%02X prev_radio=%d prev_att=%u", + (unsigned long)cur.reset_reason, + (unsigned)cur.shutdown_reason, + (unsigned)cur.boot_stage, + (int)cur.radio_status, + (unsigned)cur.attempts, + (unsigned long)prev.reset_reason, + (unsigned)prev.shutdown_reason, + (unsigned)prev.boot_stage, + (int)prev.radio_status, + (unsigned)prev.attempts); } else { sprintf(reply, "??: %s", config); } diff --git a/src/helpers/NRF52Board.cpp b/src/helpers/NRF52Board.cpp index 17265f0455..69a3847015 100644 --- a/src/helpers/NRF52Board.cpp +++ b/src/helpers/NRF52Board.cpp @@ -1,5 +1,6 @@ #if defined(NRF52_PLATFORM) #include "NRF52Board.h" +#include "RadioInitDiagnostics.h" #include #include @@ -41,6 +42,7 @@ void NRF52Board::initPowerMgr() { // Copy early-captured register values reset_reason = g_nrf52_reset_reason; shutdown_reason = g_nrf52_shutdown_reason; + radioInitCaptureBoot(reset_reason, shutdown_reason); boot_voltage_mv = 0; // Will be set by checkBootVoltage() // Clear registers for next boot @@ -91,6 +93,7 @@ const char* NRF52Board::getShutdownReasonString(uint8_t reason) { case SHUTDOWN_REASON_LOW_VOLTAGE: return "Low Voltage"; case SHUTDOWN_REASON_USER: return "User Request"; case SHUTDOWN_REASON_BOOT_PROTECT: return "Boot Protection"; + case SHUTDOWN_REASON_RADIO_INIT_FAIL: return "Radio Init Fail"; } return "Unknown"; } diff --git a/src/helpers/NRF52Board.h b/src/helpers/NRF52Board.h index 17065cf443..e63cd7edcb 100644 --- a/src/helpers/NRF52Board.h +++ b/src/helpers/NRF52Board.h @@ -11,6 +11,7 @@ #define SHUTDOWN_REASON_LOW_VOLTAGE 0x4C // 'L' - Runtime low voltage threshold #define SHUTDOWN_REASON_USER 0x55 // 'U' - User requested powerOff() #define SHUTDOWN_REASON_BOOT_PROTECT 0x42 // 'B' - Boot voltage protection +#define SHUTDOWN_REASON_RADIO_INIT_FAIL 0x52 // 'R' - Radio init failed before startup completed // Boards provide this struct with their hardware-specific settings and callbacks. struct PowerMgtConfig { @@ -76,4 +77,4 @@ class NRF52BoardDCDC : virtual public NRF52Board { NRF52BoardDCDC() {} virtual void begin() override; }; -#endif \ No newline at end of file +#endif diff --git a/src/helpers/RadioInitDiagnostics.cpp b/src/helpers/RadioInitDiagnostics.cpp new file mode 100644 index 0000000000..41351dc6ef --- /dev/null +++ b/src/helpers/RadioInitDiagnostics.cpp @@ -0,0 +1,79 @@ +#include "RadioInitDiagnostics.h" + +volatile int16_t g_last_radio_init_status = RADIOLIB_ERR_NONE; +volatile uint8_t g_radio_init_attempts = 0; +volatile uint8_t g_radio_init_boot_stage = RADIO_BOOT_STAGE_NONE; +volatile uint8_t g_radio_init_fault = RADIO_INIT_FAULT_NONE; + +#if defined(NRF52_PLATFORM) +RadioInitBootHistory g_radio_init_boot_history __attribute__((section(".noinit"))); +#else +RadioInitBootHistory g_radio_init_boot_history = {}; +#endif + +static void resetRecord(volatile RadioInitBootRecord& record) { + record.reset_reason = 0; + record.radio_status = RADIOLIB_ERR_NONE; + record.shutdown_reason = RADIO_INIT_FAULT_NONE; + record.fault = RADIO_INIT_FAULT_NONE; + record.boot_stage = RADIO_BOOT_STAGE_NONE; + record.attempts = 0; +} + +static void ensureBootHistory() { + if (g_radio_init_boot_history.magic == RADIO_INIT_BOOT_DIAG_MAGIC && + g_radio_init_boot_history.version == RADIO_INIT_BOOT_DIAG_VERSION) { + return; + } + + g_radio_init_boot_history.magic = RADIO_INIT_BOOT_DIAG_MAGIC; + g_radio_init_boot_history.version = RADIO_INIT_BOOT_DIAG_VERSION; + resetRecord(g_radio_init_boot_history.current); + resetRecord(g_radio_init_boot_history.previous); +} + +void radioInitCaptureBoot(uint32_t reset_reason, uint8_t shutdown_reason) { + ensureBootHistory(); + + g_radio_init_boot_history.previous = g_radio_init_boot_history.current; + resetRecord(g_radio_init_boot_history.current); + + g_radio_init_boot_history.current.reset_reason = reset_reason; + g_radio_init_boot_history.current.shutdown_reason = shutdown_reason; + g_radio_init_boot_history.current.fault = shutdown_reason; + + g_radio_init_fault = shutdown_reason; + g_radio_init_boot_stage = RADIO_BOOT_STAGE_NONE; + g_radio_init_attempts = 0; + g_last_radio_init_status = RADIOLIB_ERR_NONE; +} + +RadioInitBootRecord radioInitCurrentBootRecord() { + ensureBootHistory(); + return g_radio_init_boot_history.current; +} + +RadioInitBootRecord radioInitPreviousBootRecord() { + ensureBootHistory(); + return g_radio_init_boot_history.previous; +} + +void radioInitHistorySetStage(uint8_t stage) { + ensureBootHistory(); + g_radio_init_boot_history.current.boot_stage = stage; +} + +void radioInitHistorySetAttempt(uint8_t attempt) { + ensureBootHistory(); + g_radio_init_boot_history.current.attempts = attempt; +} + +void radioInitHistorySetStatus(int16_t status) { + ensureBootHistory(); + g_radio_init_boot_history.current.radio_status = status; +} + +void radioInitHistorySetFault(uint8_t fault) { + ensureBootHistory(); + g_radio_init_boot_history.current.fault = fault; +} diff --git a/src/helpers/RadioInitDiagnostics.h b/src/helpers/RadioInitDiagnostics.h new file mode 100644 index 0000000000..15c0a74b7a --- /dev/null +++ b/src/helpers/RadioInitDiagnostics.h @@ -0,0 +1,153 @@ +#pragma once + +#include +#include +#include + +#if defined(NRF52_PLATFORM) +#include +#endif + +#ifndef RADIOLIB_ERR_SPI_CMD_TIMEOUT +#define RADIOLIB_ERR_SPI_CMD_TIMEOUT -705 +#endif + +#define RADIO_INIT_FAULT_NONE 0x00 +#define RADIO_INIT_FAULT_RADIO_INIT_FAIL 0x52 +#define RADIO_INIT_BOOT_DIAG_MAGIC 0x4D435244UL // "MCRD" +#define RADIO_INIT_BOOT_DIAG_VERSION 1 + +enum RadioInitBootStage : uint8_t { + RADIO_BOOT_STAGE_NONE = 0x00, + RADIO_BOOT_STAGE_RADIO_INIT_ENTERED = 0x30, + RADIO_BOOT_STAGE_RTC_BEGIN_ENTERED = 0x31, + RADIO_BOOT_STAGE_RTC_BEGIN_RETURNED = 0x32, + RADIO_BOOT_STAGE_RADIO_STD_INIT_ENTERED = 0x40, + RADIO_BOOT_STAGE_RADIO_STD_INIT_SUCCESS = 0x41, + RADIO_BOOT_STAGE_RADIO_STD_INIT_FAIL = 0x42, + RADIO_BOOT_STAGE_RADIO_BUSY_TIMEOUT = 0x43, +}; + +struct RadioInitBootRecord { + uint32_t reset_reason; + int16_t radio_status; + uint8_t shutdown_reason; + uint8_t fault; + uint8_t boot_stage; + uint8_t attempts; +}; + +struct RadioInitBootHistory { + uint32_t magic; + uint8_t version; + RadioInitBootRecord current; + RadioInitBootRecord previous; +}; + +extern volatile int16_t g_last_radio_init_status; +extern volatile uint8_t g_radio_init_attempts; +extern volatile uint8_t g_radio_init_boot_stage; +extern volatile uint8_t g_radio_init_fault; +extern RadioInitBootHistory g_radio_init_boot_history; + +void radioInitCaptureBoot(uint32_t reset_reason, uint8_t shutdown_reason); +RadioInitBootRecord radioInitCurrentBootRecord(); +RadioInitBootRecord radioInitPreviousBootRecord(); +void radioInitHistorySetStage(uint8_t stage); +void radioInitHistorySetAttempt(uint8_t attempt); +void radioInitHistorySetStatus(int16_t status); +void radioInitHistorySetFault(uint8_t fault); + +inline void radioInitSetBootStage(uint8_t stage) { + g_radio_init_boot_stage = stage; + radioInitHistorySetStage(stage); +} + +inline void radioInitRecordAttempt(uint8_t attempt) { + g_radio_init_attempts = attempt; + radioInitHistorySetAttempt(attempt); +} + +inline void radioInitRecordStatus(int16_t status) { + g_last_radio_init_status = status; + radioInitHistorySetStatus(status); +} + +inline void radioInitRecordFault(uint8_t fault) { + g_radio_init_fault = fault; + radioInitHistorySetFault(fault); +#if defined(NRF52_PLATFORM) + // GPREGRET2 is already used as a reset-persistent one-byte reason store on + // nRF52. Writing the radio fault before reset lets the next boot report that + // the previous boot failed before normal application startup. + NRF_POWER->GPREGRET2 = fault; +#endif +} + +inline const char* radioInitFaultString(uint8_t fault) { + switch (fault) { + case RADIO_INIT_FAULT_NONE: + return "None"; + case RADIO_INIT_FAULT_RADIO_INIT_FAIL: + return "Radio Init Fail"; + } + return "Unknown"; +} + +inline bool radioInitWaitBusyLow(uint32_t timeout_ms) { +#if defined(P_LORA_BUSY) + if (P_LORA_BUSY == RADIOLIB_NC) return true; + + pinMode(P_LORA_BUSY, INPUT); + uint32_t start = millis(); + while (digitalRead(P_LORA_BUSY) == HIGH) { + if (millis() - start > timeout_ms) { + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_BUSY_TIMEOUT); + radioInitRecordStatus(RADIOLIB_ERR_SPI_CMD_TIMEOUT); + return false; + } + delay(1); + } +#endif + return true; +} + +inline void radioInitResetPulse() { +#if defined(P_LORA_RESET) + if (P_LORA_RESET == RADIOLIB_NC) return; + + pinMode(P_LORA_RESET, OUTPUT); + digitalWrite(P_LORA_RESET, LOW); + delay(10); + digitalWrite(P_LORA_RESET, HIGH); + delay(10); +#endif +} + +inline void radioInitPowerCycle() { +#if defined(SX126X_POWER_EN) + pinMode(SX126X_POWER_EN, OUTPUT); + digitalWrite(SX126X_POWER_EN, LOW); + delay(50); + digitalWrite(SX126X_POWER_EN, HIGH); + delay(100); +#endif +} + +inline void radioInitPrepareAttempt(uint8_t attempt) { + if (attempt == 2) { + radioInitResetPulse(); + delay(100); + } else if (attempt >= 3) { + radioInitPowerCycle(); + radioInitResetPulse(); + delay(150); + } +} + +inline void radioInitRebootAfterFault(mesh::MainBoard& board, uint8_t fault) { + radioInitRecordFault(fault); + Serial.flush(); + delay(250); + board.reboot(); +} diff --git a/src/helpers/radiolib/CustomLLCC68.h b/src/helpers/radiolib/CustomLLCC68.h index 82f886c324..502508ae02 100644 --- a/src/helpers/radiolib/CustomLLCC68.h +++ b/src/helpers/radiolib/CustomLLCC68.h @@ -1,6 +1,7 @@ #pragma once #include +#include #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 @@ -42,17 +43,41 @@ class CustomLLCC68 : public LLCC68 { if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif #endif - int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_ENTERED); + + int status = RADIOLIB_ERR_NONE; +#ifdef NRF52_PLATFORM + for (uint8_t attempt = 1; attempt <= 3; attempt++) { + radioInitRecordAttempt(attempt); + radioInitPrepareAttempt(attempt); + + if (!radioInitWaitBusyLow(250)) { + status = g_last_radio_init_status; + } else { + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); + radioInitRecordStatus(status); + } + + if (status == RADIOLIB_ERR_NONE) break; + delay(100 * attempt); + } +#else + radioInitRecordAttempt(1); + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { tcxo = 0.0f; status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); } + radioInitRecordStatus(status); +#endif if (status != RADIOLIB_ERR_NONE) { + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_FAIL); Serial.print("ERROR: radio init failed: "); Serial.println(status); return false; // fail } + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_SUCCESS); setCRC(1); @@ -89,4 +114,4 @@ class CustomLLCC68 : public LLCC68 { readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1); return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED); } -}; \ No newline at end of file +}; diff --git a/src/helpers/radiolib/CustomSX1262.h b/src/helpers/radiolib/CustomSX1262.h index ad20122902..bef611fc00 100644 --- a/src/helpers/radiolib/CustomSX1262.h +++ b/src/helpers/radiolib/CustomSX1262.h @@ -1,6 +1,7 @@ #pragma once #include +#include #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 @@ -42,17 +43,41 @@ class CustomSX1262 : public SX1262 { if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif #endif - int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_ENTERED); + + int status = RADIOLIB_ERR_NONE; +#ifdef NRF52_PLATFORM + for (uint8_t attempt = 1; attempt <= 3; attempt++) { + radioInitRecordAttempt(attempt); + radioInitPrepareAttempt(attempt); + + if (!radioInitWaitBusyLow(250)) { + status = g_last_radio_init_status; + } else { + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); + radioInitRecordStatus(status); + } + + if (status == RADIOLIB_ERR_NONE) break; + delay(100 * attempt); + } +#else + radioInitRecordAttempt(1); + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { tcxo = 0.0f; status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); } + radioInitRecordStatus(status); +#endif if (status != RADIOLIB_ERR_NONE) { + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_FAIL); Serial.print("ERROR: radio init failed: "); Serial.println(status); return false; // fail } + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_SUCCESS); setCRC(1); @@ -97,4 +122,4 @@ class CustomSX1262 : public SX1262 { readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1); return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED); } -}; \ No newline at end of file +}; diff --git a/src/helpers/radiolib/CustomSX1268.h b/src/helpers/radiolib/CustomSX1268.h index cc541e49f3..6ade458590 100644 --- a/src/helpers/radiolib/CustomSX1268.h +++ b/src/helpers/radiolib/CustomSX1268.h @@ -1,6 +1,7 @@ #pragma once #include +#include #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 @@ -42,17 +43,41 @@ class CustomSX1268 : public SX1268 { if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif #endif - int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_ENTERED); + + int status = RADIOLIB_ERR_NONE; +#ifdef NRF52_PLATFORM + for (uint8_t attempt = 1; attempt <= 3; attempt++) { + radioInitRecordAttempt(attempt); + radioInitPrepareAttempt(attempt); + + if (!radioInitWaitBusyLow(250)) { + status = g_last_radio_init_status; + } else { + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); + radioInitRecordStatus(status); + } + + if (status == RADIOLIB_ERR_NONE) break; + delay(100 * attempt); + } +#else + radioInitRecordAttempt(1); + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { tcxo = 0.0f; status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); } + radioInitRecordStatus(status); +#endif if (status != RADIOLIB_ERR_NONE) { + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_FAIL); Serial.print("ERROR: radio init failed: "); Serial.println(status); return false; // fail } + radioInitSetBootStage(RADIO_BOOT_STAGE_RADIO_STD_INIT_SUCCESS); setCRC(1); @@ -89,4 +114,4 @@ class CustomSX1268 : public SX1268 { readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1); return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED); } -}; \ No newline at end of file +};