Skip to content

Commit 37bf99e

Browse files
cvinayakkartben
authored andcommitted
Bluetooth: Controller: Fix radio_tmr_start_us for single timer use
This commit addresses two bugs in use of single timer s/w switch implementation, incorrect aux_offset in subsequent ADV_EXT_IND and ISO receiver failing to receive second or greater BIS subevents. Fix radio_tmr_start_now implementation to consider the initial latency in starting the event timer in single timer use mode. This fixes the incorrect aux_offset in ADV_EXT_IND PDUs. Fix radio_tmr_start_us implementation for single timer use, as the timer is reset on every radio end, and hence the requested start_us has to be adjusted for the accumulated last_end_pdu_us value. This fixes the BIS subevent receptions. Also, fix the maximum radio ISR latency value used in radio_tmr_start_us to consider the maximum Rx chain delay and maximum radio ramp up delays. 80 us + ~30 us + ~40 us should be able to meet the 150 us tIFS duration. Relates to commit bcd28e0 ("Bluetooth: Controller: Fix sw switch single timer for spurious TXEN/RXEN"). Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent 713375a commit 37bf99e

File tree

3 files changed

+85
-17
lines changed

3 files changed

+85
-17
lines changed

subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,15 @@ uint32_t radio_is_address(void)
611611
}
612612

613613
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
614+
static uint32_t last_pdu_end_latency_us;
614615
static uint32_t last_pdu_end_us;
615616

617+
static void last_pdu_end_us_init(uint32_t latency_us)
618+
{
619+
last_pdu_end_latency_us = latency_us;
620+
last_pdu_end_us = 0U;
621+
}
622+
616623
uint32_t radio_is_done(void)
617624
{
618625
if (NRF_RADIO->NRF_RADIO_TRX_END_EVENT != 0) {
@@ -1388,7 +1395,11 @@ void radio_tmr_tifs_set(uint32_t tifs)
13881395

13891396
uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
13901397
{
1398+
uint32_t remainder_us;
1399+
1400+
/* Convert jitter to positive offset remainder in microseconds */
13911401
hal_ticker_remove_jitter(&ticks_start, &remainder);
1402+
remainder_us = remainder;
13921403

13931404
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
13941405
/* When using single timer for software tIFS switching, ensure that
@@ -1401,18 +1412,18 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
14011412
uint32_t latency_ticks;
14021413
uint32_t latency_us;
14031414

1404-
latency_us = MAX(remainder, HAL_RADIO_ISR_LATENCY_MAX_US) - remainder;
1415+
latency_us = MAX(remainder_us, HAL_RADIO_ISR_LATENCY_MAX_US) - remainder_us;
14051416
latency_ticks = HAL_TICKER_US_TO_TICKS(latency_us);
14061417
ticks_start -= latency_ticks;
1407-
remainder += latency_us;
1408-
#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1418+
remainder_us += latency_us;
1419+
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
14091420

14101421
nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CLEAR);
14111422
EVENT_TIMER->MODE = 0;
14121423
EVENT_TIMER->PRESCALER = HAL_EVENT_TIMER_PRESCALER_VALUE;
14131424
EVENT_TIMER->BITMODE = 2; /* 24 - bit */
14141425

1415-
nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_TRX_CC_OFFSET, remainder);
1426+
nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_TRX_CC_OFFSET, remainder_us);
14161427

14171428
#if defined(CONFIG_BT_CTLR_NRF_GRTC)
14181429
uint32_t cntr_l, cntr_h, cntr_h_overflow, stale;
@@ -1479,7 +1490,7 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
14791490

14801491
#if !defined(CONFIG_BT_CTLR_TIFS_HW)
14811492
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1482-
last_pdu_end_us = 0U;
1493+
last_pdu_end_us_init(latency_us);
14831494

14841495
#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
14851496
nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_CLEAR);
@@ -1506,15 +1517,15 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
15061517
#endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
15071518
#endif /* !CONFIG_BT_CTLR_TIFS_HW */
15081519

1509-
return remainder;
1520+
return remainder_us;
15101521
}
15111522

15121523
uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start)
15131524
{
15141525
uint32_t remainder_us;
15151526

15161527
/* Setup compare event with min. 1 us offset */
1517-
remainder_us = 1;
1528+
remainder_us = 1U;
15181529

15191530
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
15201531
/* When using single timer for software tIFS switching, ensure that
@@ -1531,7 +1542,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start)
15311542
latency_ticks = HAL_TICKER_US_TO_TICKS(latency_us);
15321543
ticks_start -= latency_ticks;
15331544
remainder_us += latency_us;
1534-
#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1545+
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
15351546

15361547
nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_STOP);
15371548
nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CLEAR);
@@ -1603,7 +1614,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start)
16031614

16041615
#if !defined(CONFIG_BT_CTLR_TIFS_HW)
16051616
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1606-
last_pdu_end_us = 0U;
1617+
last_pdu_end_us_init(latency_us);
16071618
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
16081619
#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX)
16091620
/* NOTE: Timer clear DPPI configuration is needed only for nRF53
@@ -1630,7 +1641,10 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us)
16301641

16311642
#if !defined(CONFIG_BT_CTLR_TIFS_HW)
16321643
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1633-
last_pdu_end_us = 0U;
1644+
/* As timer is reset on every radio end, remove the accumulated
1645+
* last_pdu_end_us in the given start_us.
1646+
*/
1647+
start_us -= last_pdu_end_us;
16341648
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
16351649
#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX)
16361650
/* NOTE: Timer clear DPPI configuration is needed only for nRF53
@@ -1672,7 +1686,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us)
16721686

16731687
latency_us = MAX(actual_us, HAL_RADIO_ISR_LATENCY_MAX_US) - actual_us;
16741688
actual_us += latency_us;
1675-
#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1689+
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
16761690

16771691
nrf_timer_event_clear(EVENT_TIMER, HAL_EVENT_TIMER_TRX_EVENT);
16781692
nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_TRX_CC_OFFSET, actual_us);
@@ -1684,6 +1698,10 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us)
16841698
} while ((now_us > start_us) &&
16851699
(EVENT_TIMER->EVENTS_COMPARE[HAL_EVENT_TIMER_TRX_CC_OFFSET] == 0U));
16861700

1701+
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1702+
actual_us += last_pdu_end_us;
1703+
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1704+
16871705
return actual_us;
16881706
}
16891707

@@ -1697,9 +1715,26 @@ uint32_t radio_tmr_start_now(uint8_t trx)
16971715
nrf_timer_task_trigger(EVENT_TIMER, HAL_EVENT_TIMER_SAMPLE_TASK);
16981716
start_us = EVENT_TIMER->CC[HAL_EVENT_TIMER_SAMPLE_CC_OFFSET];
16991717

1718+
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1719+
/* As timer is reset on every radio end, add the accumulated
1720+
* last_pdu_end_us to the captured current time.
1721+
*/
1722+
start_us += last_pdu_end_us;
1723+
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1724+
17001725
/* Setup radio start at current time */
17011726
start_us = radio_tmr_start_us(trx, start_us);
17021727

1728+
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1729+
/* Remove the single timer start latency used to mitigate use of too
1730+
* small compare register value. Thus, start_us returned be always
1731+
* the value corresponding to the captured radio ready timestamp.
1732+
* This is used in the calculation of aux_offset in subsequent
1733+
* ADV_EXT_IND PDUs.
1734+
*/
1735+
start_us -= last_pdu_end_latency_us;
1736+
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1737+
17031738
return start_us;
17041739
}
17051740

@@ -1721,28 +1756,39 @@ uint32_t radio_tmr_start_get(void)
17211756
return start_ticks;
17221757
}
17231758

1759+
uint32_t radio_tmr_start_latency_get(void)
1760+
{
1761+
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1762+
return last_pdu_end_latency_us;
1763+
#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1764+
return 0U;
1765+
#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1766+
}
1767+
17241768
void radio_tmr_stop(void)
17251769
{
17261770
nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_STOP);
17271771
#if defined(TIMER_TASKS_SHUTDOWN_TASKS_SHUTDOWN_Msk)
17281772
nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_SHUTDOWN);
1729-
#endif
1773+
#endif /* TIMER_TASKS_SHUTDOWN_TASKS_SHUTDOWN_Msk */
17301774

17311775
#if !defined(CONFIG_BT_CTLR_TIFS_HW)
1776+
#if !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
17321777
nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_STOP);
17331778
#if defined(TIMER_TASKS_SHUTDOWN_TASKS_SHUTDOWN_Msk)
17341779
nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_SHUTDOWN);
1735-
#endif
1780+
#endif /* TIMER_TASKS_SHUTDOWN_TASKS_SHUTDOWN_Msk */
1781+
#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
17361782
#endif /* !CONFIG_BT_CTLR_TIFS_HW */
17371783

17381784
#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX)
17391785
NRF_POWER->TASKS_LOWPWR = 1U;
17401786
#endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */
17411787
}
17421788

1743-
void radio_tmr_hcto_configure(uint32_t hcto)
1789+
void radio_tmr_hcto_configure(uint32_t hcto_us)
17441790
{
1745-
nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_HCTO_CC_OFFSET, hcto);
1791+
nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_HCTO_CC_OFFSET, hcto_us);
17461792

17471793
hal_radio_recv_timeout_cancel_ppi_config();
17481794
hal_radio_disable_on_hcto_ppi_config();
@@ -1751,6 +1797,18 @@ void radio_tmr_hcto_configure(uint32_t hcto)
17511797
BIT(HAL_RADIO_DISABLE_ON_HCTO_PPI));
17521798
}
17531799

1800+
void radio_tmr_hcto_configure_abs(uint32_t hcto_from_start_us)
1801+
{
1802+
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1803+
/* As timer is reset on every radio end, remove the accumulated
1804+
* last_pdu_end_us in the given hcto_us.
1805+
*/
1806+
hcto_from_start_us -= last_pdu_end_us;
1807+
#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
1808+
1809+
radio_tmr_hcto_configure(hcto_from_start_us);
1810+
}
1811+
17541812
void radio_tmr_aa_capture(void)
17551813
{
17561814
hal_radio_ready_time_capture_ppi_config();
@@ -1825,7 +1883,11 @@ uint32_t radio_tmr_end_get(void)
18251883

18261884
uint32_t radio_tmr_tifs_base_get(void)
18271885
{
1886+
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
1887+
return 0U;
1888+
#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
18281889
return radio_tmr_end_get();
1890+
#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
18291891
}
18301892

18311893
#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)

subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,10 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start);
146146
uint32_t radio_tmr_start_us(uint8_t trx, uint32_t us);
147147
uint32_t radio_tmr_start_now(uint8_t trx);
148148
uint32_t radio_tmr_start_get(void);
149+
uint32_t radio_tmr_start_latency_get(void);
149150
void radio_tmr_stop(void);
150-
void radio_tmr_hcto_configure(uint32_t hcto);
151+
void radio_tmr_hcto_configure(uint32_t hcto_us);
152+
void radio_tmr_hcto_configure_abs(uint32_t hcto_from_start_us);
151153
void radio_tmr_aa_capture(void);
152154
uint32_t radio_tmr_aa_get(void);
153155
void radio_tmr_aa_save(uint32_t aa);

subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@
5050
/* Radio ISR Latency to be considered with single timer used so that the PPI/
5151
* DPPI is disabled in time when the timer is cleared on radio end, so that
5252
* the timer compare should not trigger TXEN/RXEN immediately on radio end.
53+
* This value will be used as minimum turnaround time in setting up Rx to Tx
54+
* using radio_tmr_start_us under single timer use.
55+
* The value of 80 us is used considering 150 us TIFS minus the maximum rx
56+
* chain delay ~30 us, and minus the radio ramp up delay ~40 us.
5357
*/
54-
#define HAL_RADIO_ISR_LATENCY_MAX_US 150U
58+
#define HAL_RADIO_ISR_LATENCY_MAX_US 80U
5559

5660
#if defined(CONFIG_BT_CTLR_PHY_CODED)
5761
#define SW_SWITCH_TIMER_EVTS_COMP_BASE 3

0 commit comments

Comments
 (0)