Skip to content

fix: UART file uplink/downlink failures (#457, #344) - #463

Open
Mikefly123 wants to merge 3 commits into
mainfrom
fix/457-uart-file-transfer
Open

fix: UART file uplink/downlink failures (#457, #344)#463
Mikefly123 wants to merge 3 commits into
mainfrom
fix/457-uart-file-transfer

Conversation

@Mikefly123

Copy link
Copy Markdown
Contributor

Summary

Fixes #457 (UART file uplink/downlink failure) and #344 (buffer-repeater downlink wedge).

  • Downlink: downlinkRepeater.CHANNEL_ENABLED now defaults to UART-only at boot (ReferenceDeploymentTopology.cpp), preventing the permanent wedge caused by Utilities::BufferRepeater waiting on a LoRa channel that is disabled by default and never returns its buffer.
  • Uplink: fprime-zephyr's ZephyrUartDriver RX path now uses ISR-level back-pressure (uart_irq_rx_disable/enable) instead of silently dropping bytes when its software ring buffer fills, plus a bounded per-tick drain loop and overrun visibility (RxRingBufferOverrun event / RxOverrunCount telemetry). RAM-neutral: ring buffer size unchanged (1024B). Submodule pinned to 09fdccb on Open-Source-Space-Foundation/fprime-zephyr branch fix/457-uart-rx-drain.

Verification

  • HIL testing on a PROVES V5e flight controller (RP2350/Zephyr).
  • Downlink 1/3/5-chunk cases: reliably pass from a cold boot with no manual parameter overrides (previously: permanent hang on the very first attempt).
  • Uplink 1/3/4/5/6/8/10-chunk cases and 5×5-chunk repeats: pass reliably (previously: ~100% failure/corruption above 3-4 chunks). A residual ~15-25% intermittent failure remains, root-caused to a separate, pre-existing bug in Svc::FileUplink's event-ordering (Svc::FileUplink emits FileReceived before the file is durably closed, causing spurious file-not-found #461) — not a regression of this fix; the affected code path is untouched by this PR.
  • Zero uplink corruption/frame-desync events observed across all post-fix HIL sessions (previously the dominant failure signature).

Related follow-ups filed separately (not part of this PR)

Closes #457
Closes #344

🤖 Generated with Claude Code

https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo

Mikefly123 and others added 3 commits July 19, 2026 22:40
Reproduces UART file uplink/downlink failures for multi-chunk transfers:
uplink corrupts silently above ~3-4 chunks (separate, unresolved bug),
and downlink hangs indefinitely on any transfer (root-caused to
downlinkRepeater's BufferRepeater fanning out to a disabled-by-default
LoRa channel that never returns its buffer). Oracle is fileManager's
on-board CalculateCrc vs local zlib.crc32^0xFFFFFFFF for uplink, and
byte-for-byte comparison against the GDS's own downlinked bytes for
downlink. Includes a 1/3/5-chunk parametrized suite plus slow-marked
1000-chunk uplink and downlink stress cases (downlink builds its large
source file via on-board AppendFile rather than the still-broken large
uplink path).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gMrPNe6LwGtBS6Y7B5bo8
#457

Root cause (confirmed via HIL A/B testing): Utilities::BufferRepeater only
returns a downlink buffer to fileDownlink once every enabled+connected
multiOut channel has independently returned it. BufferRepeater's own
CHANNEL_ENABLED default is all-channels-ENABLED, but lora.TRANSMIT
defaults to DISABLED on every flight reset, so the LoRa channel's
comQueue never drains its FILE buffer -> fileDownlink wedges
permanently on the very first downlink attempt (matches #457 and #344).

Fix: force downlinkRepeater.CHANNEL_ENABLED to [ENABLED, DISABLED,
DISABLED] (UART-only) on every boot, right after loadParameters() in
ReferenceDeploymentTopology.cpp, mirroring the existing
lora.start(..., TransmitState::DISABLED) override pattern already used
in this file for project-specific boot-time defaults.
paramSet_CHANNEL_ENABLED() is private on the generated component base
(command-dispatch only), so the override drives the real command path:
build a Fw::CmdArgBuffer and invoke downlinkRepeater's cmdIn port
directly with opcode getIdBase() + OPCODE_CHANNEL_ENABLED_SET (0x0).

This is a safe-default fix only -- it does not change BufferRepeater's
fan-out logic. Re-enabling LoRa downlink requires explicitly setting
CHANNEL_ENABLED[1]=ENABLED in lockstep with lora.TRANSMIT ENABLED; HIL
testing showed enabling TRANSMIT alone does not recover an
already-wedged transfer and even fresh transfers only drain slowly
against downlinkDelay's configured cadence.

Verified on hardware (PROVES V5e flight controller): downlink 1 and 3
chunk cases pass cleanly from a cold boot with no manual PRM_SET (302B
and 612B transfers land correctly and instantly). Uplink 1/3 chunks and
downlink-of-a-5-chunk-file remain red -- separate, pre-existing uplink
corruption bug above ~3-4 chunks, out of scope for this fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gMrPNe6LwGtBS6Y7B5bo8
…tion (issue #457)

Bumps the fprime-zephyr submodule pin to Open-Source-Space-Foundation/fprime-zephyr
branch fix/457-uart-rx-drain (commit 09fdccb), which fixes the UART RX driver's
silent byte-drop-on-full-ring-buffer behavior:

- schedIn_handler now drains the RX ring buffer in a bounded loop each tick
  (capped at ring-capacity/read-size iterations) instead of taking a single
  64-byte bite, so a backlog can be fully drained in one tick instead of
  trickling out while more bytes queue up and overrun.
- serial_cb (the RX ISR) now checks ring_buf_space_get() before reading a
  byte out of the hardware FIFO. Once the ring is full, it disables its own
  RX interrupt (uart_irq_rx_disable) instead of reading-and-dropping. For
  this board's USB-CDC-backed UART, that makes the underlying stack NAK the
  host's bulk-OUT endpoint, so unread bytes queue up in the *host's* USB
  stack (true end-to-end flow control) instead of being silently lost.
  schedIn_handler re-enables RX once draining frees ring space.
- RxRingBufferOverrun (throttled warning event) + RxOverrunCount (telemetry)
  surface any residual drops, which should no longer occur in normal
  operation.

RAM-neutral: RING_BUF_SIZE stays 1024 bytes; SERIAL_BUFFER_SIZE (64->248)
draws from commsBufferManager's existing 1024B-per-buffer pool, adding no
new allocation.

Verified on hardware (PROVES V5e, RP2350/Zephyr): uplink 1/3/4/5/6/8/10
chunks and 5x5-chunk repeats pass reliably; previously uplinks above 3-4
chunks corrupted ~100% of the time. Zero RX ring-buffer overrun or CCSDS
frame-desync events observed across all post-fix test sessions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@Mikefly123, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e9d707ee-d42e-478b-90f1-430796563d03

📥 Commits

Reviewing files that changed from the base of the PR and between 3d761fc and d89b568.

📒 Files selected for processing (5)
  • PROVESFlightControllerReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi
  • PROVESFlightControllerReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp
  • PROVESFlightControllerReference/test/int/uart_file_transfer_test.py
  • lib/fprime-zephyr
  • pytest.ini

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.

[BUG] UART File Uplink / Downlink Remains Broken [BUG] Buffer Repeater Buggy on Downlink Though UART

1 participant