Skip to content

Commit

Permalink
nimble/ll: Refactor transitions
Browse files Browse the repository at this point in the history
New Bluetooth features require fast RX-to-RX and TX-to-TX transitions
and use a different TIFS than 150us.

Co-authored-by: Andrzej Kaczmarek <[email protected]>
  • Loading branch information
mkasenberg and andrzej-kaczmarek committed Feb 19, 2025
1 parent c29b277 commit d5999ac
Show file tree
Hide file tree
Showing 11 changed files with 368 additions and 271 deletions.
21 changes: 8 additions & 13 deletions nimble/controller/include/controller/ble_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ struct os_mbuf;
#define BLE_PHY_STATE_TX (2)

/* BLE PHY transitions */
#define BLE_PHY_TRANSITION_NONE (0)
#define BLE_PHY_TRANSITION_RX_TX (1)
#define BLE_PHY_TRANSITION_TX_RX (2)
#define BLE_PHY_TRANSITION_TX_TX (3)
#define BLE_PHY_TRANSITION_NONE (0)
#define BLE_PHY_TRANSITION_TO_TX (1)
#define BLE_PHY_TRANSITION_TO_RX (2)
#define BLE_PHY_TRANSITION_TO_TX_ISO_SUBEVENT (3)
#define BLE_PHY_TRANSITION_TO_RX_ISO_SUBEVENT (4)

/* PHY error codes */
#define BLE_PHY_ERR_RADIO_STATE (1)
Expand All @@ -88,14 +89,8 @@ int ble_phy_init(void);
int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit);
uint8_t ble_phy_chan_get(void);

#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS)
/* Set T_ifs time for next transition */
void ble_phy_tifs_set(uint16_t tifs);
#endif

/* Set T_ifs for tx-tx transitions. Anchor is 0 for start of previous PDU,
* non-zero for end of PDU */
void ble_phy_tifs_txtx_set(uint16_t usecs, uint8_t anchor);
/* Set direction of the next transition */
void ble_phy_transition_set(uint8_t trans, uint16_t usecs);

/* Set transmit start time */
int ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs);
Expand All @@ -110,7 +105,7 @@ typedef uint8_t (*ble_phy_tx_pducb_t)(uint8_t *dptr, void *pducb_arg,
uint8_t *hdr_byte);

/* Place the PHY into transmit mode */
int ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans);
int ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg);

/* Copies the received PHY buffer into the allocated pdu */
void ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu);
Expand Down
35 changes: 18 additions & 17 deletions nimble/controller/src/ble_ll_adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,6 @@ static int
ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
{
int rc;
uint8_t end_trans;
uint32_t txstart;
struct ble_ll_adv_sm *advsm;

Expand Down Expand Up @@ -1183,18 +1182,18 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) &&
((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) ||
(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE))) {
end_trans = BLE_PHY_TRANSITION_TX_RX;
ble_phy_transition_set(BLE_PHY_TRANSITION_TO_RX, BLE_LL_IFS);
ble_phy_set_txend_cb(NULL, NULL);
} else {
end_trans = BLE_PHY_TRANSITION_NONE;
ble_phy_transition_set(BLE_PHY_TRANSITION_NONE, 0);
ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
}

/* Transmit advertisement */
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
rc = ble_phy_tx(ble_ll_adv_pdu_make, advsm, end_trans);
rc = ble_phy_tx(ble_ll_adv_pdu_make, advsm);
#else
rc = ble_phy_tx(ble_ll_adv_legacy_pdu_make, advsm, end_trans);
rc = ble_phy_tx(ble_ll_adv_legacy_pdu_make, advsm);
#endif
if (rc) {
goto adv_tx_done;
Expand Down Expand Up @@ -1268,7 +1267,6 @@ static int
ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
{
int rc;
uint8_t end_trans;
uint32_t txstart;
struct ble_ll_adv_sm *advsm;
ble_phy_tx_pducb_t pducb;
Expand Down Expand Up @@ -1319,22 +1317,22 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)

/* Set phy mode based on type of advertisement */
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
end_trans = BLE_PHY_TRANSITION_TX_RX;
ble_phy_transition_set(BLE_PHY_TRANSITION_TO_RX, BLE_LL_IFS);
ble_phy_set_txend_cb(NULL, NULL);
pducb = ble_ll_adv_aux_pdu_make;
} else if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) &&
advsm->aux_first_pdu) {
end_trans = BLE_PHY_TRANSITION_TX_RX;
ble_phy_transition_set(BLE_PHY_TRANSITION_TO_RX, BLE_LL_IFS);
ble_phy_set_txend_cb(NULL, NULL);
pducb = ble_ll_adv_aux_scannable_pdu_make;
} else {
end_trans = BLE_PHY_TRANSITION_NONE;
ble_phy_transition_set(BLE_PHY_TRANSITION_NONE, 0);
ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
pducb = ble_ll_adv_aux_pdu_make;
}

/* Transmit advertisement */
rc = ble_phy_tx(pducb, advsm, end_trans);
rc = ble_phy_tx(pducb, advsm);
if (rc) {
goto adv_aux_dropped;
}
Expand Down Expand Up @@ -2322,8 +2320,9 @@ ble_ll_adv_sync_tx_start_cb(struct ble_ll_sched_item *sch)
#endif

/* Transmit advertisement */
ble_phy_transition_set(BLE_PHY_TRANSITION_NONE, 0);
ble_phy_set_txend_cb(ble_ll_adv_sync_tx_end, advsm);
rc = ble_phy_tx(ble_ll_adv_sync_pdu_make, advsm, BLE_PHY_TRANSITION_NONE);
rc = ble_phy_tx(ble_ll_adv_sync_pdu_make, advsm);
if (rc) {
goto adv_tx_done;
}
Expand Down Expand Up @@ -4547,6 +4546,8 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
*/
ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);

ble_phy_transition_set(BLE_PHY_TRANSITION_NONE, 0);

#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
if (advsm->flags & BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF) {
ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer,
Expand All @@ -4560,12 +4561,10 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
*/

advsm->rx_ble_hdr = ble_hdr;
rc = ble_phy_tx(ble_ll_adv_scan_rsp_pdu_make, advsm,
BLE_PHY_TRANSITION_NONE);
rc = ble_phy_tx(ble_ll_adv_scan_rsp_pdu_make, advsm);
advsm->rx_ble_hdr = NULL;
#else
rc = ble_phy_tx(ble_ll_adv_scan_rsp_legacy_pdu_make, advsm,
BLE_PHY_TRANSITION_NONE);
rc = ble_phy_tx(ble_ll_adv_scan_rsp_legacy_pdu_make, advsm);
#endif

if (!rc) {
Expand Down Expand Up @@ -4599,9 +4598,9 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
rsp_data.peer = rxbuf + BLE_LL_PDU_HDR_LEN;
rsp_data.rxadd = rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK;

ble_phy_transition_set(BLE_PHY_TRANSITION_NONE, 0);
ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
rc = ble_phy_tx(ble_ll_adv_aux_conn_rsp_pdu_make, &rsp_data,
BLE_PHY_TRANSITION_NONE);
rc = ble_phy_tx(ble_ll_adv_aux_conn_rsp_pdu_make, &rsp_data);
if (!rc) {
ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD);
STATS_INC(ble_ll_stats, aux_conn_rsp_tx);
Expand Down Expand Up @@ -4892,6 +4891,8 @@ ble_ll_adv_rx_isr_start(uint8_t pdu_type)
*/
if (rc < 0) {
ble_ll_adv_tx_done(advsm);
} else if (rc > 0){
ble_phy_transition_set(BLE_PHY_TRANSITION_TO_TX, BLE_LL_IFS);
}

return rc;
Expand Down
12 changes: 7 additions & 5 deletions nimble/controller/src/ble_ll_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
txend_func = ble_ll_conn_wait_txend;
} else {
/* Wait for a response here */
end_transition = BLE_PHY_TRANSITION_TX_RX;
end_transition = BLE_PHY_TRANSITION_TO_RX;
txend_func = NULL;
}

Expand Down Expand Up @@ -1435,9 +1435,9 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
}
#endif

