Skip to content

Restore sync stream after enable_module() re-enables a direction - #2

Open
wormuz wants to merge 2 commits into
GvozdevLeonid:mainfrom
wormuz:fix/tx-sync-invalidated-after-disable
Open

Restore sync stream after enable_module() re-enables a direction#2
wormuz wants to merge 2 commits into
GvozdevLeonid:mainfrom
wormuz:fix/tx-sync-invalidated-after-disable

Conversation

@wormuz

@wormuz wormuz commented Aug 19, 2026

Copy link
Copy Markdown

libbladeRF tears down the synchronous stream when a direction is disabled: rfic_host.c calls sync_deinit() on !dir_enable, and bladerf1.c does the same. That is documented behaviour — the header says "this will shut down the underlying asynchronous stream when enable = false" — but re-enabling the module does not bring the stream back.

Every later sync_tx() / sync_rx() then fails with

sync tx invalid: not initialized

which gives no hint that sync_config() has to be repeated.

How it looks from the caller side

The radio simply appears dead. Measured on a TX1 → 50 dB pad → RX1 loopback:

symptom value
received level at TX gain 60 dB −44.4 dB
received level at TX gain −30 dB −44.5 dB
transmit calls failing 65487 of 66033

Nothing in the error text points at enable_module() as the cause, so this reads as broken hardware rather than a lifecycle contract.

Fix

Remember the last sync_config() arguments per direction and replay them when the module is enabled again.

Direction is taken from the low bit: TX channels are 1 and 3, TX layouts are 1 and 3, RX are even — verified against the enum values on device.

Verification

On hardware, the previously failing sequence:

after sync_config                             OK
after disable -> enable WITHOUT sync_config   ERR_INVAL   <- before
after disable -> enable + repeated sync_config OK

became:

after sync_config                             OK
after disable -> enable WITHOUT sync_config   OK          <- after
after disable -> enable + repeated sync_config OK

and transmit errors over a full probe run dropped from 65487 to 0.

wormuz added 2 commits August 20, 2026 00:41
libbladeRF tears down the synchronous stream when a direction is
disabled: rfic_host.c calls sync_deinit() on !dir_enable, and bladerf1.c
does the same.  That is documented ("this will shut down the underlying
asynchronous stream when enable = false"), but re-enabling the module
does not bring the stream back.

Every later sync_tx()/sync_rx() then fails with

    sync tx invalid: not initialized

which gives no hint that sync_config() must be repeated.  From the
caller's side the radio simply looks dead: measured on a TX1 -> 50 dB
pad -> RX1 loopback, the received level stopped responding to TX gain
(60 dB and -30 dB both gave -44.4 dB) and 65487 of 66033 transmit calls
failed.

Remember the last sync_config() arguments per direction and replay them
when the module is enabled again.  Direction is taken from the low bit:
TX channels are 1 and 3, TX layouts are 1 and 3, RX are even.

Verified on hardware: the disable -> enable -> sync_tx sequence went from
ERR_INVAL to OK, and transmit errors dropped from 65487 to 0.
A stream configured with a *_META format carries per-buffer timestamps and
flags. Passing metadata=None leaves libbladeRF with nowhere to report them,
so the caller silently loses the timestamp it needs and
bladerf_get_timestamp() keeps returning 0.

Nothing in the error path points at the cause, so this reads as dead
hardware rather than a mismatched call.

Measured on a TX1 -> 50 dB pad -> RX1 loopback at 15.36 MSps: with the
stream in a metadata format but metadata=None, the frame timestamp stayed
at 762229041 across 8 consecutive reads and get_timestamp() returned 0.
Consecutive gain steps then analysed the same buffer, so the receive level
repeated in pairs (-34.9/-34.9, -20.2/-20.2 dBFS) and a gain ladder that is
in fact monotonic came out looking broken.

The stream format is already remembered per direction for the enable_module
restore path, so the check costs nothing extra: sync_rx()/sync_tx() now
raise instead of losing timestamps quietly.

After fixing the call sites the same ladder is monotonic, with deviations of
+0.1 to +0.8 dB over a 40 dB span.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant