Skip to content

Commit

Permalink
Bluetooth: Controller: Use reschedule margin as minimum ticks_slot
Browse files Browse the repository at this point in the history
Use reschedule margin as minimum ticks_slot when ticker with
reschedule expires. This will ensure not too many unreserved
tickers expire in close proximity that can lead of pile up
of CPU processing time and eventually causing timeout
callbacks to be delayed. This mitigate possible LL asserts
due to overhead in start of radio events.

Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
  • Loading branch information
cvinayak authored and fabiobaltieri committed May 2, 2024
1 parent 263357e commit 64f4130
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
3 changes: 2 additions & 1 deletion subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@
HAL_TICKER_TICKS_TO_US(HAL_TICKER_PSEC_PER_USEC)

/* Macro defining the margin for positioning re-scheduled nodes */
#define HAL_TICKER_RESCHEDULE_MARGIN_US 150U
#define HAL_TICKER_RESCHEDULE_MARGIN \
HAL_TICKER_US_TO_TICKS(150)
HAL_TICKER_US_TO_TICKS(HAL_TICKER_RESCHEDULE_MARGIN_US)

/* Remove ticks and return positive remainder value in microseconds */
static inline void hal_ticker_remove_jitter(uint32_t *ticks,
Expand Down
41 changes: 34 additions & 7 deletions subsys/bluetooth/controller/ticker/ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -840,15 +840,25 @@ static uint8_t ticker_resolve_collision(struct ticker_node *nodes,

while (id_head != TICKER_NULL) {
struct ticker_node *ticker_next = &nodes[id_head];
uint32_t ticker_next_ticks_slot;

/* Accumulate ticks_to_expire for each node */
acc_ticks_to_expire += ticker_next->ticks_to_expire;
if (acc_ticks_to_expire > ticker_ticks_slot) {
break;
}

if (TICKER_HAS_SLOT_WINDOW(ticker_next) &&
(ticker_next->ticks_slot == 0U)) {
ticker_next_ticks_slot =
HAL_TICKER_RESCHEDULE_MARGIN;
} else {
ticker_next_ticks_slot =
ticker_next->ticks_slot;
}

/* We only care about nodes with slot reservation */
if (ticker_next->ticks_slot == 0U) {
if (ticker_next_ticks_slot == 0U) {
id_head = ticker_next->next;
continue;
}
Expand Down Expand Up @@ -977,7 +987,8 @@ static uint8_t ticker_resolve_collision(struct ticker_node *nodes,
/* Check if next node is within this reservation slot
* and wins conflict resolution
*/
if (curr_has_ticks_slot_window ||
if ((curr_has_ticks_slot_window &&
next_not_ticks_slot_window) ||
(!lazy_next_periodic_skip &&
(next_is_critical ||
next_force ||
Expand Down Expand Up @@ -1295,11 +1306,19 @@ void ticker_worker(void *param)

#if !defined(CONFIG_BT_TICKER_LOW_LAT) && \
!defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
uint32_t ticker_ticks_slot;

if (TICKER_HAS_SLOT_WINDOW(ticker) &&
(ticker->ticks_slot == 0U)) {
ticker_ticks_slot = HAL_TICKER_RESCHEDULE_MARGIN;
} else {
ticker_ticks_slot = ticker->ticks_slot;
}

/* Check if node has slot reservation and resolve any collision
* with other ticker nodes
*/
if (((ticker->ticks_slot != 0U) ||
TICKER_HAS_SLOT_WINDOW(ticker)) &&
if ((ticker_ticks_slot != 0U) &&
(slot_reserved ||
(instance->ticks_slot_previous > ticks_expired) ||
ticker_resolve_collision(node, ticker))) {
Expand Down Expand Up @@ -1431,7 +1450,7 @@ void ticker_worker(void *param)

#if !defined(CONFIG_BT_TICKER_LOW_LAT) && \
!defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
if (ticker->ticks_slot != 0U) {
if (ticker_ticks_slot != 0U) {
/* Any further nodes will be skipped */
slot_reserved = 1U;
}
Expand Down Expand Up @@ -2061,13 +2080,21 @@ static inline void ticker_job_worker_bh(struct ticker_instance *instance,
instance->ticks_slot_previous = 0U;
}

uint32_t ticker_ticks_slot;

if (TICKER_HAS_SLOT_WINDOW(ticker) && !ticker->ticks_slot) {
ticker_ticks_slot = HAL_TICKER_RESCHEDULE_MARGIN;
} else {
ticker_ticks_slot = ticker->ticks_slot;
}

/* If a reschedule is set pending, we will need to keep
* the slot_previous information
*/
if (ticker->ticks_slot && (state == 2U) && !skip_collision &&
if (ticker_ticks_slot && (state == 2U) && !skip_collision &&
!TICKER_RESCHEDULE_PENDING(ticker)) {
instance->ticker_id_slot_previous = id_expired;
instance->ticks_slot_previous = ticker->ticks_slot;
instance->ticks_slot_previous = ticker_ticks_slot;
}
#endif /* CONFIG_BT_TICKER_SLOT_AGNOSTIC */

Expand Down

0 comments on commit 64f4130

Please sign in to comment.