/* Set transmit end callback */
ble_phy_transition_set(end_transition, BLE_LL_IFS);
ble_phy_set_txend_cb(txend_func, connsm);
rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, m, end_transition);
rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, m);
if (!rc) {
/* Log transmit on connection state */
cur_txlen = ble_hdr->txinfo.pyld_len;
Expand Down Expand Up @@ -3269,9 +3269,11 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
ble_ll_conn_prepare_connect_ind(connsm, ble_ll_scan_get_pdu_data(), addrd,
rxhdr->rxinfo.channel);

ble_phy_transition_set(ext ? BLE_PHY_TRANSITION_TO_RX :
BLE_PHY_TRANSITION_NONE,
BLE_LL_IFS);
ble_phy_set_txend_cb(NULL, NULL);
rc = ble_phy_tx(ble_ll_conn_tx_connect_ind_pducb, connsm,
ext ? BLE_PHY_TRANSITION_TX_RX : BLE_PHY_TRANSITION_NONE);
rc = ble_phy_tx(ble_ll_conn_tx_connect_ind_pducb, connsm);
if (rc) {
ble_ll_conn_send_connect_req_cancel();
return -1;
Expand Down
3 changes: 2 additions & 1 deletion nimble/controller/src/ble_ll_dtm.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch)
goto resched;
}

rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, ctx->om, BLE_PHY_TRANSITION_NONE);
ble_phy_transition_set(BLE_PHY_TRANSITION_NONE, 0);
rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, ctx->om);
if (rc) {
goto resched;
}
Expand Down
18 changes: 8 additions & 10 deletions nimble/controller/src/ble_ll_iso_big.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,8 @@ ble_ll_iso_big_control_tx(struct ble_ll_iso_big *big)
ble_phy_set_txend_cb(ble_ll_iso_big_control_txend_cb, big);
ble_phy_setchan(chan_idx, big->ctrl_aa, big->crc_init << 8);

rc = ble_phy_tx(ble_ll_iso_big_control_pdu_cb, big, BLE_PHY_TRANSITION_NONE);
ble_phy_transition_set(BLE_PHY_TRANSITION_NONE, 0);
rc = ble_phy_tx(ble_ll_iso_big_control_pdu_cb, big);

return rc;
}
Expand Down Expand Up @@ -773,9 +774,12 @@ ble_ll_iso_big_subevent_tx(struct ble_ll_iso_big *big)

to_tx = (big->tx.subevents_rem > 1) || big->cstf;

rc = ble_phy_tx(ble_ll_iso_big_subevent_pdu_cb, big,
to_tx ? BLE_PHY_TRANSITION_TX_TX
: BLE_PHY_TRANSITION_NONE);
ble_phy_transition_set(to_tx ? BLE_PHY_TRANSITION_TO_TX_ISO_SUBEVENT :
BLE_PHY_TRANSITION_NONE,
big->interleaved ? big->bis_spacing :
big->sub_interval);

rc = ble_phy_tx(ble_ll_iso_big_subevent_pdu_cb, big);
return rc;
}

Expand Down Expand Up @@ -874,12 +878,6 @@ ble_ll_iso_big_event_sched_cb(struct ble_ll_sched_item *sch)
big->tx.bis = STAILQ_FIRST(&big->bis_q);
big->tx.bis->tx.subevent_num = 1;

if (big->interleaved) {
ble_phy_tifs_txtx_set(big->bis_spacing, 0);
} else {
ble_phy_tifs_txtx_set(big->sub_interval, 0);
}

rc = ble_phy_tx_set_start_time(sch->start_time + g_ble_ll_sched_offset_ticks,
sch->remainder);
if (rc) {
Expand Down
3 changes: 2 additions & 1 deletion nimble/controller/src/ble_ll_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1563,7 +1563,8 @@ ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf,
ble_ll_scan_req_pdu_prepare(scansm, addrd->adva, addrd->adva_type,
rpa_index);

rc = ble_phy_tx(ble_ll_scan_req_tx_pdu_cb, scansm, BLE_PHY_TRANSITION_TX_RX);
ble_phy_transition_set(BLE_PHY_TRANSITION_TO_RX, BLE_LL_IFS);
rc = ble_phy_tx(ble_ll_scan_req_tx_pdu_cb, scansm);
if (rc) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions nimble/controller/src/ble_ll_scan_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,8 +1226,8 @@ ble_ll_scan_aux_send_scan_req(struct ble_ll_scan_aux_data *aux,
* interrupted if scheduler kicks in.
*/

rc = ble_phy_tx(ble_ll_scan_aux_scan_req_tx_pdu_cb, aux,
BLE_PHY_TRANSITION_TX_RX);
ble_phy_transition_set(BLE_PHY_TRANSITION_TO_RX, BLE_LL_IFS);
rc = ble_phy_tx(ble_ll_scan_aux_scan_req_tx_pdu_cb, aux);
if (rc) {
return false;
}
Expand Down
16 changes: 10 additions & 6 deletions nimble/drivers/dialog_cmac/src/ble_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ ble_phy_irq_field_tx_exc_bs_start_4this(void)
{
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_START_4THIS_Msk;

if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) {
if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TO_RX) {
/*
* Setup 2nd frame that will start after current one.
* -2us offset to adjust for allowed active clock accuracy.
Expand Down Expand Up @@ -642,7 +642,7 @@ ble_phy_irq_frame_tx_exc_bs_stop(void)
/* Clear latched timestamp so we do not have error on next frame */
(void)CMAC->CM_TS1_REG;

if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) {
if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TO_RX) {
#if MYNEWT_VAL(BLE_LL_PHY)
ble_phy_mode_apply(g_ble_phy_data.phy_mode_rx);
#endif
Expand All @@ -665,7 +665,7 @@ ble_phy_irq_frame_tx_exc_phy_to_idle_4this(void)
{
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk;

if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) {
if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TO_RX) {
ble_phy_rx_setup_xcvr();

g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
Expand Down Expand Up @@ -1403,7 +1403,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
}

int
ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg)
{
uint8_t *txbuf = g_ble_phy_tx_buf;
int rc;
Expand All @@ -1412,8 +1412,6 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)

assert(CMAC->CM_FRAME_1_REG & CMAC_CM_FRAME_1_REG_FRAME_TX_Msk);

g_ble_phy_data.end_transition = end_trans;

/*
* Program required fields now so in worst case TX can continue while we
* are still preparing header and payload.
Expand Down Expand Up @@ -1829,3 +1827,9 @@ ble_phy_dtm_carrier(uint8_t rf_channel)
}
#endif
#endif

void
ble_phy_transition_set(uint8_t trans, uint16_t usecs)
{
g_ble_phy_data.end_transition = trans;
}
10 changes: 4 additions & 6 deletions nimble/drivers/native/src/ble_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ ble_phy_isr(void)
ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_TX_END);

transition = g_ble_phy_data.phy_transition;
if (transition == BLE_PHY_TRANSITION_TX_RX) {
if (transition == BLE_PHY_TRANSITION_TO_RX) {
/* Disable the phy */
/* XXX: count no bufs? */
ble_phy_disable();
Expand Down Expand Up @@ -422,7 +422,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)


int
ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg)
{
uint8_t hdr_byte;
int rc;
Expand All @@ -440,9 +440,6 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
} else {
}

/* Set the PHY transition */
g_ble_phy_data.phy_transition = end_trans;

/* Set phy state to transmitting and count packet statistics */
g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
++g_ble_phy_stats.tx_good;
Expand Down Expand Up @@ -662,6 +659,7 @@ ble_phy_rfclk_disable(void)
}

void
ble_phy_tifs_txtx_set(uint16_t usecs, uint8_t anchor)
ble_phy_transition_set(uint8_t trans, uint16_t usecs)
{
g_ble_phy_data.phy_transition = trans;
}
Loading

0 comments on commit d5999ac

Please sign in to comment.