Skip to content

feat(sband) 2/3: SBand component — fault policy, radio seam, RadioLib backend - #449

Open
Mikefly123 wants to merge 8 commits into
feat/sband-pr1-infrafrom
feat/sband-pr2-component
Open

feat(sband) 2/3: SBand component — fault policy, radio seam, RadioLib backend#449
Mikefly123 wants to merge 8 commits into
feat/sband-pr1-infrafrom
feat/sband-pr2-component

Conversation

@Mikefly123

Copy link
Copy Markdown
Contributor

Second of three stacked PRs (base: #448). The SBand component itself, still not wired into the topology (that's PR 3).

What

  • SBandFaultPolicy (TDD'd): N=5 consecutive radio failures → nRST reset request; M=3 resets without an intervening success → FAULTED latched until ground RESET_RADIO. Design invariant (grilled): S-Band failure degrades to "no S-Band" — never backpressure, never a spacecraft reset, never touches UHF.
  • SBandRadioIf seam + RadioLibSBandRadio production impl: the component is unit-testable without hardware (SBand previously had zero tests).
  • RX reads into Fw::Buffer from the buffer manager (kills the 256 B stack array implicated in [FEATURE] S Band Radio #299's overflow).
  • Four post-removal correctness fixes hand-ported from the orphaned s-band-speedup branch (repo rename blocks cherry-pick): BUSY-GPIO wiring, dataOut ordering after SPI ops (SPI bus shared with flash), atomic transmit flag, enableRx return types.
  • RADIOLIB_STATIC_ONLY=1 (PUBLIC): no in-flight RadioLib heap churn ([BUG]: RadioHead Library Can Crash Software #122).

Verification

GTest suites for fault policy + component logic against a mock SBandRadioIf; builds clean v5e/v5d. End-to-end behavior validated on HWIL under PR 3 (fault surface pristine through TX soak windows, RESET_RADIO full re-init OK).

🤖 Generated with Claude Code

Mikefly123 and others added 8 commits July 13, 2026 01:56
Implements decision D3 from S-BAND-REINTEGRATION-PLAN.md: N=5 consecutive
radio-operation failures request one nRST reset; M=3 resets without an
intervening success latch FAULTED; ground can re-arm from FAULTED via
groundResetRequested(). Host-compilable pure class (no Zephyr/F' deps),
five RED->GREEN behaviors pinned in test_SBand_FaultPolicy.cpp. The
SBand component will wire this in as a thin adapter in a follow-up commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Abstract interface over the exact 13 SX1280 (RadioLib) calls SBand uses
(begin, setPacketParamsLoRa, transmit, readData, getPacketLength,
getIrqStatus, startReceive, standby, setSpreadingFactor, setCodingRate,
setBandwidth, getRSSI, getSNR). No Zephyr/F' dependency -- just
stdint/cstddef -- so both the production RadioLib-backed implementation and
test fakes can implement it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
consecutiveFailures()/resetsSinceSuccess() expose the fault policy's
internal counts read-only, so the SBand component can surface them as
telemetry (ConsecutiveRadioFailures/RadioResetCount) and EVR arguments
without changing the state machine's semantics. Pinned with a test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Owns the RadioLib HAL/Module/SX1280 stack the SBand component used to hold
directly, and forwards every SBandRadioIf call 1:1 to it. Decision D4:
production wiring uses this class; host/component tests point the same
SBandRadioIf* at a fake instead. No behavior change -- pure delegation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Un-comments add_fprime_subdirectory for Components/SBand -- the library
and its sources now build again (topology stays untouched: the sband
instance remains commented out until PR 3, so no flight-behavior change).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports s-band-speedup 363101e + 7c473f4 (hand-applied: this repo was
renamed FprimeZephyrReference -> PROVESFlightControllerReference in #331,
so the original commits don't cherry-pick cleanly). Adds SBAND_PIN_BUSY
and FprimeHal::digitalRead's BUSY branch; RadioLibSBandRadio's Module is
already constructed with the BUSY pin (this commit makes that pin do
something). The topology-level GPIO connection (gpioSbandBusy) is deferred
to PR 3 along with the rest of the sband instance wiring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Thin-adapter refactor (D3+D4), verified by firmware build now / HWIL in
PR 3 -- logic is covered by the SBandFaultPolicy host UTs:

- Component holds a SBandRadioIf* (default: &m_rlb_radio, a
  RadioLibSBandRadio) instead of the RadioLib types directly; every
  begin/transmit/readData/etc. call goes through m_radio.
- Every radio-call outcome feeds SBandFaultPolicy via handleRadioResult();
  applyFaultDecision() reacts to REQUEST_RESET (nRST reset + re-init
  attempt, existing resetSend_out path) and FAULTED (stop all
  radio-interface calls, WARNING_HI EVR once, RadioFaulted telemetry).
- New RESET_RADIO command: groundResetRequested() + full re-init attempt.
- FAULTED and !configured both still return dataIn buffers and emit
  comStatus immediately so the com queue never starves; run ticks become
  no-ops while FAULTED.
- deferredRxHandler allocates from getPacketLength() and reads RadioLib
  data directly into the Fw::Buffer -- the 256-byte stack array is gone
  (this was implicated in the #299 SBand-thread stack overflow).
- New telemetry: RadioFaulted (bool), ConsecutiveRadioFailures,
  RadioResetCount. New events: RadioResetRequested, RadioFaultLatched,
  RadioFaultCleared.

Also hand-ports the remaining s-band-speedup correctness fixes (cherry-pick
doesn't apply post-#331 rename):
- 8aeee2f: dataOut_out only after all SPI ops for the RX'd packet
  (readData/RSSI/SNR/enableRx) -- avoids contending with flash on the SPI
  bus while dataOut_out's synchronous downstream chain runs.
- 9b240d0: m_rxHandlerQueued is now std::atomic<bool>, exchanged
  atomically in run_handler -- it's genuinely shared between the
  rate-group thread and SBand's own thread.
- 17df3ec: enableRx/enableTx return the RadioLib int16_t state instead of
  Status; re-arming RX goes through enableRx() (not a raw startReceive())
  so RF params are reapplied on every re-arm.

Trivial compile fix against current RadioLib: startReceive() no longer
takes a timeout arg (the no-arg overload is already continuous-Rx mode).

SBand/CMakeLists.txt: adds SBandFaultPolicy.cpp/RadioLibSBandRadio.cpp to
the library, and defines RADIOLIB_STATIC_ONLY=1 PUBLIC on the RadioLib
target so it applies to RadioLib's own TUs and everything that includes
its headers (no heap allocation after boot).

The sband instance stays commented out of topology.fpp; no
ReferenceDeploymentPackets.fppi changes (its channels aren't in the
dictionary until PR 3).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Slice 1.2 resolved via investigation: assert path is loud for late-started
tasks; fprime-zephyr gets a stack-alloc-failure log (separate PR); the
early-component half-alive gap is pre-existing and filed separately.
Also corrects the plan's assumption that issue #109 fault management was
on main — it was never merged; PR 2 built the fault surface fresh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a60d1039-726e-46de-98bc-5590046f6fcc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant