Skip to content

Commit 52d1ba2

Browse files
committed
Bluetooth: Controller: 1 ms connection
1 ms connection interval support. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent f732fa2 commit 52d1ba2

File tree

10 files changed

+215
-42
lines changed

10 files changed

+215
-42
lines changed

subsys/bluetooth/controller/Kconfig.ll_sw_split

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,19 @@ config BT_CTLR_ALLOW_SAME_PEER_CONN
10881088
WARNING: This option enables behavior that violates the Bluetooth
10891089
specification.
10901090

1091+
config BT_CTLR_CONN_INTERVAL_LOW_LATENCY
1092+
bool "Allow low latency connection intervals"
1093+
help
1094+
Allow low latency connection intervals.
1095+
1096+
config BT_CTLR_EVENT_IFS_LOW_LAT_US
1097+
prompt "Low latency tIFS value in microseconds" if BT_CTLR_CONN_INTERVAL_LOW_LATENCY
1098+
int
1099+
default 52 if BT_CTLR_CONN_INTERVAL_LOW_LATENCY
1100+
default 150
1101+
help
1102+
Set low latency tIFS value.
1103+
10911104
endif # BT_CONN
10921105

10931106
config BT_CTLR_ADV_INDICATION

subsys/bluetooth/controller/ll_sw/lll.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616

1717
#define EVENT_PIPELINE_MAX 7
1818

19-
#define ADV_INT_UNIT_US 625U
20-
#define SCAN_INT_UNIT_US 625U
21-
#define CONN_INT_UNIT_US 1250U
22-
#define ISO_INT_UNIT_US CONN_INT_UNIT_US
23-
#define PERIODIC_INT_UNIT_US CONN_INT_UNIT_US
19+
#define ADV_INT_UNIT_US 625U
20+
#define SCAN_INT_UNIT_US 625U
21+
#define CONN_INT_UNIT_US 1250U
22+
#define ISO_INT_UNIT_US CONN_INT_UNIT_US
23+
#define PERIODIC_INT_UNIT_US CONN_INT_UNIT_US
24+
#define CONN_LOW_LAT_INT_UNIT_US 500U
2425

2526
#define ISO_INTERVAL_TO_US(interval) ((interval) * ISO_INT_UNIT_US)
2627

subsys/bluetooth/controller/ll_sw/lll_conn.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,10 @@ int lll_conn_reset(void);
175175
void lll_conn_flush(uint16_t handle, struct lll_conn *lll);
176176

177177
void lll_conn_prepare_reset(void);
178-
int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb);
178+
int lll_conn_central_is_abort_cb(void *next, void *curr,
179+
lll_prepare_cb_t *resume_cb);
180+
int lll_conn_peripheral_is_abort_cb(void *next, void *curr,
181+
lll_prepare_cb_t *resume_cb);
179182
void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param);
180183
void lll_conn_isr_rx(void *param);
181184
void lll_conn_isr_tx(void *param);

subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,10 +1311,15 @@ static void preempt(void *param)
13111311

13121312
/* Check if current event want to continue */
13131313
err = event.curr.is_abort_cb(ready->prepare_param.param, event.curr.param, &resume_cb);
1314-
if (!err) {
1315-
/* Let preemptor LLL know about the cancelled prepare */
1316-
ready->is_aborted = 1;
1317-
ready->abort_cb(&ready->prepare_param, ready->prepare_param.param);
1314+
if (!err || (err == -EBUSY)) {
1315+
/* Returns -EBUSY when same curr and next state/role, do not
1316+
* abort same curr and next event.
1317+
*/
1318+
if (err != -EBUSY) {
1319+
/* Let preemptor LLL know about the cancelled prepare */
1320+
ready->is_aborted = 1;
1321+
ready->abort_cb(&ready->prepare_param, ready->prepare_param.param);
1322+
}
13181323

13191324
return;
13201325
}

subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ void lll_central_prepare(void *param)
7575
LL_ASSERT(err >= 0);
7676

7777
/* Invoke common pipeline handling of prepare */
78-
err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0,
79-
param);
78+
err = lll_prepare(lll_conn_central_is_abort_cb, lll_conn_abort_cb,
79+
prepare_cb, 0, param);
8080
LL_ASSERT(!err || err == -EINPROGRESS);
8181
}
8282

subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ void lll_conn_prepare_reset(void)
157157
#endif /* CONFIG_BT_CTLR_LE_ENC */
158158
}
159159

160-
int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb)
160+
#if defined(CONFIG_BT_CENTRAL)
161+
int lll_conn_central_is_abort_cb(void *next, void *curr,
162+
lll_prepare_cb_t *resume_cb)
161163
{
162164
struct lll_conn *lll = curr;
163165

@@ -166,8 +168,38 @@ int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb)
166168
return 0;
167169
}
168170

171+
/* Do not be aborted by same event if a single central trx has not been
172+
* exchanged.
173+
*/
174+
if ((next == curr) && (trx_cnt < 1U)) {
175+
return -EBUSY;
176+
}
177+
169178
return -ECANCELED;
170179
}
180+
#endif /* CONFIG_BT_CENTRAL */
181+
182+
#if defined(CONFIG_BT_PERIPHERAL)
183+
int lll_conn_peripheral_is_abort_cb(void *next, void *curr,
184+
lll_prepare_cb_t *resume_cb)
185+
{
186+
struct lll_conn *lll = curr;
187+
188+
/* Do not abort if near supervision timeout */
189+
if (lll->forced) {
190+
return 0;
191+
}
192+
193+
/* Do not be aborted by same event if a single peripheral trx has not
194+
* been exchanged.
195+
*/
196+
if ((next == curr) && (trx_cnt <= 1U)) {
197+
return -EBUSY;
198+
}
199+
200+
return -ECANCELED;
201+
}
202+
#endif /* CONFIG_BT_PERIPHERAL */
171203

172204
void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
173205
{

subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ void lll_periph_prepare(void *param)
8080
lll = p->param;
8181

8282
/* Invoke common pipeline handling of prepare */
83-
err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb,
84-
0U, p);
83+
err = lll_prepare(lll_conn_peripheral_is_abort_cb, lll_conn_abort_cb,
84+
prepare_cb, 0U, param);
8585
LL_ASSERT(!err || err == -EINPROGRESS);
8686
}
8787

subsys/bluetooth/controller/ll_sw/ull_conn.c

Lines changed: 139 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,13 @@ uint8_t ll_apto_get(uint16_t handle, uint16_t *apto)
698698
return BT_HCI_ERR_UNKNOWN_CONN_ID;
699699
}
700700

701-
*apto = conn->apto_reload * conn->lll.interval * 125U / 1000;
701+
if (conn->lll.interval >= BT_HCI_LE_INTERVAL_MIN) {
702+
*apto = conn->apto_reload * conn->lll.interval *
703+
CONN_INT_UNIT_US / (10U * USEC_PER_MSEC);
704+
} else {
705+
*apto = conn->apto_reload * (conn->lll.interval + 1U) *
706+
CONN_LOW_LAT_INT_UNIT_US / (10U * USEC_PER_MSEC);
707+
}
702708

703709
return 0;
704710
}
@@ -712,9 +718,17 @@ uint8_t ll_apto_set(uint16_t handle, uint16_t apto)
712718
return BT_HCI_ERR_UNKNOWN_CONN_ID;
713719
}
714720

715-
conn->apto_reload = RADIO_CONN_EVENTS(apto * 10U * 1000U,
716-
conn->lll.interval *
717-
CONN_INT_UNIT_US);
721+
if (conn->lll.interval >= BT_HCI_LE_INTERVAL_MIN) {
722+
conn->apto_reload =
723+
RADIO_CONN_EVENTS(apto * 10U * USEC_PER_MSEC,
724+
conn->lll.interval *
725+
CONN_INT_UNIT_US);
726+
} else {
727+
conn->apto_reload =
728+
RADIO_CONN_EVENTS(apto * 10U * USEC_PER_MSEC,
729+
(conn->lll.interval + 1U) *
730+
CONN_LOW_LAT_INT_UNIT_US);
731+
}
718732

719733
return 0;
720734
}
@@ -1028,8 +1042,17 @@ void ull_conn_done(struct node_rx_event_done *done)
10281042
if (0) {
10291043
#if defined(CONFIG_BT_PERIPHERAL)
10301044
} else if (lll->role) {
1031-
ull_drift_ticks_get(done, &ticks_drift_plus,
1032-
&ticks_drift_minus);
1045+
if (!conn->periph.drift_skip) {
1046+
ull_drift_ticks_get(done, &ticks_drift_plus,
1047+
&ticks_drift_minus);
1048+
1049+
if (ticks_drift_plus || ticks_drift_minus) {
1050+
conn->periph.drift_skip =
1051+
ull_ref_get(&conn->ull);
1052+
}
1053+
} else {
1054+
conn->periph.drift_skip--;
1055+
}
10331056

10341057
if (!ull_tx_q_peek(&conn->tx_q)) {
10351058
ull_conn_tx_demux(UINT8_MAX);
@@ -1073,10 +1096,18 @@ void ull_conn_done(struct node_rx_event_done *done)
10731096
else {
10741097
/* Start supervision timeout, if not started already */
10751098
if (!conn->supervision_expire) {
1076-
const uint32_t conn_interval_us = conn->lll.interval * CONN_INT_UNIT_US;
1099+
uint32_t conn_interval_us;
1100+
1101+
if (conn->lll.interval >= BT_HCI_LE_INTERVAL_MIN) {
1102+
conn_interval_us = conn->lll.interval *
1103+
CONN_INT_UNIT_US;
1104+
} else {
1105+
conn_interval_us = (conn->lll.interval + 1U) *
1106+
CONN_LOW_LAT_INT_UNIT_US;
1107+
}
10771108

10781109
conn->supervision_expire = RADIO_CONN_EVENTS(
1079-
(conn->supervision_timeout * 10U * 1000U),
1110+
(conn->supervision_timeout * 10U * USEC_PER_MSEC),
10801111
conn_interval_us);
10811112
}
10821113
}
@@ -2149,17 +2180,22 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_
21492180
uint32_t win_offset_us, uint16_t interval, uint16_t latency,
21502181
uint16_t timeout, uint16_t instant)
21512182
{
2152-
struct lll_conn *lll;
2183+
uint16_t conn_interval_unit_old;
2184+
uint16_t conn_interval_unit_new;
21532185
uint32_t ticks_win_offset = 0U;
2186+
uint16_t conn_interval_old_us;
2187+
uint16_t conn_interval_new_us;
21542188
uint32_t ticks_slot_overhead;
21552189
uint16_t conn_interval_old;
21562190
uint16_t conn_interval_new;
21572191
uint32_t conn_interval_us;
2158-
uint32_t periodic_us;
2159-
uint16_t latency_upd;
2192+
uint32_t ticks_at_expire;
21602193
uint16_t instant_latency;
2194+
uint32_t ready_delay_us;
21612195
uint16_t event_counter;
2162-
uint32_t ticks_at_expire;
2196+
uint32_t periodic_us;
2197+
uint16_t latency_upd;
2198+
struct lll_conn *lll;
21632199

21642200
lll = &conn->lll;
21652201

@@ -2183,16 +2219,89 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_
21832219
}
21842220
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
21852221

2222+
#if defined(CONFIG_BT_CTLR_PHY)
2223+
ready_delay_us = lll_radio_tx_ready_delay_get(lll->phy_tx,
2224+
lll->phy_flags);
2225+
#else
2226+
ready_delay_us = lll_radio_tx_ready_delay_get(0U, 0U);
2227+
#endif
2228+
21862229
/* compensate for instant_latency due to laziness */
2187-
conn_interval_old = instant_latency * lll->interval;
2188-
latency_upd = conn_interval_old / interval;
2189-
conn_interval_new = latency_upd * interval;
2190-
if (conn_interval_new > conn_interval_old) {
2191-
ticks_at_expire += HAL_TICKER_US_TO_TICKS((conn_interval_new - conn_interval_old) *
2192-
CONN_INT_UNIT_US);
2230+
if (lll->interval >= BT_HCI_LE_INTERVAL_MIN) {
2231+
conn_interval_old = instant_latency * lll->interval;
2232+
conn_interval_unit_old = CONN_INT_UNIT_US;
21932233
} else {
2194-
ticks_at_expire -= HAL_TICKER_US_TO_TICKS((conn_interval_old - conn_interval_new) *
2195-
CONN_INT_UNIT_US);
2234+
conn_interval_old = instant_latency * (lll->interval + 1U);
2235+
conn_interval_unit_old = CONN_LOW_LAT_INT_UNIT_US;
2236+
}
2237+
2238+
if (interval >= BT_HCI_LE_INTERVAL_MIN) {
2239+
uint16_t max_tx_time;
2240+
uint16_t max_rx_time;
2241+
uint32_t slot_us;
2242+
2243+
conn_interval_new = interval;
2244+
conn_interval_unit_new = CONN_INT_UNIT_US;
2245+
lll->tifs_tx_us = EVENT_IFS_DEFAULT_US;
2246+
lll->tifs_rx_us = EVENT_IFS_DEFAULT_US;
2247+
lll->tifs_hcto_us = EVENT_IFS_DEFAULT_US;
2248+
2249+
#if defined(CONFIG_BT_CTLR_DATA_LENGTH) && \
2250+
defined(CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE)
2251+
max_tx_time = lll->dle.eff.max_tx_time;
2252+
max_rx_time = lll->dle.eff.max_rx_time;
2253+
2254+
#else /* !CONFIG_BT_CTLR_DATA_LENGTH ||
2255+
* !CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE
2256+
*/
2257+
max_tx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
2258+
max_rx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
2259+
#if defined(CONFIG_BT_CTLR_PHY)
2260+
max_tx_time = MAX(max_tx_time, PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_tx));
2261+
max_rx_time = MAX(max_rx_time, PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_rx));
2262+
#endif /* !CONFIG_BT_CTLR_PHY */
2263+
#endif /* !CONFIG_BT_CTLR_DATA_LENGTH ||
2264+
* !CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE
2265+
*/
2266+
2267+
/* Calculate event time reservation */
2268+
slot_us = max_tx_time + max_rx_time;
2269+
slot_us += lll->tifs_rx_us + (EVENT_CLOCK_JITTER_US << 1);
2270+
slot_us += ready_delay_us;
2271+
2272+
if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX) ||
2273+
(lll->role == BT_HCI_ROLE_CENTRAL)) {
2274+
slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
2275+
}
2276+
2277+
conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us);
2278+
2279+
} else {
2280+
conn_interval_new = interval + 1U;
2281+
conn_interval_unit_new = CONN_LOW_LAT_INT_UNIT_US;
2282+
lll->tifs_tx_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
2283+
lll->tifs_rx_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
2284+
lll->tifs_hcto_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
2285+
/* Reserve only the processing overhead, on overlap the
2286+
* is_abort_cb mechanism will ensure to continue the event so
2287+
* as to not loose anchor point sync.
2288+
*/
2289+
conn->ull.ticks_slot =
2290+
HAL_TICKER_US_TO_TICKS_CEIL(EVENT_OVERHEAD_START_US);
2291+
}
2292+
2293+
conn_interval_us = conn_interval_new * conn_interval_unit_new;
2294+
periodic_us = conn_interval_us;
2295+
2296+
conn_interval_old_us = conn_interval_old * conn_interval_unit_old;
2297+
latency_upd = conn_interval_old_us / conn_interval_us;
2298+
conn_interval_new_us = latency_upd * conn_interval_us;
2299+
if (conn_interval_new_us > conn_interval_old_us) {
2300+
ticks_at_expire += HAL_TICKER_US_TO_TICKS(
2301+
conn_interval_new_us - conn_interval_old_us);
2302+
} else {
2303+
ticks_at_expire -= HAL_TICKER_US_TO_TICKS(
2304+
conn_interval_old_us - conn_interval_new_us);
21962305
}
21972306

