diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 9c326b35cf6f4..bd366758dcd0c 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -900,6 +900,13 @@ config BT_CTLR_RADIO_ENABLE_FAST help Enable use of fast radio ramp-up mode. +config BT_CTLR_RADIO_TIMER_ISR + # Hidden, enables use of timer ISR callback + bool + depends on SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X + help + Enables use of timer ISR callback. + config BT_CTLR_TIFS_HW bool "H/w Accelerated tIFS Trx switching" depends on !BT_CTLR_RADIO_ENABLE_FAST && BT_CTLR_TIFS_HW_SUPPORT @@ -1013,6 +1020,14 @@ config BT_CTLR_TX_RETRY_DISABLE would happen in the next connection event instead of repeated retries in the current connection event. +config BT_CTLR_TX_DEFER + bool "Deferred ACL Tx packet transmission setup" + select BT_CTLR_RADIO_TIMER_ISR + help + Enable deferred ACL Tx packet transmission setup by radio, so that an + enqueued ACL Data packet by the upper layer can be transmitted with + the shortest latency. + config BT_CTLR_THROUGHPUT bool "Measure incoming Tx throughput" help @@ -1073,6 +1088,19 @@ config BT_CTLR_ALLOW_SAME_PEER_CONN WARNING: This option enables behavior that violates the Bluetooth specification. +config BT_CTLR_CONN_INTERVAL_LOW_LATENCY + bool "Allow low latency connection intervals" + help + Allow low latency connection intervals. + +config BT_CTLR_EVENT_IFS_LOW_LAT_US + prompt "Low latency tIFS value in microseconds" if BT_CTLR_CONN_INTERVAL_LOW_LATENCY + int + default 52 if BT_CTLR_CONN_INTERVAL_LOW_LATENCY + default 150 + help + Set low latency tIFS value. + endif # BT_CONN config BT_CTLR_ADV_INDICATION diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index 4cecde96f8ebb..8aea8bed0b814 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -16,11 +16,12 @@ #define EVENT_PIPELINE_MAX 7 -#define ADV_INT_UNIT_US 625U -#define SCAN_INT_UNIT_US 625U -#define CONN_INT_UNIT_US 1250U -#define ISO_INT_UNIT_US CONN_INT_UNIT_US -#define PERIODIC_INT_UNIT_US CONN_INT_UNIT_US +#define ADV_INT_UNIT_US 625U +#define SCAN_INT_UNIT_US 625U +#define CONN_INT_UNIT_US 1250U +#define ISO_INT_UNIT_US CONN_INT_UNIT_US +#define PERIODIC_INT_UNIT_US CONN_INT_UNIT_US +#define CONN_LOW_LAT_INT_UNIT_US 500U #define ISO_INTERVAL_TO_US(interval) ((interval) * ISO_INT_UNIT_US) diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn.h b/subsys/bluetooth/controller/ll_sw/lll_conn.h index b57e4db5ea24c..19a7820ed9492 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn.h @@ -43,10 +43,15 @@ struct lll_conn { uint8_t access_addr[4]; uint8_t crc_init[3]; + uint16_t tifs_tx_us; + uint16_t tifs_rx_us; + uint16_t tifs_hcto_us; + uint16_t tifs_cis_us; + uint16_t handle; uint16_t interval; - uint16_t latency; + uint16_t latency; uint16_t latency_prepare; uint16_t lazy_prepare; uint16_t latency_event; @@ -170,7 +175,10 @@ int lll_conn_reset(void); void lll_conn_flush(uint16_t handle, struct lll_conn *lll); void lll_conn_prepare_reset(void); -int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb); +int lll_conn_central_is_abort_cb(void *next, void *curr, + lll_prepare_cb_t *resume_cb); +int lll_conn_peripheral_is_abort_cb(void *next, void *curr, + lll_prepare_cb_t *resume_cb); void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param); void lll_conn_isr_rx(void *param); void lll_conn_isr_tx(void *param); diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h index a8c1d5325905e..31e2f70fcd61b 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h @@ -36,6 +36,11 @@ struct lll_conn_iso_stream { uint32_t offset; /* Offset of CIS from start of CIG in us */ uint32_t sub_interval; /* Interval between subevents in us */ uint8_t nse:5; /* Number of subevents */ + + /* Frame Spacing */ + uint16_t tifs_us; + + /* Stream parameters */ struct lll_conn_iso_stream_rxtx rx; /* RX parameters */ struct lll_conn_iso_stream_rxtx tx; /* TX parameters */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 175a76ecae6c5..f372ef667d0a0 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -620,7 +620,7 @@ uint32_t radio_is_done(void) * Note: this depends on the function being called exactly once * in the ISR function. */ - last_pdu_end_us += EVENT_TIMER->CC[2]; + last_pdu_end_us += EVENT_TIMER->CC[HAL_EVENT_TIMER_TRX_END_CC_OFFSET]; return 1; } else { return 0; @@ -1153,6 +1153,56 @@ uint32_t radio_bc_has_match(void) return (NRF_RADIO->EVENTS_BCMATCH != 0); } +#if defined(CONFIG_BT_CTLR_RADIO_TIMER_ISR) +static radio_isr_cb_t isr_radio_tmr_cb; +static void *isr_radio_tmr_cb_param; + +void isr_radio_tmr(void) +{ + irq_disable(TIMER0_IRQn); + nrf_timer_int_disable(EVENT_TIMER, TIMER_INTENSET_COMPARE2_Msk); + nrf_timer_event_clear(EVENT_TIMER, HAL_EVENT_TIMER_DEFERRED_TX_EVENT); + + isr_radio_tmr_cb(isr_radio_tmr_cb_param); +} + +uint32_t radio_tmr_isr_set(uint32_t start_us, radio_isr_cb_t cb, void *param) +{ + irq_disable(TIMER0_IRQn); + + isr_radio_tmr_cb_param = param; + isr_radio_tmr_cb = cb; + + /* start_us could be the current count in the timer */ + uint32_t now_us = start_us; + + /* Setup timer compare while determining the latency in doing so */ + do { + /* Set start to be, now plus the determined latency */ + start_us = (now_us << 1) - start_us; + + /* Setup compare event with min. 1 us offset */ + nrf_timer_event_clear(EVENT_TIMER, HAL_EVENT_TIMER_DEFERRED_TX_EVENT); + nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_DEFERRED_TRX_CC_OFFSET, + start_us + 1U); + + /* Capture the current time */ + nrf_timer_task_trigger(EVENT_TIMER, HAL_EVENT_TIMER_SAMPLE_TASK); + + now_us = EVENT_TIMER->CC[HAL_EVENT_TIMER_SAMPLE_CC_OFFSET]; + } while ((now_us > start_us) && + (EVENT_TIMER->EVENTS_COMPARE[HAL_EVENT_TIMER_DEFERRED_TRX_CC_OFFSET] == 0U)); + + nrf_timer_int_enable(EVENT_TIMER, TIMER_INTENSET_COMPARE2_Msk); + + NVIC_ClearPendingIRQ(TIMER0_IRQn); + + irq_enable(TIMER0_IRQn); + + return start_us + 1U; +} +#endif /* CONFIG_BT_CTLR_RADIO_TIMER_ISR */ + void radio_tmr_status_reset(void) { #if defined(CONFIG_BT_CTLR_NRF_GRTC) @@ -1362,7 +1412,7 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder) EVENT_TIMER->PRESCALER = HAL_EVENT_TIMER_PRESCALER_VALUE; EVENT_TIMER->BITMODE = 2; /* 24 - bit */ - nrf_timer_cc_set(EVENT_TIMER, 0, remainder); + nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_TRX_CC_OFFSET, remainder); #if defined(CONFIG_BT_CTLR_NRF_GRTC) uint32_t cntr_l, cntr_h, cntr_h_overflow, stale; @@ -1486,7 +1536,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start) nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_STOP); nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CLEAR); - nrf_timer_cc_set(EVENT_TIMER, 0, remainder_us); + nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_TRX_CC_OFFSET, remainder_us); #if defined(CONFIG_BT_CTLR_NRF_GRTC) uint32_t cntr_l, cntr_h, cntr_h_overflow, stale; @@ -1602,7 +1652,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) uint32_t now_us = start_us; uint32_t actual_us; - /* Setup PPI while determining the latency in doing so */ + /* Setup timer compare while determining the latency in doing so */ do { /* Set start to be, now plus the determined latency */ start_us = (now_us << 1) - start_us; @@ -1624,15 +1674,15 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) actual_us += latency_us; #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ - nrf_timer_event_clear(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE0); - nrf_timer_cc_set(EVENT_TIMER, 0, actual_us); + nrf_timer_event_clear(EVENT_TIMER, HAL_EVENT_TIMER_TRX_EVENT); + nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_TRX_CC_OFFSET, actual_us); /* Capture the current time */ - nrf_timer_task_trigger(EVENT_TIMER, - HAL_EVENT_TIMER_SAMPLE_TASK); + nrf_timer_task_trigger(EVENT_TIMER, HAL_EVENT_TIMER_SAMPLE_TASK); now_us = EVENT_TIMER->CC[HAL_EVENT_TIMER_SAMPLE_CC_OFFSET]; - } while ((now_us > start_us) && (EVENT_TIMER->EVENTS_COMPARE[0] == 0U)); + } while ((now_us > start_us) && + (EVENT_TIMER->EVENTS_COMPARE[HAL_EVENT_TIMER_TRX_CC_OFFSET] == 0U)); return actual_us; } @@ -1688,7 +1738,7 @@ void radio_tmr_stop(void) void radio_tmr_hcto_configure(uint32_t hcto) { - nrf_timer_cc_set(EVENT_TIMER, 1, hcto); + nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_HCTO_CC_OFFSET, hcto); hal_radio_recv_timeout_cancel_ppi_config(); hal_radio_disable_on_hcto_ppi_config(); @@ -1708,7 +1758,7 @@ void radio_tmr_aa_capture(void) uint32_t radio_tmr_aa_get(void) { - return EVENT_TIMER->CC[1]; + return EVENT_TIMER->CC[HAL_EVENT_TIMER_HCTO_CC_OFFSET]; } static uint32_t radio_tmr_aa; @@ -1726,7 +1776,7 @@ uint32_t radio_tmr_aa_restore(void) uint32_t radio_tmr_ready_get(void) { - return EVENT_TIMER->CC[0]; + return EVENT_TIMER->CC[HAL_EVENT_TIMER_TRX_CC_OFFSET]; } static uint32_t radio_tmr_ready; @@ -1765,7 +1815,7 @@ uint32_t radio_tmr_end_get(void) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) return last_pdu_end_us; #else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ - return EVENT_TIMER->CC[2]; + return EVENT_TIMER->CC[HAL_EVENT_TIMER_TRX_END_CC_OFFSET]; #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ } @@ -1909,9 +1959,10 @@ void radio_gpio_lna_off(void) void radio_gpio_pa_lna_enable(uint32_t trx_us) { - nrf_timer_cc_set(EVENT_TIMER, 2, trx_us); + nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_PA_LNA_CC_OFFSET, trx_us); #if defined(HAL_RADIO_FEM_IS_NRF21540) && DT_NODE_HAS_PROP(FEM_NODE, pdn_gpios) - nrf_timer_cc_set(EVENT_TIMER, 3, (trx_us - NRF_GPIO_PDN_OFFSET)); + nrf_timer_cc_set(EVENT_TIMER, HAL_EVENT_TIMER_PA_LNA_PDN_CC_OFFSET, + (trx_us - NRF_GPIO_PDN_OFFSET)); hal_radio_nrf_ppi_channels_enable(BIT(HAL_ENABLE_PALNA_PPI) | BIT(HAL_DISABLE_PALNA_PPI) | BIT(HAL_ENABLE_FEM_PPI) | diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h index eac3381c8824d..bc5d1605302c2 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h @@ -130,6 +130,9 @@ void radio_bc_configure(uint32_t n); void radio_bc_status_reset(void); uint32_t radio_bc_has_match(void); +void isr_radio_tmr(void); +uint32_t radio_tmr_isr_set(uint32_t start_us, radio_isr_cb_t cb, void *param); + void radio_tmr_status_reset(void); void radio_tmr_tx_status_reset(void); void radio_tmr_rx_status_reset(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index 414e4a0dbb562..327888e4dfecd 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -109,3 +109,6 @@ #else /* For simulated targets there is no delay for the PPI task -> TIMER start */ #define HAL_RADIO_TMR_START_DELAY_US 0U #endif + +/* This is the minimum prepare duration required to setup radio for deferred transmission */ +#define HAL_RADIO_TMR_DEFERRED_TX_DELAY_US 50U diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h index 7a8fd0e8f13f2..618e1535839ee 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h @@ -25,8 +25,20 @@ */ #define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk -#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 -#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 +#define HAL_EVENT_TIMER_TRX_CC_OFFSET 0 +#define HAL_EVENT_TIMER_TRX_EVENT NRF_TIMER_EVENT_COMPARE0 + +#define HAL_EVENT_TIMER_HCTO_CC_OFFSET 1 +#define HAL_EVENT_TIMER_TRX_END_CC_OFFSET 2 + +#define HAL_EVENT_TIMER_DEFERRED_TRX_CC_OFFSET 2 +#define HAL_EVENT_TIMER_DEFERRED_TX_EVENT NRF_TIMER_EVENT_COMPARE2 + +#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 +#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 + +#define HAL_EVENT_TIMER_PA_LNA_CC_OFFSET 2 +#define HAL_EVENT_TIMER_PA_LNA_PDN_CC_OFFSET 3 #else /* !CONFIG_BT_CTLR_TIFS_HW */ #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) @@ -56,8 +68,20 @@ */ #define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk -#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2 -#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2 +#define HAL_EVENT_TIMER_TRX_CC_OFFSET 0 +#define HAL_EVENT_TIMER_TRX_EVENT NRF_TIMER_EVENT_COMPARE0 + +#define HAL_EVENT_TIMER_HCTO_CC_OFFSET 1 +#define HAL_EVENT_TIMER_TRX_END_CC_OFFSET 2 + +#define HAL_EVENT_TIMER_DEFERRED_TRX_CC_OFFSET 2 +#define HAL_EVENT_TIMER_DEFERRED_TX_EVENT NRF_TIMER_EVENT_COMPARE2 + +#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2 +#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2 + +#define HAL_EVENT_TIMER_PA_LNA_CC_OFFSET 2 +#define HAL_EVENT_TIMER_PA_LNA_PDN_CC_OFFSET 3 #else /* !CONFIG_BT_CTLR_PHY_CODED */ #define SW_SWITCH_TIMER_EVTS_COMP_BASE 4 @@ -73,8 +97,20 @@ */ #define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk -#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 -#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 +#define HAL_EVENT_TIMER_TRX_CC_OFFSET 0 +#define HAL_EVENT_TIMER_TRX_EVENT NRF_TIMER_EVENT_COMPARE0 + +#define HAL_EVENT_TIMER_HCTO_CC_OFFSET 1 +#define HAL_EVENT_TIMER_TRX_END_CC_OFFSET 2 + +#define HAL_EVENT_TIMER_DEFERRED_TRX_CC_OFFSET 2 +#define HAL_EVENT_TIMER_DEFERRED_TX_EVENT NRF_TIMER_EVENT_COMPARE2 + +#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 +#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 + +#define HAL_EVENT_TIMER_PA_LNA_CC_OFFSET 2 +#define HAL_EVENT_TIMER_PA_LNA_PDN_CC_OFFSET 3 #endif /* !CONFIG_BT_CTLR_PHY_CODED */ #else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ @@ -142,7 +178,19 @@ #define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk #endif /* !CONFIG_BT_CTLR_DF */ -#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 -#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 +#define HAL_EVENT_TIMER_TRX_CC_OFFSET 0 +#define HAL_EVENT_TIMER_TRX_EVENT NRF_TIMER_EVENT_COMPARE0 + +#define HAL_EVENT_TIMER_HCTO_CC_OFFSET 1 +#define HAL_EVENT_TIMER_TRX_END_CC_OFFSET 2 + +#define HAL_EVENT_TIMER_DEFERRED_TRX_CC_OFFSET 2 +#define HAL_EVENT_TIMER_DEFERRED_TX_EVENT NRF_TIMER_EVENT_COMPARE2 + +#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 +#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 + +#define HAL_EVENT_TIMER_PA_LNA_CC_OFFSET 2 +#define HAL_EVENT_TIMER_PA_LNA_PDN_CC_OFFSET 3 #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 098fd309352be..ebfdf364941ea 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -115,6 +115,33 @@ ISR_DIRECT_DECLARE(radio_nrf5_isr) #endif /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ } +#if defined(CONFIG_BT_CTLR_RADIO_TIMER_ISR) +#if defined(CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS) && \ + defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) +static void timer_nrf5_isr(const void *arg) +#else /* !CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS */ +ISR_DIRECT_DECLARE(timer_nrf5_isr) +#endif /* !CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS */ +{ + DEBUG_RADIO_ISR(1); + + lll_prof_enter_radio(); + + isr_radio_tmr(); + + ISR_DIRECT_PM(); + + lll_prof_exit_radio(); + + DEBUG_RADIO_ISR(0); + +#if !defined(CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS) || \ + !defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) + return 1; +#endif /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ +} +#endif /* CONFIG_BT_CTLR_RADIO_TIMER_ISR */ + static void rtc0_nrf5_isr(const void *arg) { DEBUG_TICKER_ISR(1); @@ -221,9 +248,19 @@ int lll_init(void) IRQ_CONNECT_FLAGS, no_reschedule); irq_connect_dynamic(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); +#if defined(CONFIG_BT_CTLR_RADIO_TIMER_ISR) + ARM_IRQ_DIRECT_DYNAMIC_CONNECT(TIMER0_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + IRQ_CONNECT_FLAGS, no_reschedule); + irq_connect_dynamic(TIMER0_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + timer_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); +#endif /* CONFIG_BT_CTLR_RADIO_TIMER_ISR */ #else /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ IRQ_DIRECT_CONNECT(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, IRQ_CONNECT_FLAGS); +#if defined(CONFIG_BT_CTLR_RADIO_TIMER_ISR) + IRQ_DIRECT_CONNECT(TIMER0_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + timer_nrf5_isr, IRQ_CONNECT_FLAGS); +#endif /* CONFIG_BT_CTLR_RADIO_TIMER_ISR */ #endif /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ irq_connect_dynamic(HAL_RTC_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, rtc0_nrf5_isr, NULL, 0U); @@ -238,6 +275,10 @@ int lll_init(void) #else /* !CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS */ IRQ_DIRECT_CONNECT(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, IRQ_CONNECT_FLAGS); +#if defined(CONFIG_BT_CTLR_RADIO_TIMER_ISR) + IRQ_DIRECT_CONNECT(TIMER0_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + timer_nrf5_isr, IRQ_CONNECT_FLAGS); +#endif /* CONFIG_BT_CTLR_RADIO_TIMER_ISR */ IRQ_CONNECT(HAL_RTC_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, rtc0_nrf5_isr, NULL, 0); #if defined(CONFIG_BT_CTLR_ZLI) @@ -298,6 +339,10 @@ int lll_deinit(void) #if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) irq_disconnect_dynamic(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); +#if defined(CONFIG_BT_CTLR_RADIO_TIMER_ISR) + irq_disconnect_dynamic(TIMER0_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + timer_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); +#endif /* CONFIG_BT_CTLR_RADIO_TIMER_ISR */ #endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ irq_disconnect_dynamic(HAL_RTC_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, rtc0_nrf5_isr, NULL, 0U); @@ -1266,10 +1311,15 @@ static void preempt(void *param) /* Check if current event want to continue */ err = event.curr.is_abort_cb(ready->prepare_param.param, event.curr.param, &resume_cb); - if (!err) { - /* Let preemptor LLL know about the cancelled prepare */ - ready->is_aborted = 1; - ready->abort_cb(&ready->prepare_param, ready->prepare_param.param); + if (!err || (err == -EBUSY)) { + /* Returns -EBUSY when same curr and next state/role, do not + * abort same curr and next event. + */ + if (err != -EBUSY) { + /* Let preemptor LLL know about the cancelled prepare */ + ready->is_aborted = 1; + ready->abort_cb(&ready->prepare_param, ready->prepare_param.param); + } return; } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c index 7a8405de84c9e..0fd8a368047e1 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c @@ -75,8 +75,8 @@ void lll_central_prepare(void *param) LL_ASSERT(err >= 0); /* Invoke common pipeline handling of prepare */ - err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, - param); + err = lll_prepare(lll_conn_central_is_abort_cb, lll_conn_abort_cb, + prepare_cb, 0, param); LL_ASSERT(!err || err == -EINPROGRESS); } @@ -186,7 +186,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_isr_set(lll_conn_isr_tx, lll); - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(lll->tifs_rx_us); #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /* If CTE RX is enabled and the PHY is not CODED, store channel used for diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index 218a1d133c094..4b4a76a3dec2e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -306,7 +306,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_isr_set(isr_tx, cis_lll); - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(cis_lll->tifs_us); #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_rx(cis_lll->rx.phy); @@ -501,7 +501,7 @@ static void isr_tx(void *param) LL_ASSERT(!radio_is_ready()); /* +/- 2us active clock jitter, +1 us PPI to timer start compensation */ - hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + + hcto = radio_tmr_tifs_base_get() + cis_lll->tifs_us + (EVENT_CLOCK_JITTER_US << 1) + RANGE_DELAY_US + HAL_RADIO_TMR_START_DELAY_US; @@ -527,13 +527,13 @@ static void isr_tx(void *param) radio_gpio_lna_setup(); #if defined(CONFIG_BT_CTLR_PHY) - radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - + radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + cis_lll->tifs_us - (EVENT_CLOCK_JITTER_US << 1) - radio_tx_chain_delay_get(cis_lll->tx.phy, cis_lll->tx.phy_flags) - HAL_RADIO_GPIO_LNA_OFFSET); #else /* !CONFIG_BT_CTLR_PHY */ - radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - + radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + cis_lll->tifs_us - (EVENT_CLOCK_JITTER_US << 1) - radio_tx_chain_delay_get(0U, 0U) - HAL_RADIO_GPIO_LNA_OFFSET); @@ -1044,7 +1044,7 @@ static void isr_prepare_subevent(void *param) radio_tmr_rx_disable(); radio_tmr_tx_enable(); - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(cis_lll->tifs_us); #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_rx(cis_lll->rx.phy); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 6f41be448486f..4f61cba9665bc 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -48,11 +48,18 @@ static void isr_done(void *param); static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx, uint8_t *is_rx_enqueue, struct node_tx **tx_release, uint8_t *is_done); + +#if defined(CONFIG_BT_CTLR_TX_DEFER) +static void isr_tx_deferred_set(void *param); +#endif /* CONFIG_BT_CTLR_TX_DEFER */ + static void empty_tx_init(void); + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) static inline bool create_iq_report(struct lll_conn *lll, uint8_t rssi_ready, uint8_t packet_status); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) static struct pdu_data *get_last_tx_pdu(struct lll_conn *lll); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ @@ -150,7 +157,9 @@ void lll_conn_prepare_reset(void) #endif /* CONFIG_BT_CTLR_LE_ENC */ } -int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) +#if defined(CONFIG_BT_CENTRAL) +int lll_conn_central_is_abort_cb(void *next, void *curr, + lll_prepare_cb_t *resume_cb) { struct lll_conn *lll = curr; @@ -159,8 +168,38 @@ int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) return 0; } + /* Do not be aborted by same event if a single central trx has not been + * exchanged. + */ + if ((next == curr) && (trx_cnt < 1U)) { + return -EBUSY; + } + return -ECANCELED; } +#endif /* CONFIG_BT_CENTRAL */ + +#if defined(CONFIG_BT_PERIPHERAL) +int lll_conn_peripheral_is_abort_cb(void *next, void *curr, + lll_prepare_cb_t *resume_cb) +{ + struct lll_conn *lll = curr; + + /* Do not abort if near supervision timeout */ + if (lll->forced) { + return 0; + } + + /* Do not be aborted by same event if a single peripheral trx has not + * been exchanged. + */ + if ((next == curr) && (trx_cnt <= 1U)) { + return -EBUSY; + } + + return -ECANCELED; +} +#endif /* CONFIG_BT_PERIPHERAL */ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param) { @@ -365,7 +404,8 @@ void lll_conn_isr_rx(void *param) } /* Decide on event continuation and hence Radio Shorts to use */ - is_done = is_done || ((crc_ok) && (pdu_data_rx->md == 0) && + is_done = is_done || ((crc_ok) && + (pdu_data_rx->md == 0) && (pdu_data_tx->md == 0) && (pdu_data_tx->len == 0)); @@ -395,7 +435,7 @@ void lll_conn_isr_rx(void *param) #endif /* CONFIG_BT_PERIPHERAL */ } } else { - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(lll->tifs_rx_us); #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_rx(lll->phy_rx); @@ -428,7 +468,7 @@ void lll_conn_isr_rx(void *param) radio_gpio_pa_setup(); pa_lna_enable_us = - radio_tmr_tifs_base_get() + EVENT_IFS_US + cte_len - HAL_RADIO_GPIO_PA_OFFSET; + radio_tmr_tifs_base_get() + lll->tifs_tx_us - cte_len - HAL_RADIO_GPIO_PA_OFFSET; #if defined(CONFIG_BT_CTLR_PHY) pa_lna_enable_us -= radio_rx_chain_delay_get(lll->phy_rx, PHY_FLAGS_S8); #else /* !CONFIG_BT_CTLR_PHY */ @@ -445,6 +485,22 @@ void lll_conn_isr_rx(void *param) LL_ASSERT(!radio_is_address()); } +#if defined(CONFIG_BT_CTLR_TX_DEFER) + if (!is_empty_pdu_tx_retry && (pdu_data_tx->len == 0U)) { + uint32_t tx_defer_us; + uint32_t defer_us; + + /* Restore state if transmission setup for empty PDU */ + lll->empty = 0U; + + /* Setup deferred tx packet set */ + tx_defer_us = radio_tmr_tifs_base_get() + lll->tifs_tx_us - + HAL_RADIO_TMR_DEFERRED_TX_DELAY_US; + defer_us = radio_tmr_isr_set(tx_defer_us, isr_tx_deferred_set, + param); + } +#endif /* CONFIG_BT_CTLR_TX_DEFER */ + lll_conn_isr_rx_exit: /* Save the AA captured for the first Rx in connection event */ if (!radio_tmr_aa_restore()) { @@ -551,11 +607,11 @@ void lll_conn_isr_tx(void *param) /* Clear radio tx status and events */ lll_isr_tx_status_reset(); - /* setup tIFS switching */ - radio_tmr_tifs_set(EVENT_IFS_US); - lll = param; + /* setup tIFS switching */ + radio_tmr_tifs_set(lll->tifs_tx_us); + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) enum radio_end_evt_delay_state end_evt_delay; @@ -592,6 +648,7 @@ void lll_conn_isr_tx(void *param) #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) /* Use special API for SOC that requires compensation for PHYEND event delay. */ + #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_with_delay_compensation_and_tx(lll->phy_rx, 0, lll->phy_tx, lll->phy_flags, end_evt_delay); @@ -636,7 +693,7 @@ void lll_conn_isr_tx(void *param) #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ /* +/- 2us active clock jitter, +1 us PPI to timer start compensation */ - hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + + hcto = radio_tmr_tifs_base_get() + lll->tifs_hcto_us + (EVENT_CLOCK_JITTER_US << 1) + RANGE_DELAY_US + HAL_RADIO_TMR_START_DELAY_US; #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) @@ -666,20 +723,26 @@ void lll_conn_isr_tx(void *param) } #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \ + defined(CONFIG_BT_CTLR_TX_DEFER) || \ defined(HAL_RADIO_GPIO_HAVE_PA_PIN) radio_tmr_end_capture(); -#endif /* CONFIG_BT_CTLR_PROFILE_ISR */ +#endif /* CONFIG_BT_CTLR_PROFILE_ISR || + * CONFIG_BT_CTLR_TX_DEFER || + * HAL_RADIO_GPIO_HAVE_PA_PIN + */ #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) radio_gpio_lna_setup(); #if defined(CONFIG_BT_CTLR_PHY) - radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 - + radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + lll->tifs_rx_us - + (EVENT_CLOCK_JITTER_US << 1) - radio_tx_chain_delay_get(lll->phy_tx, lll->phy_flags) - HAL_RADIO_GPIO_LNA_OFFSET); #else /* !CONFIG_BT_CTLR_PHY */ - radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 - - radio_tx_chain_delay_get(0, 0) - + radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + lll->tifs_rx_us - + (EVENT_CLOCK_JITTER_US << 1) - + radio_tx_chain_delay_get(0U, 0U) - HAL_RADIO_GPIO_LNA_OFFSET); #endif /* !CONFIG_BT_CTLR_PHY */ #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */ @@ -1123,6 +1186,25 @@ static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx, return 0; } +#if defined(CONFIG_BT_CTLR_TX_DEFER) +static void isr_tx_deferred_set(void *param) +{ + struct pdu_data *pdu_data_tx; + struct lll_conn *lll; + + /* Prepare Tx PDU, maybe we have non-empty PDU when we check here */ + lll = param; + lll_conn_pdu_tx_prep(lll, &pdu_data_tx); + + /* Fill sn and nesn */ + pdu_data_tx->sn = lll->sn; + pdu_data_tx->nesn = lll->nesn; + + /* setup the radio tx packet buffer */ + lll_conn_tx_pkt_set(lll, pdu_data_tx); +} +#endif /* CONFIG_BT_CTLR_TX_DEFER */ + static void empty_tx_init(void) { struct pdu_data *p; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c index b8e82692e3c0d..c15ca24eb9096 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c @@ -80,8 +80,8 @@ void lll_periph_prepare(void *param) lll = p->param; /* Invoke common pipeline handling of prepare */ - err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb, - 0U, p); + err = lll_prepare(lll_conn_peripheral_is_abort_cb, lll_conn_abort_cb, + prepare_cb, 0U, param); LL_ASSERT(!err || err == -EINPROGRESS); } @@ -211,7 +211,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_isr_set(lll_conn_isr_rx, lll); - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(lll->tifs_tx_us); #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) @@ -315,9 +315,13 @@ static int prepare_cb(struct lll_prepare_param *p) #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */ #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \ + defined(CONFIG_BT_CTLR_TX_DEFER) || \ defined(HAL_RADIO_GPIO_HAVE_PA_PIN) radio_tmr_end_capture(); -#endif /* CONFIG_BT_CTLR_PROFILE_ISR */ +#endif /* CONFIG_BT_CTLR_PROFILE_ISR || + * CONFIG_BT_CTLR_TX_DEFER || + * HAL_RADIO_GPIO_HAVE_PA_PIN + */ #if defined(CONFIG_BT_CTLR_CONN_RSSI) radio_rssi_measure(); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index 1391755274dc1..d189a22d61e41 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -261,7 +261,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_isr_set(isr_rx, cis_lll); - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(cis_lll->tifs_us); #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_tx(cis_lll->rx.phy, 0U, cis_lll->tx.phy, @@ -743,7 +743,7 @@ static void isr_rx(void *param) radio_gpio_pa_setup(); - pa_lna_enable_us = radio_tmr_tifs_base_get() + EVENT_IFS_US - + pa_lna_enable_us = radio_tmr_tifs_base_get() + cis_lll->tifs_us - HAL_RADIO_GPIO_PA_OFFSET; #if defined(CONFIG_BT_CTLR_PHY) pa_lna_enable_us -= radio_rx_chain_delay_get(cis_lll->rx.phy, @@ -897,7 +897,7 @@ static void isr_tx(void *param) radio_tmr_tx_disable(); radio_tmr_rx_enable(); - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(cis_lll->tifs_us); #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_tx(cis_lll->rx.phy, 0U, cis_lll->tx.phy, @@ -1114,7 +1114,7 @@ static void isr_prepare_subevent_common(void *param) radio_tmr_tx_disable(); radio_tmr_rx_enable(); - radio_tmr_tifs_set(EVENT_IFS_US); + radio_tmr_tifs_set(cis_lll->tifs_us); #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_tx(cis_lll->rx.phy, 0U, cis_lll->tx.phy, diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index 18ae111d8ae27..c577532ce78ac 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -185,6 +185,8 @@ #define EVENT_CLOCK_JITTER_US 2 /* Event interframe timings */ #define EVENT_IFS_US 150 +/* Event interframe timings, default */ +#define EVENT_IFS_DEFAULT_US EVENT_IFS_US /* Standard allows 2 us timing uncertainty inside the event */ #define EVENT_IFS_MAX_US (EVENT_IFS_US + EVENT_CLOCK_JITTER_US) /* Specification defined Minimum AUX Frame Space (MAFS) */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index 397c0d0b5f9da..712a89cb2b750 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -311,6 +311,11 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, /* Re-initialize the Tx Q */ ull_tx_q_init(&conn->tx_q); + conn_lll->tifs_tx_us = EVENT_IFS_DEFAULT_US; + conn_lll->tifs_rx_us = EVENT_IFS_DEFAULT_US; + conn_lll->tifs_hcto_us = EVENT_IFS_DEFAULT_US; + conn_lll->tifs_cis_us = EVENT_IFS_DEFAULT_US; + /* TODO: active_to_start feature port */ conn->ull.ticks_active_to_start = 0U; conn->ull.ticks_prepare_to_start = @@ -363,7 +368,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, /* Calculate event time reservation */ slot_us = max_tx_time + max_rx_time; - slot_us += EVENT_IFS_US + (EVENT_CLOCK_JITTER_US << 1); + slot_us += conn_lll->tifs_rx_us + (EVENT_CLOCK_JITTER_US << 1); slot_us += ready_delay_us; slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 957d4e8863b1e..e46ecfb8c3916 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -931,6 +931,7 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, #endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.next_subevent = 0U; + cis->lll.tifs_us = conn->lll.tifs_cis_us; cis->lll.sn = 0U; cis->lll.nesn = 0U; cis->lll.cie = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 1af9bacea20c7..887c0ebfeaafb 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -698,7 +698,13 @@ uint8_t ll_apto_get(uint16_t handle, uint16_t *apto) return BT_HCI_ERR_UNKNOWN_CONN_ID; } - *apto = conn->apto_reload * conn->lll.interval * 125U / 1000; + if (conn->lll.interval >= BT_HCI_LE_INTERVAL_MIN) { + *apto = conn->apto_reload * conn->lll.interval * + CONN_INT_UNIT_US / (10U * USEC_PER_MSEC); + } else { + *apto = conn->apto_reload * (conn->lll.interval + 1U) * + CONN_LOW_LAT_INT_UNIT_US / (10U * USEC_PER_MSEC); + } return 0; } @@ -712,9 +718,17 @@ uint8_t ll_apto_set(uint16_t handle, uint16_t apto) return BT_HCI_ERR_UNKNOWN_CONN_ID; } - conn->apto_reload = RADIO_CONN_EVENTS(apto * 10U * 1000U, - conn->lll.interval * - CONN_INT_UNIT_US); + if (conn->lll.interval >= BT_HCI_LE_INTERVAL_MIN) { + conn->apto_reload = + RADIO_CONN_EVENTS(apto * 10U * USEC_PER_MSEC, + conn->lll.interval * + CONN_INT_UNIT_US); + } else { + conn->apto_reload = + RADIO_CONN_EVENTS(apto * 10U * USEC_PER_MSEC, + (conn->lll.interval + 1U) * + CONN_LOW_LAT_INT_UNIT_US); + } return 0; } @@ -1028,8 +1042,17 @@ void ull_conn_done(struct node_rx_event_done *done) if (0) { #if defined(CONFIG_BT_PERIPHERAL) } else if (lll->role) { - ull_drift_ticks_get(done, &ticks_drift_plus, - &ticks_drift_minus); + if (!conn->periph.drift_skip) { + ull_drift_ticks_get(done, &ticks_drift_plus, + &ticks_drift_minus); + + if (ticks_drift_plus || ticks_drift_minus) { + conn->periph.drift_skip = + ull_ref_get(&conn->ull); + } + } else { + conn->periph.drift_skip--; + } if (!ull_tx_q_peek(&conn->tx_q)) { ull_conn_tx_demux(UINT8_MAX); @@ -1073,10 +1096,18 @@ void ull_conn_done(struct node_rx_event_done *done) else { /* Start supervision timeout, if not started already */ if (!conn->supervision_expire) { - const uint32_t conn_interval_us = conn->lll.interval * CONN_INT_UNIT_US; + uint32_t conn_interval_us; + + if (conn->lll.interval >= BT_HCI_LE_INTERVAL_MIN) { + conn_interval_us = conn->lll.interval * + CONN_INT_UNIT_US; + } else { + conn_interval_us = (conn->lll.interval + 1U) * + CONN_LOW_LAT_INT_UNIT_US; + } conn->supervision_expire = RADIO_CONN_EVENTS( - (conn->supervision_timeout * 10U * 1000U), + (conn->supervision_timeout * 10U * USEC_PER_MSEC), conn_interval_us); } } @@ -1275,7 +1306,7 @@ void ull_conn_done(struct node_rx_event_done *done) /* Calculate event time reservation */ slot_us = tx_time + rx_time; - slot_us += EVENT_IFS_US + (EVENT_CLOCK_JITTER_US << 1); + slot_us += lll->tifs_rx_us + (EVENT_CLOCK_JITTER_US << 1); slot_us += ready_delay; if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX) || @@ -2149,17 +2180,22 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_ uint32_t win_offset_us, uint16_t interval, uint16_t latency, uint16_t timeout, uint16_t instant) { - struct lll_conn *lll; + uint16_t conn_interval_unit_old; + uint16_t conn_interval_unit_new; uint32_t ticks_win_offset = 0U; + uint16_t conn_interval_old_us; + uint16_t conn_interval_new_us; uint32_t ticks_slot_overhead; uint16_t conn_interval_old; uint16_t conn_interval_new; uint32_t conn_interval_us; - uint32_t periodic_us; - uint16_t latency_upd; + uint32_t ticks_at_expire; uint16_t instant_latency; + uint32_t ready_delay_us; uint16_t event_counter; - uint32_t ticks_at_expire; + uint32_t periodic_us; + uint16_t latency_upd; + struct lll_conn *lll; lll = &conn->lll; @@ -2183,16 +2219,89 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_ } #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ +#if defined(CONFIG_BT_CTLR_PHY) + ready_delay_us = lll_radio_tx_ready_delay_get(lll->phy_tx, + lll->phy_flags); +#else + ready_delay_us = lll_radio_tx_ready_delay_get(0U, 0U); +#endif + /* compensate for instant_latency due to laziness */ - conn_interval_old = instant_latency * lll->interval; - latency_upd = conn_interval_old / interval; - conn_interval_new = latency_upd * interval; - if (conn_interval_new > conn_interval_old) { - ticks_at_expire += HAL_TICKER_US_TO_TICKS((conn_interval_new - conn_interval_old) * - CONN_INT_UNIT_US); + if (lll->interval >= BT_HCI_LE_INTERVAL_MIN) { + conn_interval_old = instant_latency * lll->interval; + conn_interval_unit_old = CONN_INT_UNIT_US; } else { - ticks_at_expire -= HAL_TICKER_US_TO_TICKS((conn_interval_old - conn_interval_new) * - CONN_INT_UNIT_US); + conn_interval_old = instant_latency * (lll->interval + 1U); + conn_interval_unit_old = CONN_LOW_LAT_INT_UNIT_US; + } + + if (interval >= BT_HCI_LE_INTERVAL_MIN) { + uint16_t max_tx_time; + uint16_t max_rx_time; + uint32_t slot_us; + + conn_interval_new = interval; + conn_interval_unit_new = CONN_INT_UNIT_US; + lll->tifs_tx_us = EVENT_IFS_DEFAULT_US; + lll->tifs_rx_us = EVENT_IFS_DEFAULT_US; + lll->tifs_hcto_us = EVENT_IFS_DEFAULT_US; + +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) && \ + defined(CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE) + max_tx_time = lll->dle.eff.max_tx_time; + max_rx_time = lll->dle.eff.max_rx_time; + +#else /* !CONFIG_BT_CTLR_DATA_LENGTH || + * !CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE + */ + max_tx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M); + max_rx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M); +#if defined(CONFIG_BT_CTLR_PHY) + max_tx_time = MAX(max_tx_time, PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_tx)); + max_rx_time = MAX(max_rx_time, PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_rx)); +#endif /* !CONFIG_BT_CTLR_PHY */ +#endif /* !CONFIG_BT_CTLR_DATA_LENGTH || + * !CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE + */ + + /* Calculate event time reservation */ + slot_us = max_tx_time + max_rx_time; + slot_us += lll->tifs_rx_us + (EVENT_CLOCK_JITTER_US << 1); + slot_us += ready_delay_us; + + if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX) || + (lll->role == BT_HCI_ROLE_CENTRAL)) { + slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + } + + conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us); + + } else { + conn_interval_new = interval + 1U; + conn_interval_unit_new = CONN_LOW_LAT_INT_UNIT_US; + lll->tifs_tx_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US; + lll->tifs_rx_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US; + lll->tifs_hcto_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US; + /* Reserve only the processing overhead, on overlap the + * is_abort_cb mechanism will ensure to continue the event so + * as to not loose anchor point sync. + */ + conn->ull.ticks_slot = + HAL_TICKER_US_TO_TICKS_CEIL(EVENT_OVERHEAD_START_US); + } + + conn_interval_us = conn_interval_new * conn_interval_unit_new; + periodic_us = conn_interval_us; + + conn_interval_old_us = conn_interval_old * conn_interval_unit_old; + latency_upd = conn_interval_old_us / conn_interval_us; + conn_interval_new_us = latency_upd * conn_interval_us; + if (conn_interval_new_us > conn_interval_old_us) { + ticks_at_expire += HAL_TICKER_US_TO_TICKS( + conn_interval_new_us - conn_interval_old_us); + } else { + ticks_at_expire -= HAL_TICKER_US_TO_TICKS( + conn_interval_old_us - conn_interval_new_us); } 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_ /* calculate the offset */ if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { ticks_slot_overhead = - MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_prepare_to_start); + MAX(conn->ull.ticks_active_to_start, + conn->ull.ticks_prepare_to_start); + } else { ticks_slot_overhead = 0U; } /* calculate the window widening and interval */ - conn_interval_us = interval * CONN_INT_UNIT_US; - periodic_us = conn_interval_us; - switch (lll->role) { #if defined(CONFIG_BT_PERIPHERAL) case BT_HCI_ROLE_PERIPHERAL: @@ -2296,7 +2404,13 @@ void ull_conn_update_peer_sca(struct ll_conn *conn) lll = &conn->lll; /* calculate the window widening and interval */ - conn_interval_us = lll->interval * CONN_INT_UNIT_US; + if (lll->interval >= BT_HCI_LE_INTERVAL_MIN) { + conn_interval_us = lll->interval * + CONN_INT_UNIT_US; + } else { + conn_interval_us = (lll->interval + 1U) * + CONN_LOW_LAT_INT_UNIT_US; + } periodic_us = conn_interval_us; lll->periph.window_widening_periodic_us = diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index ac466b73dc622..45c682312fd7b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -192,6 +192,7 @@ struct ll_conn { #endif /* CONFIG_BT_CTLR_CONN_META */ uint8_t latency_cancel:1; uint8_t sca:3; + uint8_t drift_skip; uint32_t force; uint32_t ticks_to_offset; } periph; diff --git a/subsys/bluetooth/controller/ll_sw/ull_internal.h b/subsys/bluetooth/controller/ll_sw/ull_internal.h index e2cdaa4181403..a5505365b6eaa 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_internal.h @@ -8,11 +8,15 @@ * User CPR Interval */ #if !defined(CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN) +#if defined(CONFIG_BT_CTLR_CONN_INTERVAL_LOW_LATENCY) +#define CONN_INTERVAL_MIN(x) (0U) +#else /* !CONFIG_BT_CTLR_CONN_INTERVAL_LOW_LATENCY */ /* Bluetooth defined CPR Interval Minimum (7.5ms) */ -#define CONN_INTERVAL_MIN(x) (6) +#define CONN_INTERVAL_MIN(x) (6U) +#endif /* !CONFIG_BT_CTLR_CONN_INTERVAL_LOW_LATENCY */ #else /* CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN */ /* Proprietary user defined CPR Interval Minimum */ -#define CONN_INTERVAL_MIN(x) (MAX(ull_conn_interval_min_get(x), 1)) +#define CONN_INTERVAL_MIN(x) (MAX(ull_conn_interval_min_get(x), 1U)) #endif /* CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN */ /** diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c index cb2eda865927b..386bf84a445fa 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c @@ -381,9 +381,14 @@ void ull_periph_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, ready_delay_us = lll_radio_rx_ready_delay_get(0U, 0U); #endif /* CONFIG_BT_CTLR_PHY */ + lll->tifs_tx_us = EVENT_IFS_DEFAULT_US; + lll->tifs_rx_us = EVENT_IFS_DEFAULT_US; + lll->tifs_hcto_us = EVENT_IFS_DEFAULT_US; + lll->tifs_cis_us = EVENT_IFS_DEFAULT_US; + /* Calculate event time reservation */ slot_us = max_rx_time + max_tx_time; - slot_us += EVENT_IFS_US + (EVENT_CLOCK_JITTER_US << 1); + slot_us += lll->tifs_rx_us + (EVENT_CLOCK_JITTER_US << 1); slot_us += ready_delay_us; if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX)) { diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index b7718a3091f80..345fddb874652 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -294,6 +294,7 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, { struct ll_conn_iso_stream *cis = NULL; struct ll_conn_iso_group *cig; + struct ll_conn *conn; uint32_t cis_offset; /* Get CIG by id */ @@ -310,6 +311,8 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, return BT_HCI_ERR_UNSPECIFIED; } + conn = ll_conn_get(cis->lll.acl_handle); + cis_offset = sys_get_le24(ind->cis_offset); #if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO_EARLY_CIG_START) @@ -332,6 +335,7 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, #endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.next_subevent = 0U; + cis->lll.tifs_us = conn->lll.tifs_cis_us; cis->lll.sn = 0U; cis->lll.nesn = 0U; cis->lll.cie = 0U; diff --git a/tests/bsim/bluetooth/ll/compile.sh b/tests/bsim/bluetooth/ll/compile.sh index c27c55a004774..43bc833c41700 100755 --- a/tests/bsim/bluetooth/ll/compile.sh +++ b/tests/bsim/bluetooth/ll/compile.sh @@ -17,6 +17,8 @@ app=tests/bsim/bluetooth/ll/advx \ conf_overlay=overlay-ticker_expire_info.conf compile app=tests/bsim/bluetooth/ll/conn conf_file=prj_split.conf compile +app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_1ms.conf compile +app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_tx_defer.conf compile app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_privacy.conf compile app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_low_lat.conf compile app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_single_timer.conf compile diff --git a/tests/bsim/bluetooth/ll/conn/Kconfig b/tests/bsim/bluetooth/ll/conn/Kconfig new file mode 100644 index 0000000000000..87a403f2d7d92 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config TEST_CONN_INTERVAL_1MS + bool "Test 1 ms connection interval support" + help + Test 1 ms connection interval support. + +menu "Zephyr Kernel" +source "Kconfig.zephyr" +endmenu diff --git a/tests/bsim/bluetooth/ll/conn/prj_split_1ms.conf b/tests/bsim/bluetooth/ll/conn/prj_split_1ms.conf new file mode 100644 index 0000000000000..58276bd991e64 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/prj_split_1ms.conf @@ -0,0 +1,23 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_PRIVACY=y +CONFIG_BT_SMP=y +CONFIG_BT_SIGNING=y +CONFIG_BT_BAS=y +CONFIG_BT_HRS=y +CONFIG_BT_ATT_PREPARE_COUNT=2 +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_DEVICE_NAME="bsim_test_split_1m" +CONFIG_BT_L2CAP_TX_BUF_COUNT=6 + +CONFIG_BT_CTLR_PRIVACY=n + +CONFIG_BT_CONN_PARAM_ANY=y + +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_CONN_INTERVAL_LOW_LATENCY=y + +CONFIG_TEST_CONN_INTERVAL_1MS=y diff --git a/tests/bsim/bluetooth/ll/conn/prj_split_tx_defer.conf b/tests/bsim/bluetooth/ll/conn/prj_split_tx_defer.conf new file mode 100644 index 0000000000000..22dc32be4c429 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/prj_split_tx_defer.conf @@ -0,0 +1,19 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_PRIVACY=y +CONFIG_BT_SMP=y +CONFIG_BT_SIGNING=y +CONFIG_BT_BAS=y +CONFIG_BT_HRS=y +CONFIG_BT_ATT_PREPARE_COUNT=2 +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_DEVICE_NAME="bsim_test_split" +CONFIG_BT_L2CAP_TX_BUF_COUNT=6 + +CONFIG_BT_CTLR_PRIVACY=n + +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_TX_DEFER=y diff --git a/tests/bsim/bluetooth/ll/conn/src/test_connect1.c b/tests/bsim/bluetooth/ll/conn/src/test_connect1.c index 0e1da09068758..a31ff3d0d9acd 100644 --- a/tests/bsim/bluetooth/ll/conn/src/test_connect1.c +++ b/tests/bsim/bluetooth/ll/conn/src/test_connect1.c @@ -29,10 +29,19 @@ static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0); static struct bt_gatt_discover_params discover_params; static struct bt_gatt_subscribe_params subscribe_params; +#if defined(CONFIG_TEST_CONN_INTERVAL_1MS) +#define UPDATE_PARAM_INTERVAL_MIN 1 +#define UPDATE_PARAM_INTERVAL_MAX 1 +#define UPDATE_PARAM_LATENCY 0 +#define UPDATE_PARAM_TIMEOUT 10 +#define TEST_NOTIFY_COUNT 3000 +#else /* !CONFIG_TEST_CONN_INTERVAL_1MS */ #define UPDATE_PARAM_INTERVAL_MIN 25 #define UPDATE_PARAM_INTERVAL_MAX 45 #define UPDATE_PARAM_LATENCY 1 #define UPDATE_PARAM_TIMEOUT 250 +#define TEST_NOTIFY_COUNT 3 +#endif /* !CONFIG_TEST_CONN_INTERVAL_1MS */ static struct bt_le_conn_param update_params = { .interval_min = UPDATE_PARAM_INTERVAL_MIN, @@ -60,6 +69,7 @@ static uint8_t connected_signal; */ #define WAIT_TIME 6 /*seconds*/ +#define WAIT_TIME_TX_DEFER 800 /* milliseconds */ #define WAIT_TIME_REPEAT 22 /*seconds*/ extern enum bst_result_t bst_result; @@ -77,7 +87,11 @@ extern enum bst_result_t bst_result; static void test_con1_init(void) { - bst_ticker_set_next_tick_absolute(WAIT_TIME*1e6); + if (IS_ENABLED(CONFIG_BT_CTLR_TX_DEFER)) { + bst_ticker_set_next_tick_absolute(WAIT_TIME_TX_DEFER*1e3); + } else { + bst_ticker_set_next_tick_absolute(WAIT_TIME*1e6); + } bst_result = In_progress; } @@ -119,16 +133,32 @@ static uint8_t notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, const void *data, uint16_t length) { + static uint32_t cycle_stamp; static int notify_count; + uint32_t cycle_now; + uint64_t delta; + if (!data) { printk("[UNSUBSCRIBED]\n"); params->value_handle = 0U; return BT_GATT_ITER_STOP; } - printk("[NOTIFICATION] data %p length %u\n", data, length); + cycle_now = k_cycle_get_32(); + delta = cycle_now - cycle_stamp; + cycle_stamp = cycle_now; + delta = k_cyc_to_ns_floor64(delta); + + if (!IS_ENABLED(CONFIG_TEST_CONN_INTERVAL_1MS) || + ((delta > (NSEC_PER_MSEC / 2U)) && + (delta < (NSEC_PER_MSEC + (NSEC_PER_MSEC / 2U))))) { + notify_count++; + } + + printk("[NOTIFICATION] %u. data %p length %u in %llu ns\n", + notify_count, data, length, delta); - if (notify_count++ >= 1) { /* We consider it passed */ + if (notify_count >= TEST_NOTIFY_COUNT) { /* We consider it passed */ int err; /* Disconnect before actually passing */ diff --git a/tests/bsim/bluetooth/ll/conn/src/test_connect2.c b/tests/bsim/bluetooth/ll/conn/src/test_connect2.c index 44b7af7a55f5a..f648d2d2d905f 100644 --- a/tests/bsim/bluetooth/ll/conn/src/test_connect2.c +++ b/tests/bsim/bluetooth/ll/conn/src/test_connect2.c @@ -209,7 +209,12 @@ static void test_con2_main(void) * of starting delayed work so we do it here */ while (1) { - k_sleep(K_SECONDS(1)); + if (IS_ENABLED(CONFIG_TEST_CONN_INTERVAL_1MS) || + IS_ENABLED(CONFIG_BT_CTLR_TX_DEFER)) { + k_sleep(K_MSEC(1)); + } else { + k_sleep(K_SECONDS(1)); + } /* Heartrate measurements simulation */ hrs_notify(); diff --git a/tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_split_1ms.sh b/tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_split_1ms.sh new file mode 100755 index 0000000000000..0be845f12d67f --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_split_1ms.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic connection test: a central connects to a peripheral and expects a +# notification, using the split controller (ULL LLL) and 1ms connection +# interval +simulation_id="basic_conn_split_1ms" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_conn_prj_split_1ms_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=1 \ + -testid=peripheral -rs=23 + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_conn_prj_split_1ms_conf\ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=1 \ + -testid=central -rs=6 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_split_tx_defer.sh b/tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_split_tx_defer.sh new file mode 100755 index 0000000000000..59c7c465be021 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_split_tx_defer.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic connection test: a central connects to a peripheral and expects a +# notification, using the split controller (ULL LLL) +simulation_id="basic_conn_split_tx_defer" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_conn_prj_split_tx_defer_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=0 \ + -testid=peripheral -rs=23 + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_conn_prj_split_tx_defer_conf\ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ + -testid=central -rs=6 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs