fix(radio): don't hang on a transient SPI failure talking to the LoRa chip - #11234
fix(radio): don't hang on a transient SPI failure talking to the LoRa chip#11234ndoo wants to merge 2 commits into
Conversation
… chip assert(err == RADIOLIB_ERR_NONE)/assert(result != RADIOLIB_ERR_WRONG_MODEM) guarded SPI communication with the physical radio chip in setStandby(), startReceive(), and isChannelActive() (plus a few config-time calls) across all five RadioLib interface wrappers. On STM32WL these hang forever with no diagnostic instead of a logged, recoverable error - a real risk since these run on every RX/TX state transition, i.e. continuously during normal operation, guarding against exactly the kind of transient SPI glitch (noise, marginal power, contention) that's a realistic field failure mode. The ARCH_PORTDUINO branch next to each of these already treats the same condition as recoverable (sets portduino_status.LoRa_in_error instead of asserting) - real hardware just never got the same treatment. Converted to RECORD_CRITICALERROR (INVALID_RADIO_SETTING for config calls, RADIO_SPI_BUG for the runtime SPI ops), matching the treatment every neighboring call in the same functions (setSpreadingFactor, setBandwidth, setFrequency, etc.) already gets. SX126xInterface.cpp is the only one of these actually compiled for STM32WL today; the other four (LR11x0/SX128x/RF95/LR20x0) are identical copy-paste siblings, fixed in the same pass since a future STM32WL variant using a different RadioLib-supported front-end is plausible given this board family's history of gaining hardware support over time. Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Andrew Yong <me@ndoo.sg>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
⚡ Try this PR in the Web FlasherNote Building this pull request… the flash button, badges and supported-board |
|
have you observed this in the wild? I've got some issues with LR1121 of my own. |
|
I don’t really know if this PR should be merged. It stops the firmware from intentionally crashing, but it leaves the node unreachable by LoRa anyway. Pros for merging: You can still reach it by BLE/Wi-Fi/USB as available and reboot it from a Meshtastic client device. WDYT? |
Problem
assert(err == RADIOLIB_ERR_NONE)/assert(result != RADIOLIB_ERR_WRONG_MODEM)guard SPI communication with the physical LoRa chip insetStandby(),startReceive(),isChannelActive()(plus a few config-time calls ininit()) across all five RadioLib interface wrappers (SX126xInterface.cpp,LR11x0Interface.cpp,SX128xInterface.cpp,RF95Interface.cpp,LR20x0Interface.cpp). On STM32WL these hang forever with no diagnostic instead of a logged, recoverable error — a real risk sincesetStandby()/startReceive()/isChannelActive()run on every RX/TX state transition, i.e. continuously during normal operation, guarding against exactly the kind of transient SPI glitch (noise, marginal power, contention) that's a realistic field failure mode.Tellingly, the
ARCH_PORTDUINObranch sitting right next to each of these already treats the same condition as recoverable (portduino_status.LoRa_in_error = true;instead of asserting) — real hardware just never got the same treatment.Fix
Converted each
assert()toRECORD_CRITICALERROR():INVALID_RADIO_SETTINGfor the config-time calls (matching how every neighboring call in the sameinit()functions —setSpreadingFactor,setBandwidth,setFrequency, etc. — already handles a rejected setting),RADIO_SPI_BUGfor the runtime SPI operations insetStandby()/startReceive()/isChannelActive().SX126xInterface.cppis the only one of these actually compiled for STM32WL today (RADIOLIB_EXCLUDE_{SX128X,SX127X,LR11X0,LR2021}=1); the other four are identical copy-paste siblings. Fixed all five in the same pass — a future STM32WL variant using a different RadioLib-supported front-end is plausible given this board family's history of gaining hardware support over time (RTC, TCXO options), and it's the same mechanical fix either way.Test plan
pio run -e wio-e5/pio run -e rak3172— build clean (exercisesSX126xInterface.cpp, the one compiled for STM32WL).pio run -e native-macos— build clean, confirmed all 5 modified files actually compile (portduino builds every radio driver).pio run -e tbeam(RF95/SX1276),pio run -e heltec-wireless-bridge(LR11x0 + LR2021),pio run -e makerpython_nrf52840_sx1280_oled(SX128x) — build clean on real hardware targets, exercising the non-ARCH_PORTDUINObranch (the actual new code path) for all four sibling files not compiled on STM32WL.setStandby()/startReceive()on every boot's radio init) and sent a text message over LoRa (exercisesisChannelActive()'s CAD scan before transmit) — device stayed fully responsive throughout, confirming the success path through all six converted call sites inSX126xInterface.cppis unaffected.RECORD_CRITICALERRORconversion, matching the already-established pattern from fix(stm32wl): recover from littlefs internal corruption instead of hanging #11230/fix(router): release packets Router::send() declines instead of leaking them #11231/fix(mesh): harden MemoryPool<T,MaxSize>::release() against bad pointers #11232.🤝 Attestations