21982307
lll->latency_prepare += conn->llcp.prep.lazy;
@@ -2201,15 +2310,14 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_
22012310
/* calculate the offset */
22022311
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
22032312
ticks_slot_overhead =
2204-
MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_prepare_to_start);
2313+
MAX(conn->ull.ticks_active_to_start,
2314+
conn->ull.ticks_prepare_to_start);
2315+
22052316
} else {
22062317
ticks_slot_overhead = 0U;
22072318
}
22082319

22092320
/* calculate the window widening and interval */
2210-
conn_interval_us = interval * CONN_INT_UNIT_US;
2211-
periodic_us = conn_interval_us;
2212-
22132321
switch (lll->role) {
22142322
#if defined(CONFIG_BT_PERIPHERAL)
22152323
case BT_HCI_ROLE_PERIPHERAL:
@@ -2296,7 +2404,13 @@ void ull_conn_update_peer_sca(struct ll_conn *conn)
22962404
lll = &conn->lll;
22972405

22982406
/* calculate the window widening and interval */
2299-
conn_interval_us = lll->interval * CONN_INT_UNIT_US;
2407+
if (lll->interval >= BT_HCI_LE_INTERVAL_MIN) {
2408+
conn_interval_us = lll->interval *
2409+
CONN_INT_UNIT_US;
2410+
} else {
2411+
conn_interval_us = (lll->interval + 1U) *
2412+
CONN_LOW_LAT_INT_UNIT_US;
2413+
}
23002414
periodic_us = conn_interval_us;
23012415

23022416
lll->periph.window_widening_periodic_us =

subsys/bluetooth/controller/ll_sw/ull_conn_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ struct ll_conn {
192192
#endif /* CONFIG_BT_CTLR_CONN_META */
193193
uint8_t latency_cancel:1;
194194
uint8_t sca:3;
195+
uint8_t drift_skip;
195196
uint32_t force;
196197
uint32_t ticks_to_offset;
197198
} periph;

0 commit comments

Comments
 (0)