From 55813ad95b14189f467f4c27e8bffbe35177ac82 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 10 Jun 2024 22:12:56 +0200 Subject: [PATCH] Bluetooth: Controller: nRF54Lx: Use NRF_GRTC for radio scheduling Use NRF_GRTC, Global real-time counter, instead of NRF_RTC. NRF_GRTC is present in a different power domain in the SoC. Also, NRF_GRTC provide microsecond resolution timing units, in the future use of NRF_TIMER for packet timer can also be replaced. Use of NRF_RTC would keep Radio power domain ON in addition to already ON NRF_GRTC's power domain, hence switch to using NRF_GRTC on nRF54Lx SoC to have lower power consumptions. Signed-off-by: Vinayak Kariappa Chettimada --- .../bluetooth/controller/Kconfig.ll_sw_split | 32 ++++ .../controller/ll_sw/nordic/hal/nrf5/cntr.c | 128 +++++++++++++ .../ll_sw/nordic/hal/nrf5/radio/radio.c | 178 +++++++++++++++++- .../ll_sw/nordic/hal/nrf5/radio/radio.h | 2 +- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h | 5 + .../nordic/hal/nrf5/radio/radio_nrf54lx.h | 2 + .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 4 + .../controller/ll_sw/nordic/hal/nrf5/swi.h | 9 +- .../controller/ll_sw/nordic/hal/nrf5/ticker.c | 6 +- .../controller/ll_sw/nordic/hal/nrf5/ticker.h | 31 ++- .../controller/ll_sw/nordic/lll/lll.c | 7 +- .../controller/ll_sw/nordic/lll/lll_scan.c | 3 +- .../controller/ll_sw/nordic/lll/lll_vendor.h | 3 +- 13 files changed, 392 insertions(+), 18 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index a17689373d6..faa3d7cc286 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -831,6 +831,38 @@ config BT_CTLR_RX_PDU_META prompt "RX pdu meta data" bool +config BT_CTLR_NRF_GRTC + bool "Use nRF GRTC peripheral" + depends on SOC_SERIES_NRF54LX + select BT_TICKER_CNTR_FREE_RUNNING + default y + help + Enable use of nRF54Lx NRF_GRTC peripheral. + +config BT_CTLR_NRF_GRTC_START + bool "Start nRF GRTC peripheral" + depends on BT_CTLR_NRF_GRTC + help + Enable explicit start of nRF54Lx NRF_GRTC peripheral. + +config BT_CTLR_NRF_GRTC_KEEPRUNNING + bool "Keep running nRF GRTC peripheral" + depends on BT_CTLR_NRF_GRTC_START + help + Keep running nRF GRTC peripheral. + +config BT_CTLR_NRF_GRTC_AUTOEN_CPUACTIVE + bool "Auto enable nRF GRTC on CPU active" + depends on BT_CTLR_NRF_GRTC_START + help + Auto enable nRF GRTC on CPU active. + +config BT_CTLR_NRF_GRTC_AUTOEN_DEFAULT + bool "Auto enable nRF GRTC by default" + depends on BT_CTLR_NRF_GRTC_START + help + Auto enable nRF GRTC by default. + config BT_CTLR_RADIO_ENABLE_FAST bool "Use tTXEN/RXEN,FAST ramp-up" depends on SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c index 1dccf4ed2f9..20dd22f1bf6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c @@ -11,6 +11,7 @@ #include "hal/debug.h" +#if !defined(CONFIG_BT_CTLR_NRF_GRTC) #ifndef NRF_RTC #if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #define NRF_RTC NRF_RTC10 @@ -18,14 +19,65 @@ #define NRF_RTC NRF_RTC0 #endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !NRF_RTC */ +#endif /* CONFIG_BT_CTLR_NRF_GRTC */ static uint8_t _refcount; void cntr_init(void) { +#if defined(CONFIG_BT_CTLR_NRF_GRTC) +#if defined(CONFIG_BT_CTLR_NRF_GRTC_START) + NRF_GRTC->MODE = (GRTC_MODE_SYSCOUNTEREN_Disabled << + GRTC_MODE_SYSCOUNTEREN_Pos) & + GRTC_MODE_SYSCOUNTEREN_Msk; + + NRF_GRTC->TASKS_CLEAR = 1U; + +#if defined(CONFIG_BT_CTLR_NRF_GRTC_KEEPRUNNING) + NRF_GRTC->KEEPRUNNING = + (GRTC_KEEPRUNNING_REQUEST1_Active << + GRTC_KEEPRUNNING_REQUEST1_Pos) & + GRTC_KEEPRUNNING_REQUEST1_Msk; + NRF_GRTC->TIMEOUT = 0U; + NRF_GRTC->INTERVAL = 0U; + NRF_GRTC->WAKETIME = 4U; +#endif /* CONFIG_BT_CTLR_NRF_GRTC_KEEPRUNNING */ + + NRF_GRTC->CLKCFG = ((GRTC_CLKCFG_CLKSEL_LFXO << + GRTC_CLKCFG_CLKSEL_Pos) & + GRTC_CLKCFG_CLKSEL_Msk) | + ((GRTC_CLKCFG_CLKFASTDIV_Min << + GRTC_CLKCFG_CLKFASTDIV_Pos) & + GRTC_CLKCFG_CLKFASTDIV_Msk); +#endif /* CONFIG_BT_CTLR_NRF_GRTC_START */ + + NRF_GRTC->EVENTS_COMPARE[10] = 0U; + NRF_GRTC->INTENSET1 = GRTC_INTENSET1_COMPARE10_Msk; + +#if defined(CONFIG_BT_CTLR_NRF_GRTC_START) + NRF_GRTC->MODE = ((GRTC_MODE_SYSCOUNTEREN_Enabled << + GRTC_MODE_SYSCOUNTEREN_Pos) & + GRTC_MODE_SYSCOUNTEREN_Msk) | +#if defined(CONFIG_BT_CTLR_NRF_GRTC_AUTOEN_CPUACTIVE) + ((GRTC_MODE_AUTOEN_CpuActive << + GRTC_MODE_AUTOEN_Pos) & + GRTC_MODE_AUTOEN_Msk) | +#endif /* CONFIG_BT_CTLR_NRF_GRTC_AUTOEN_CPUACTIVE */ +#if defined(CONFIG_BT_CTLR_NRF_GRTC_AUTOEN_DEFAULT) + ((GRTC_MODE_AUTOEN_Default << + GRTC_MODE_AUTOEN_Pos) & + GRTC_MODE_AUTOEN_Msk) | +#endif /* CONFIG_BT_CTLR_NRF_GRTC_AUTOEN_DEFAULT */ + 0U; + + NRF_GRTC->TASKS_START = 1U; +#endif /* CONFIG_BT_CTLR_NRF_GRTC_START */ + +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ NRF_RTC->PRESCALER = 0; nrf_rtc_event_enable(NRF_RTC, RTC_EVTENSET_COMPARE0_Msk); nrf_rtc_int_enable(NRF_RTC, RTC_INTENSET_COMPARE0_Msk); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ } uint32_t cntr_start(void) @@ -34,7 +86,11 @@ uint32_t cntr_start(void) return 1; } +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + /* TODO: if we own and start GRTC, implement start here */ +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_task_trigger(NRF_RTC, NRF_RTC_TASK_START); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ return 0; } @@ -47,17 +103,89 @@ uint32_t cntr_stop(void) return 1; } +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + /* TODO: if we own and stop GRTC, implement stop here */ +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_task_trigger(NRF_RTC, NRF_RTC_TASK_STOP); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ return 0; } uint32_t cntr_cnt_get(void) { +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + uint32_t l, h, ho; + + /* NOTE: For a 32-bit implementation, L value is read after H + * to avoid another L value after SYSCOUNTER gets ready. + * If both H and L values are desired, then swap the order and + * ensure that L value does not change when H value is read. + */ + do { + h = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + l = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERL; + ho = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + } while ((h & GRTC_SYSCOUNTER_SYSCOUNTERH_BUSY_Msk) || + (ho & GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Msk)); + + return l; +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ return nrf_rtc_counter_get(NRF_RTC); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ } void cntr_cmp_set(uint8_t cmp, uint32_t value) { +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + uint32_t l, h, ho, stale; + + /* NOTE: We are going to use TASKS_CAPTURE to read current + * SYSCOUNTER H and L, so that COMPARE registers can be set + * considering that we need to set H compare value too. + */ + + /* Read current syscounter value */ + do { + h = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + l = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERL; + ho = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + } while ((h & GRTC_SYSCOUNTER_SYSCOUNTERH_BUSY_Msk) || + (ho & GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Msk)); + + /* Disable capture/compare */ + NRF_GRTC->CC[cmp].CCEN = 0U; + + /* Set a stale value in capture value */ + stale = l - 1U; + NRF_GRTC->CC[cmp].CCL = stale; + + /* Trigger a capture */ + NRF_GRTC->TASKS_CAPTURE[cmp] = 1U; + + /* Wait to get a new L value */ + do { + l = NRF_GRTC->CC[cmp].CCL; + } while (l == stale); + + /* Read H value */ + h = NRF_GRTC->CC[cmp].CCH; + + /* NOTE: HERE, we have h and l in sync. */ + + /* Handle rollover between current and expected value */ + if (value < l) { + h++; + } + + /* Set compare register values */ + NRF_GRTC->CC[cmp].CCL = value; + NRF_GRTC->CC[cmp].CCH = h & GRTC_CC_CCH_CCH_Msk; + + /* Enable compare */ + NRF_GRTC->CC[cmp].CCEN = 1U; + +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_cc_set(NRF_RTC, cmp, value); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ } 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 e349826afe4..bcfd9530d63 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 @@ -1175,7 +1175,12 @@ uint32_t radio_bc_has_match(void) void radio_tmr_status_reset(void) { +#if defined(CONFIG_BT_CTLR_NRF_GRTC) +#define GRTC_CC_IDX_RADIO 11U + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCEN = 0U; +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_event_disable(NRF_RTC, RTC_EVTENCLR_COMPARE2_Msk); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); @@ -1214,7 +1219,11 @@ void radio_tmr_status_reset(void) void radio_tmr_tx_status_reset(void) { +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCEN = 0U; +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_event_disable(NRF_RTC, RTC_EVTENCLR_COMPARE2_Msk); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); @@ -1257,7 +1266,11 @@ void radio_tmr_tx_status_reset(void) void radio_tmr_rx_status_reset(void) { +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCEN = 0U; +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_event_disable(NRF_RTC, RTC_EVTENCLR_COMPARE2_Msk); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); @@ -1370,8 +1383,81 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder) nrf_timer_cc_set(EVENT_TIMER, 0, remainder); +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + uint32_t l, h, ho, stale; + + /* Disable capture/compare */ + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCEN = 0U; + + /* Publish GRTC compare */ + NRF_GRTC->PUBLISH_COMPARE[GRTC_CC_IDX_RADIO] = + ((HAL_EVENT_TIMER_START_PPI << + GRTC_PUBLISH_COMPARE_CHIDX_Pos) & + GRTC_PUBLISH_COMPARE_CHIDX_Msk) | + ((GRTC_PUBLISH_COMPARE_EN_Enabled << + GRTC_PUBLISH_COMPARE_EN_Pos) & + GRTC_PUBLISH_COMPARE_EN_Msk); + + /* Enable same DPPI in Global domain */ + NRF_DPPIC20->CHENSET = BIT(HAL_EVENT_TIMER_START_PPI); + + /* Setup PPIB send subscribe */ + NRF_PPIB21->SUBSCRIBE_SEND[HAL_EVENT_TIMER_START_PPI] = + BIT(HAL_EVENT_TIMER_START_PPI) | PPIB_SUBSCRIBE_SEND_EN_Msk; + + /* Setup PPIB receive publish */ + NRF_PPIB11->PUBLISH_RECEIVE[HAL_EVENT_TIMER_START_PPI] = + BIT(HAL_EVENT_TIMER_START_PPI) | PPIB_PUBLISH_RECEIVE_EN_Msk; + + /* NOTE: We are going to use TASKS_CAPTURE to read current + * SYSCOUNTER H and L, so that COMPARE registers can be set + * considering that we need to set H compare value too. + */ + + /* Read current syscounter value */ + do { + h = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + l = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERL; + ho = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + } while ((h & GRTC_SYSCOUNTER_SYSCOUNTERH_BUSY_Msk) || + (ho & GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Msk)); + + /* Set a stale value in capture value */ + stale = l - 1U; + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCL = stale; + + /* Trigger a capture */ + NRF_GRTC->TASKS_CAPTURE[GRTC_CC_IDX_RADIO] = 1U; + + /* Wait to get a new L value */ + do { + l = NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCL; + } while (l == stale); + + /* Read H value */ + h = NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCH; + + /* NOTE: HERE, we have h and l in sync. */ + + /* Handle rollover between current and expected value */ + if (ticks_start < l) { + h++; + } + + /* Clear compare event, if any */ + NRF_GRTC->EVENTS_COMPARE[GRTC_CC_IDX_RADIO] = 0U; + + /* Set compare register values */ + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCL = ticks_start; + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCH = h & GRTC_CC_CCH_CCH_Msk; + + /* Enable compare */ + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCEN = 1U; + +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_cc_set(NRF_RTC, 2, ticks_start); nrf_rtc_event_enable(NRF_RTC, RTC_EVTENSET_COMPARE2_Msk); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ hal_event_timer_start_ppi_config(); hal_radio_nrf_ppi_channels_enable(BIT(HAL_EVENT_TIMER_START_PPI)); @@ -1410,7 +1496,7 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder) return remainder; } -uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) +uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start) { uint32_t remainder_us; @@ -1437,8 +1523,81 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) nrf_timer_cc_set(EVENT_TIMER, 0, remainder_us); - nrf_rtc_cc_set(NRF_RTC, 2, tick); +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + uint32_t l, h, ho, stale; + + /* Disable capture/compare */ + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCEN = 0U; + + /* Publish GRTC compare */ + NRF_GRTC->PUBLISH_COMPARE[GRTC_CC_IDX_RADIO] = + ((HAL_EVENT_TIMER_START_PPI << + GRTC_PUBLISH_COMPARE_CHIDX_Pos) & + GRTC_PUBLISH_COMPARE_CHIDX_Msk) | + ((GRTC_PUBLISH_COMPARE_EN_Enabled << + GRTC_PUBLISH_COMPARE_EN_Pos) & + GRTC_PUBLISH_COMPARE_EN_Msk); + + /* Enable same DPPI in Global domain */ + NRF_DPPIC20->CHENSET = BIT(HAL_EVENT_TIMER_START_PPI); + + /* Setup PPIB send subscribe */ + NRF_PPIB21->SUBSCRIBE_SEND[HAL_EVENT_TIMER_START_PPI] = + BIT(HAL_EVENT_TIMER_START_PPI) | PPIB_SUBSCRIBE_SEND_EN_Msk; + + /* Setup PPIB receive publish */ + NRF_PPIB11->PUBLISH_RECEIVE[HAL_EVENT_TIMER_START_PPI] = + BIT(HAL_EVENT_TIMER_START_PPI) | PPIB_PUBLISH_RECEIVE_EN_Msk; + + /* NOTE: We are going to use TASKS_CAPTURE to read current + * SYSCOUNTER H and L, so that COMPARE registers can be set + * considering that we need to set H compare value too. + */ + + /* Read current syscounter value */ + do { + h = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + l = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERL; + ho = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH; + } while ((h & GRTC_SYSCOUNTER_SYSCOUNTERH_BUSY_Msk) || + (ho & GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Msk)); + + /* Set a stale value in capture value */ + stale = l - 1U; + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCL = stale; + + /* Trigger a capture */ + NRF_GRTC->TASKS_CAPTURE[GRTC_CC_IDX_RADIO] = 1U; + + /* Wait to get a new L value */ + do { + l = NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCL; + } while (l == stale); + + /* Read H value */ + h = NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCH; + + /* NOTE: HERE, we have h and l in sync. */ + + /* Handle rollover between current and expected value */ + if (ticks_start < l) { + h++; + } + + /* Clear compare event, if any */ + NRF_GRTC->EVENTS_COMPARE[GRTC_CC_IDX_RADIO] = 0U; + + /* Set compare register values */ + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCL = ticks_start; + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCH = h & GRTC_CC_CCH_CCH_Msk; + + /* Enable compare */ + NRF_GRTC->CC[GRTC_CC_IDX_RADIO].CCEN = 1U; + +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ + nrf_rtc_cc_set(NRF_RTC, 2, ticks_start); nrf_rtc_event_enable(NRF_RTC, RTC_EVTENSET_COMPARE2_Msk); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ hal_event_timer_start_ppi_config(); hal_radio_nrf_ppi_channels_enable(BIT(HAL_EVENT_TIMER_START_PPI)); @@ -1549,7 +1708,20 @@ uint32_t radio_tmr_start_now(uint8_t trx) uint32_t radio_tmr_start_get(void) { - return nrf_rtc_cc_get(NRF_RTC, 2); + uint32_t start_ticks; + +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + uint64_t cc; + + cc = nrf_grtc_sys_counter_cc_get(NRF_GRTC, HAL_CNTR_GRTC_CC_IDX_RADIO); + + start_ticks = cc & 0xffffffffUL; + +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ + start_ticks = nrf_rtc_cc_get(NRF_RTC, 2); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ + + return start_ticks; } void radio_tmr_stop(void) 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 bebd256eed6..3d517121ec0 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 @@ -139,7 +139,7 @@ void radio_tmr_tx_disable(void); void radio_tmr_rx_disable(void); void radio_tmr_tifs_set(uint32_t tifs); uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder); -uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick); +uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start); uint32_t radio_tmr_start_us(uint8_t trx, uint32_t us); uint32_t radio_tmr_start_now(uint8_t trx); uint32_t radio_tmr_start_get(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 ac771b37af8..b07ce22172f 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 @@ -49,7 +49,12 @@ #error "Unsupported SoC." #endif +#if defined(CONFIG_BT_CTLR_NRF_GRTC) +#include +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ #include +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ + #include #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h index aef11bd7bc4..dde412b6c1e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h @@ -5,7 +5,9 @@ */ /* Use the NRF_RTC instance for coarse radio event scheduling */ +#if !defined(CONFIG_BT_CTLR_NRF_GRTC) #define NRF_RTC NRF_RTC10 +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) #error "Single Timer feature not supported yet" diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 29ed17dcc7e..7c4661d7204 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -100,7 +100,11 @@ static inline void hal_radio_end_time_capture_ppi_config(void) */ static inline void hal_event_timer_start_ppi_config(void) { +#if defined(CONFIG_BT_CTLR_NRF_GRTC) +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_publish_set(NRF_RTC, NRF_RTC_EVENT_COMPARE_2, HAL_EVENT_TIMER_START_PPI); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ + nrf_timer_subscribe_set(EVENT_TIMER, NRF_TIMER_TASK_START, HAL_EVENT_TIMER_START_PPI); } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h index 1cd17defbb9..80147920646 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h @@ -45,7 +45,14 @@ #elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #define HAL_SWI_RADIO_IRQ SWI02_IRQn + +#if defined(CONFIG_BT_CTLR_NRF_GRTC) +#define HAL_SWI_WORKER_IRQ GRTC_1_IRQn +#define HAL_RTC_IRQn GRTC_1_IRQn +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ #define HAL_SWI_WORKER_IRQ RTC10_IRQn +#define HAL_RTC_IRQn RTC10_IRQn +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ #if !defined(CONFIG_BT_CTLR_LOW_LAT) && \ (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) @@ -54,8 +61,6 @@ #define HAL_SWI_JOB_IRQ SWI03_IRQn #endif -#define HAL_RTC_IRQn RTC10_IRQn - #endif static inline void hal_swi_init(void) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c index 482e48b198b..c3c99d6cd62 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c @@ -194,5 +194,9 @@ void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t ch void hal_ticker_instance0_trigger_set(uint32_t value) { - cntr_cmp_set(0, value); +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + cntr_cmp_set(10U, value); +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ + cntr_cmp_set(0U, value); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h index 0def788727b..fa419c831bf 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h @@ -5,17 +5,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U -#define HAL_TICKER_CNTR_CLK_UNIT_FSEC 30517578125UL -#define HAL_TICKER_FSEC_PER_USEC 1000000000UL -#define HAL_TICKER_PSEC_PER_USEC 1000000UL -#define HAL_TICKER_FSEC_PER_PSEC 1000UL +#if defined(CONFIG_BT_CTLR_NRF_GRTC) +#define HAL_TICKER_CNTR_CLK_UNIT_FSEC 1000000000UL + +/* Macro defines the h/w supported most significant bit */ +#define HAL_TICKER_CNTR_MSBIT 31 + +/* Macro defining the HW supported counter bits */ +#define HAL_TICKER_CNTR_MASK 0xFFFFFFFF /* Macro defining the minimum counter compare offset */ -#define HAL_TICKER_CNTR_CMP_OFFSET_MIN 3 +#define HAL_TICKER_CNTR_CMP_OFFSET_MIN 1 /* Macro defining the max. counter update latency in ticks */ -#define HAL_TICKER_CNTR_SET_LATENCY 0 +#define HAL_TICKER_CNTR_SET_LATENCY 4 + +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ +#define HAL_TICKER_CNTR_CLK_UNIT_FSEC 30517578125UL /* Macro defines the h/w supported most significant bit */ #define HAL_TICKER_CNTR_MSBIT 23 @@ -23,6 +29,17 @@ /* Macro defining the HW supported counter bits */ #define HAL_TICKER_CNTR_MASK 0x00FFFFFF +/* Macro defining the minimum counter compare offset */ +#define HAL_TICKER_CNTR_CMP_OFFSET_MIN 3 + +/* Macro defining the max. counter update latency in ticks */ +#define HAL_TICKER_CNTR_SET_LATENCY 0 +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ + +#define HAL_TICKER_FSEC_PER_USEC 1000000000UL +#define HAL_TICKER_PSEC_PER_USEC 1000000UL +#define HAL_TICKER_FSEC_PER_PSEC 1000UL + /* Macro to translate microseconds to tick units. * NOTE: This returns the floor value. */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 8e3af92ea24..e88b9eb8079 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -8,8 +8,6 @@ #include #include -#include - #include #include @@ -120,8 +118,13 @@ static void rtc0_nrf5_isr(const void *arg) lll_prof_enter_ull_high(); /* On compare0 run ticker worker instance0 */ +#if defined(CONFIG_BT_CTLR_NRF_GRTC) + if (NRF_GRTC->EVENTS_COMPARE[10]) { + nrf_grtc_event_clear(NRF_GRTC, NRF_GRTC_EVENT_COMPARE_10); +#else /* !CONFIG_BT_CTLR_NRF_GRTC */ if (NRF_RTC->EVENTS_COMPARE[0]) { nrf_rtc_event_clear(NRF_RTC, NRF_RTC_EVENT_COMPARE_0); +#endif /* !CONFIG_BT_CTLR_NRF_GRTC */ ticker_trigger(0); } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c index ce37381dda1..fc85e67441e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c @@ -940,7 +940,8 @@ static void isr_window(void *param) ticks_at_start = ticker_ticks_now_get() + HAL_TICKER_US_TO_TICKS(HAL_RADIO_ISR_LATENCY_MAX_US) + - HAL_TICKER_CNTR_CMP_OFFSET_MIN; + HAL_TICKER_CNTR_CMP_OFFSET_MIN + + HAL_TICKER_CNTR_SET_LATENCY; remainder_us = radio_tmr_start_tick(0, ticks_at_start); #else /* !CONFIG_BT_CENTRAL && !CONFIG_BT_CTLR_ADV_EXT */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h index db5f8e3f1d8..a8ba935b35c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h @@ -55,7 +55,8 @@ * and ticker_update. Set to 32 us, which is ~1 tick with 32768 Hz * clock. */ -#define EVENT_TICKER_RES_MARGIN_US 32 +#define EVENT_TICKER_RES_MARGIN_US DIV_ROUND_UP(HAL_TICKER_CNTR_CLK_UNIT_FSEC, \ + HAL_TICKER_FSEC_PER_USEC) #define EVENT_RX_JITTER_US(phy) 16 /* Radio Rx timing uncertainty */ #define EVENT_RX_TO_US(phy) ((((((phy)&0x03) + 4)<<3)/BIT((((phy)&0x3)>>1))) + \