Skip to content

Bridge link fixes - #1631

Open
kareltucek wants to merge 10 commits into
masterfrom
bridge_link_fixes
Open

kareltucek wants to merge 10 commits into
masterfrom
bridge_link_fixes

Conversation

@kareltucek

@kareltucek kareltucek commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Changelog:

  • Fix bridge cable link issues present since 17.2.0

In detail:

  • Fix parser sync framing issue
  • deduplicate messages - accidentally (?) removed in 18.x
  • decrease resend delay.
  • stack-dma race that may have discard or mutate control bytes

Hypothesis: Timing change in the SDK made acknowledge bytes get lost frequently on some units, because control bytes were not double buffered. Normal send from key scanner doesn't block, however, second key change send will block until the first send's ack is delivered. With resend delay 64ms this already postulates 64ms stalls whenever an ack gets lost. If third state change arrives in this interval, it doesn't get scanned and may even be missed entirelly.

kareltucek and others added 5 commits September 29, 2026 18:21
Frame/ack/resend counters, RX stop reasons, and ack latency histograms (sender:

uart_tx -> ack parsed; receiver: frame parsed -> ack handed to uart_tx). Printed by

'uhk uartStats' and included in the 'uhk recover' dump.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
After any RX teardown, bridgeOnRxDisabled resyncs the parser while the peer's frame

may still be streaming in; the rest of it arrived as 'unexpected' bytes, each of which

reset RX again (10ms deaf, mid-frame re-enable) until the frame ended. Let the parser

resync on the next Start byte instead, as the low-power build already did.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Restore the watermark check removed in 8d055e5: a frame whose ack got lost is

resent with the same watermark and must not be applied twice (left key states carry

cursor deltas). rxIdxValid exempts the first frame after a local watermark reset.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The ack loop is ~3ms for a key-state frame and ~13ms for a maximum-length one; every

retry blinds the left key scanner for the whole delay. Backoff still doubles per retry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
shared/uart_parser.c never included debug.h, so the flag was undefined there and the

byte-corruption block was compiled out regardless of its value (since a689d1f).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
kareltucek and others added 5 commits September 30, 2026 11:25
uart_tx stores the buffer pointer and returns; EasyDMA reads it afterwards. Control

bytes (Ack/Nack/Ping) and the wake byte were sent from stack variables that went out

of scope before the transfer, so what reached the wire was not guaranteed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The CRC-invalid dump ran in the UART RX ISR and emitted one deferred log message per

byte; a single bad frame overflowed the log buffer regardless of log thread priority.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The exponential backoff let one unacked frame hold txBufferBusy for ~1s (was ~8s at

64ms); on the left half that blocks the key scanner, so key changes made meanwhile are

coalesced or lost. Worst case is now UART_RESEND_COUNT * UART_RESEND_DELAY = 45ms.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Under DEBUG_STRESS_UART, ack/nack/ping bytes are discarded with ~5% probability, so the
timeout -> resend -> duplicate path gets exercised, not only CRC failures.

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

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant