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 Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Chettimada 2017-05-01 05:52:57 +02:00 committed by Johan Hedberg
commit 75bff19541
3 changed files with 98 additions and 9 deletions

View file

@ -209,6 +209,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

View file

@ -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)

View file

@ -37,7 +37,8 @@
#include <bluetooth/log.h>
#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 */