diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 1a394d38351..0bf92079d09 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -176,6 +176,22 @@ config BT_CTLR_ADV_PDU_LINK is required to enable advertising data trains (i.e. transmission of AUX_CHAIN_IND). +config BT_CTLR_ADV_PDU_BACK2BACK + bool "Enable back-to-back transmission of extended advertising trains" + depends on BT_CTLR_ADV_EXT && BT_BROADCASTER + select BT_CTLR_ADV_PDU_LINK + help + Enables transmission of AUX_CHAIN_IND in extended advertising train by + sending each AUX_CHAIN_IND one after another back-to-back. + +config BT_CTLR_ADV_PDU_BACK2BACK_AFS + int "AUX Frame Space for back-to-back transmission of extended advertising trains" + depends on BT_CTLR_ADV_PDU_BACK2BACK + range 300 1000 + help + Specific AUX Frame Space to be used for back-to-back transmission of + extended advertising trains. Time specified in microseconds. + config BT_CTLR_ADV_SYNC_PDU_BACK2BACK bool "Enable back-to-back transmission of periodic advertising trains" depends on BT_CTLR_ADV_PERIODIC diff --git a/subsys/bluetooth/controller/ll_sw/lll_adv.h b/subsys/bluetooth/controller/ll_sw/lll_adv.h index 11bd3cb4b0e..ca93de14ca7 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_adv.h +++ b/subsys/bluetooth/controller/ll_sw/lll_adv.h @@ -67,6 +67,9 @@ struct lll_adv_aux { uint32_t ticks_offset; struct lll_adv_pdu data; +#if defined(CONFIG_BT_CTLR_ADV_PDU_LINK) + struct pdu_adv *last_pdu; +#endif /* CONFIG_BT_CTLR_ADV_PDU_LINK */ #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) int8_t tx_pwr_lvl; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c index dd068af9492..7bec7d08f4f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c @@ -46,7 +46,10 @@ static int init_reset(void); static int prepare_cb(struct lll_prepare_param *p); static void isr_done(void *param); -static void isr_tx(void *param); +#if defined(CONFIG_BT_CTLR_ADV_PDU_BACK2BACK) +static void isr_tx_chain(void *param); +#endif /* CONFIG_BT_CTLR_ADV_PDU_BACK2BACK */ +static void isr_tx_rx(void *param); static void isr_rx(void *param); static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux, uint8_t devmatch_ok, uint8_t devmatch_id, @@ -224,9 +227,21 @@ static int prepare_cb(struct lll_prepare_param *p) ARG_UNUSED(upd); #endif /* !CONFIG_BT_CTLR_PRIVACY */ - radio_isr_set(isr_tx, lll); + radio_isr_set(isr_tx_rx, lll); radio_tmr_tifs_set(EVENT_IFS_US); radio_switch_complete_and_rx(phy_s); + +#if defined(CONFIG_BT_CTLR_ADV_PDU_BACK2BACK) + } else if (sec_pdu->adv_ext_ind.ext_hdr_len && + sec_pdu->adv_ext_ind.ext_hdr.aux_ptr) { + lll->last_pdu = sec_pdu; + + radio_isr_set(isr_tx_chain, lll); + radio_tmr_tifs_set(EVENT_B2B_MAFS_US); + radio_switch_complete_and_b2b_tx(phy_s, lll_adv->phy_flags, + phy_s, lll_adv->phy_flags); +#endif /* CONFIG_BT_CTLR_ADV_PDU_BACK2BACK */ + } else { radio_isr_set(isr_done, lll); radio_switch_complete_and_disable(); @@ -290,7 +305,77 @@ static void isr_done(void *param) lll_isr_cleanup(param); } -static void isr_tx(void *param) +#if defined(CONFIG_BT_CTLR_ADV_PDU_BACK2BACK) +static void isr_tx_chain(void *param) +{ + struct lll_adv_aux *lll_aux; + struct lll_adv *lll; + struct pdu_adv *pdu; + + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_latency_capture(); + } + + /* Clear radio tx status and events */ + lll_isr_tx_status_reset(); + + lll_aux = param; + lll = lll_aux->adv; + + /* FIXME: Use implementation defined channel index */ + lll_chan_set(0); + + pdu = lll_adv_pdu_linked_next_get(lll_aux->last_pdu); + LL_ASSERT(pdu); + lll_aux->last_pdu = pdu; + + /* setup tIFS switching */ + if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) { + radio_isr_set(isr_tx_chain, lll_aux); + radio_tmr_tifs_set(EVENT_B2B_MAFS_US); + radio_switch_complete_and_b2b_tx(lll->phy_s, lll->phy_flags, + lll->phy_s, lll->phy_flags); + } else { + radio_isr_set(isr_done, lll_aux); + radio_switch_complete_and_disable(); + } + + radio_pkt_tx_set(pdu); + + /* assert if radio packet ptr is not set and radio started rx */ + LL_ASSERT(!radio_is_ready()); + + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_cputime_capture(); + } + + /* capture end of AUX_SYNC_IND/AUX_CHAIN_IND PDU, used for calculating + * next PDU timestamp. + */ + radio_tmr_end_capture(); + +#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN) + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + /* PA/LNA enable is overwriting packet end used in ISR + * profiling, hence back it up for later use. + */ + lll_prof_radio_end_backup(); + } + + radio_gpio_lna_setup(); + radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_B2B_MAFS_US - + 4 - radio_tx_chain_delay_get(lll->phy_s, + lll->phy_flags) - + CONFIG_BT_CTLR_GPIO_LNA_OFFSET); +#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */ + + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_send(); + } +} +#endif /* CONFIG_BT_CTLR_ADV_PDU_BACK2BACK */ + +static void isr_tx_rx(void *param) { struct node_rx_pdu *node_rx_prof; struct node_rx_pdu *node_rx; diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index bd865470824..264affa3a9d 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -93,6 +93,8 @@ #define EVENT_MAFS_US 300 /* Standard allows 2 us timing uncertainty inside the event */ #define EVENT_MAFS_MAX_US (EVENT_MAFS_US + EVENT_CLOCK_JITTER_US) +/* Controller defined back to back transmit MAFS */ +#define EVENT_B2B_MAFS_US (CONFIG_BT_CTLR_ADV_PDU_BACK2BACK_AFS) /* Minimum Subevent Space timings */ #define EVENT_MSS_US 150 /* Standard allows 2 us timing uncertainty inside the event */ diff --git a/tests/bluetooth/init/prj_ctlr_dbg.conf b/tests/bluetooth/init/prj_ctlr_dbg.conf index 03f5ba59fd5..a3e1db67aa0 100644 --- a/tests/bluetooth/init/prj_ctlr_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_dbg.conf @@ -16,6 +16,7 @@ CONFIG_BT_CTLR_ADVANCED_FEATURES=y CONFIG_BT_CTLR_PHY_2M=y CONFIG_BT_CTLR_PHY_2M_NRF=y CONFIG_BT_CTLR_PHY_CODED=y +CONFIG_BT_CTLR_ADV_PDU_BACK2BACK=y CONFIG_BT_CTLR_LLL_PRIO=0 CONFIG_BT_CTLR_ULL_HIGH_PRIO=1 CONFIG_BT_CTLR_XTAL_ADVANCED=n