Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

samples: bluetooth: central_iso: fix synchronization of data submission #72622

Closed
wants to merge 10 commits into from
8 changes: 2 additions & 6 deletions samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,14 @@ CONFIG_BT_LL_SW_SPLIT=y
# Advertising Report for receiving the complete 1650 bytes of data
CONFIG_BT_BUF_EVT_RX_COUNT=16

# Set maximum scan data length for Extended Scanning in Bluetooth LE Controller
CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650

# Increase Zephyr Bluetooth LE Controller Rx buffer to receive complete chain
# of PDUs
CONFIG_BT_CTLR_RX_BUFFERS=9

# Sufficient ISO SDU and PDU length for this sample with ISO_TX_MTU of 247
CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247
CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251

# Number of supported streami sources and sinks
# Number of supported streaming sources and sinks
CONFIG_BT_CTLR_ISOAL_SOURCES=2
CONFIG_BT_CTLR_ISOAL_SINKS=1

Expand All @@ -27,7 +23,7 @@ CONFIG_BT_CTLR_ISO_TX_BUFFERS=4

# Use Low Latency Connected ISO policy
CONFIG_BT_CTLR_ADVANCED_FEATURES=y
CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y
CONFIG_BT_CTLR_CONN_ISO_RELIABILITY_POLICY=y

# Use the below if the sample is sending stale packet sequence number
# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n
3 changes: 3 additions & 0 deletions samples/bluetooth/central_iso/prj.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
CONFIG_BT=y
# Max 2 PDUs per SDU (BN = 2)
CONFIG_BT_ISO_TX_MTU=494
Comment on lines +2 to +3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand this.

CONFIG_BT_ISO_TX_MTU effectively reflects the maximum size of the SDUs. The SDUs can be any value below this, and thus increasing this size does not necessarily affect the number of PDUs per SDU.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sample now counts up to 494 bytes, so two PDUs will effectively be required to transfer that SDU (as the MAX PDU size payload is limited in the sample to exactly half of this value). This is required to prove that timing will work even if SDU interval != ISO interval.


CONFIG_LOG=y
CONFIG_BT_ISO_CENTRAL=y
24 changes: 9 additions & 15 deletions samples/bluetooth/central_iso/sample.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
sample:
description: Bluetooth ISO central (client) sample
name: Bluetooth ISO central (client) sample
common:
harness: bluetooth
platform_allow:
- nrf52_bsim
- nrf52833dk/nrf52833
integration_platforms:
- nrf52833dk/nrf52833
tags: bluetooth
tests:
sample.bluetooth.central_iso:
harness: bluetooth
platform_allow: qemu_x86
integration_platforms:
- qemu_x86
tags: bluetooth
sample.bluetooth.central_iso: {}
sample.bluetooth.central_iso.bt_ll_sw_split:
harness: bluetooth
platform_allow:
- qemu_cortex_m3
- qemu_x86
- nrf52_bsim
- nrf52833dk/nrf52833
integration_platforms:
- nrf52833dk/nrf52833
extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf
tags: bluetooth
33 changes: 33 additions & 0 deletions samples/bluetooth/central_iso/src/bt_clock_hal_nrf5.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2024, Florian Grandel, grandcentrix GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
*
* @brief Bluetooth clock hardware abstraction for nRF5x
*
* @details Currently, there is no way to access the Bluetooth clock
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you have seen earlier, the timestamps in the HCI packets are defined by the controller.
For the Zephyr open source link layer, the timestamp maps directly to RTC0 ticks. For the SoftDevice Controller the timestamps also takes wrapping into account. Therefore, the approach taken here will only work until the RTC wraps (8 minutes). Also, the approach taken here will only work when run on a single-core 52 series device. That is, it will not work on the nRF53 app core.

Looking at this it looks like the only feasible way forward:

  • Remove reading out the controller clock
  • Never issue SDUs with timestamps.
  • Not use timers to trigger submission of SDUs, just push them to controller as quickly as possible.

The drawback will be that the total end-to-end latency becomes slightly longer.
If we want to optimize for reduced latency, controller-specific assumptions are needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @rugeGerritsen here

As the current BT Core spec works w.r.t. ISO over HCI, we can't really make any (good) assumptions, and the best we really can do is just to always enqueue at least 2 SDUs and TX as fast as possible.

There are no guarantees we can make without knowing the specific controller.

I've recently refactored TX for a similar sample: #73406

Effectively moving a timer-based approach to just sending as fast and much as possible, based on the available buffers.

Keep in mind that the buffer handling will also change as part of #72090

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, see my comment re next steps.

* independently of its implementation. The following macros hide implementation
* details from the application.
*/

#include <stdint.h>

#include <hal/nrf_rtc.h>

#define BT_CLOCK_HAL_CNTR_MASK 0x00FFFFFF
#define BT_CLOCK_HAL_CNTR_UNIT_FSEC 30517578125UL

#define BT_CLOCK_HAL_FSEC_PER_USEC 1000000000UL

#define BT_CLOCK_HAL_TICKS_TO_US(x) \
(((uint32_t)(((uint64_t)(x) * BT_CLOCK_HAL_CNTR_UNIT_FSEC) / BT_CLOCK_HAL_FSEC_PER_USEC)))

#define BT_CLOCK_HAL_WRAPPING_POINT_US (BT_CLOCK_HAL_TICKS_TO_US(BT_CLOCK_HAL_CNTR_MASK))
#define BT_CLOCK_HAL_CYCLE_US (BT_CLOCK_HAL_WRAPPING_POINT_US + 1)

#define hal_ticker_now_ticks() nrf_rtc_counter_get(NRF_RTC0)
#define hal_ticker_now_usec() BT_CLOCK_HAL_TICKS_TO_US(hal_ticker_now_ticks())
Loading
Loading