From ed5569f3a546b1fcae2f8f2d57d5e04201624f59 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Mon, 1 May 2017 05:52:57 +0200 Subject: [PATCH] Bluetooth: controller: Introduce s/w based TRX switching Introduce alternative TRX switching using dedicated timers and peripheral interconnect. This will enable the possibility to independently configure the Tx and Rx settings between the tIFS. Note, this will also provide the opportunity to design a soft realtime Radio ISR. Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/Kconfig | 6 ++ subsys/bluetooth/controller/hal/nrf5/radio.c | 87 ++++++++++++++++++-- subsys/bluetooth/controller/ll_sw/ctrl.c | 14 +++- 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 44fa3ad278f55c..e99be1424b6768 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -200,6 +200,12 @@ config BLUETOOTH_CONTROLLER_SCHED_ADVANCED Disabling this feature will lead to overlapping role in timespace leading to skipped events amongst active roles. +config BLUETOOTH_CONTROLLER_TIFS_HW + bool "H/w Accelerated tIFS Trx switching" + default y + help + Enable use of hardware accelerated tIFS Trx switching. + config BLUETOOTH_CONTROLLER_FAST_ENC bool "Fast Encryption Setup" help diff --git a/subsys/bluetooth/controller/hal/nrf5/radio.c b/subsys/bluetooth/controller/hal/nrf5/radio.c index e7c9a9c07e2e7e..70de81687b2554 100644 --- a/subsys/bluetooth/controller/hal/nrf5/radio.c +++ b/subsys/bluetooth/controller/hal/nrf5/radio.c @@ -229,24 +229,67 @@ void *radio_pkt_scratch_get(void) return _pkt_scratch; } +#if !defined(CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW) +static u8_t sw_tifs_toggle; + +static void sw_switch(u8_t dir) +{ + u8_t ppi = 12 + sw_tifs_toggle; + + NRF_PPI->CH[11].EEP = (u32_t)&(NRF_RADIO->EVENTS_END); + NRF_PPI->CH[11].TEP = (u32_t)&(NRF_PPI->TASKS_CHG[sw_tifs_toggle].EN); + NRF_PPI->CHENSET = PPI_CHEN_CH11_Msk; + + NRF_PPI->CH[ppi].EEP = (u32_t) + &(NRF_TIMER1->EVENTS_COMPARE[sw_tifs_toggle]); + if (dir) { + NRF_TIMER1->CC[sw_tifs_toggle] -= RADIO_TX_READY_DELAY_US + + RADIO_TX_CHAIN_DELAY_US; + NRF_PPI->CH[ppi].TEP = (u32_t)&(NRF_RADIO->TASKS_TXEN); + } else { + NRF_TIMER1->CC[sw_tifs_toggle] -= RADIO_RX_READY_DELAY_US; + NRF_PPI->CH[ppi].TEP = (u32_t)&(NRF_RADIO->TASKS_RXEN); + } + + sw_tifs_toggle += 1; + sw_tifs_toggle &= 1; +} +#endif /* CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ + void radio_switch_complete_and_rx(void) { - NRF_RADIO->SHORTS = - (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | - RADIO_SHORTS_DISABLED_RXEN_Msk); +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW) + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | + RADIO_SHORTS_END_DISABLE_Msk | + RADIO_SHORTS_DISABLED_RXEN_Msk; +#else /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | + RADIO_SHORTS_END_DISABLE_Msk; + sw_switch(0); +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ } void radio_switch_complete_and_tx(void) { - NRF_RADIO->SHORTS = - (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | - RADIO_SHORTS_DISABLED_TXEN_Msk); +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW) + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | + RADIO_SHORTS_END_DISABLE_Msk | + RADIO_SHORTS_DISABLED_TXEN_Msk; +#else /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | + RADIO_SHORTS_END_DISABLE_Msk; + sw_switch(1); +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ } void radio_switch_complete_and_disable(void) { NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk); + +#if !defined(CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW) + NRF_PPI->CHENCLR = PPI_CHEN_CH8_Msk | PPI_CHEN_CH11_Msk; +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ } void radio_rssi_measure(void) @@ -331,7 +374,11 @@ void radio_tmr_status_reset(void) void radio_tmr_tifs_set(u32_t tifs) { +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW) NRF_RADIO->TIFS = tifs; +#else /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ + NRF_TIMER1->CC[sw_tifs_toggle] = tifs; +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ } u32_t radio_tmr_start(u8_t trx, u32_t ticks_start, u32_t remainder) @@ -372,6 +419,29 @@ u32_t radio_tmr_start(u8_t trx, u32_t ticks_start, u32_t remainder) NRF_PPI->CHENSET = PPI_CHEN_CH0_Msk; } +#if !defined(CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW) + NRF_TIMER1->TASKS_CLEAR = 1; + NRF_TIMER1->MODE = 0; + NRF_TIMER1->PRESCALER = 4; + NRF_TIMER1->BITMODE = 0; /* 16 bit */ + NRF_TIMER1->TASKS_START = 1; + + NRF_PPI->CH[8].EEP = (u32_t)&(NRF_RADIO->EVENTS_END); + NRF_PPI->CH[8].TEP = (u32_t)&(NRF_TIMER1->TASKS_CLEAR); + NRF_PPI->CHENSET = PPI_CHEN_CH8_Msk; + + NRF_PPI->CH[9].EEP = (u32_t) + &(NRF_TIMER1->EVENTS_COMPARE[0]); + NRF_PPI->CH[9].TEP = (u32_t)&(NRF_PPI->TASKS_CHG[0].DIS); + + NRF_PPI->CH[10].EEP = (u32_t) + &(NRF_TIMER1->EVENTS_COMPARE[1]); + NRF_PPI->CH[10].TEP = (u32_t)&(NRF_PPI->TASKS_CHG[1].DIS); + + NRF_PPI->CHG[0] = PPI_CHG_CH9_Msk | PPI_CHG_CH12_Msk; + NRF_PPI->CHG[1] = PPI_CHG_CH10_Msk | PPI_CHG_CH13_Msk; +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ + return remainder; } @@ -379,6 +449,11 @@ void radio_tmr_stop(void) { NRF_TIMER0->TASKS_STOP = 1; NRF_TIMER0->TASKS_SHUTDOWN = 1; + +#if !defined(CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW) + NRF_TIMER1->TASKS_STOP = 1; + NRF_TIMER1->TASKS_SHUTDOWN = 1; +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_TIFS_HW */ } void radio_tmr_hcto_configure(u32_t hcto) diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index b9eb36d84b004e..f833316ccc9c07 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -37,7 +37,8 @@ #include #define RADIO_PREAMBLE_TO_ADDRESS_US 40 -#define RADIO_HCTO_US (150 + 2 + 2 + \ +#define RADIO_TIFS 150 +#define RADIO_HCTO_US (RADIO_TIFS + 2 + 2 + \ RADIO_PREAMBLE_TO_ADDRESS_US) #define RADIO_CONN_EVENTS(x, y) ((u16_t)((x) / (y))) @@ -511,6 +512,7 @@ static inline void isr_radio_state_tx(void) { _radio.state = STATE_RX; + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_tx(); radio_tmr_hcto_configure(radio_tmr_end_get() + @@ -1116,6 +1118,7 @@ static inline u32_t isr_rx_obs(u8_t irkmatch_id, u8_t rssi_ready) _radio.state = STATE_TX; radio_pkt_tx_set(pdu_adv_tx); + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_rx(); radio_tmr_end_capture(); @@ -2245,7 +2248,7 @@ static inline void isr_rx_conn(u8_t crc_ok, u8_t trx_done, radio_switch_complete_and_disable(); } } else { /* if (_radio.state == STATE_TX) */ - + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_rx(); radio_tmr_end_capture(); } @@ -2470,6 +2473,7 @@ static inline u32_t isr_close_obs(void) dont_close = 1; radio_pkt_rx_set(_radio.packet_rx[_radio.packet_rx_last]->pdu_data); + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_tx(); radio_rssi_measure(); @@ -4299,7 +4303,6 @@ static void adv_obs_conn_configure(u8_t phy) radio_reset(); radio_phy_set(phy); radio_tx_power_set(0); - radio_tmr_tifs_set(150); radio_isr_set(isr); } @@ -4352,6 +4355,7 @@ static void adv_setup(void) radio_pkt_tx_set(&_radio.advertiser.adv_data.data [_radio.advertiser.adv_data.first][0]); + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_rx(); bitmap = _radio.advertiser.chl_map_current; @@ -4576,6 +4580,7 @@ static void event_obs(u32_t ticks_at_expire, u32_t remainder, u16_t lazy, } radio_pkt_rx_set(_radio.packet_rx[_radio.packet_rx_last]->pdu_data); + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_tx(); radio_rssi_measure(); @@ -5871,6 +5876,7 @@ static void event_slave(u32_t ticks_at_expire, u32_t remainder, u16_t lazy, rx_packet_set(conn, (struct pdu_data *) _radio.packet_rx[_radio.packet_rx_last]->pdu_data); + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_tx(); #if defined(CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI) @@ -6008,6 +6014,7 @@ static void event_master(u32_t ticks_at_expire, u32_t remainder, u16_t lazy, connection_configure(conn); tx_packet_set(conn, pdu_data_tx); + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_rx(); /* Setup Radio Channel */ @@ -6054,6 +6061,7 @@ static void event_master(u32_t ticks_at_expire, u32_t remainder, u16_t lazy, rx_packet_set(conn, (struct pdu_data *)_radio. packet_rx[_radio.packet_rx_last]->pdu_data); + radio_tmr_tifs_set(RADIO_TIFS); radio_switch_complete_and_tx(); /* setup pkticker and hcto */