Bluetooth: Controller: nrf53: Fix back-to-back Tx Rx implementation

Back-to-back Tx Rx implementation was incorrect for nRF53
that uses DPPI. Both current and next DPPI channels where
enabled in the implementation which only worked correctly
to have the right tIFS when current and next PDU length
were same.

Fix ensures that the correct current DPPI is subscribed
to by the radio subscribe.

The implementation has been refactor to be able to use the
current sw_tifs_toggle value in the HAL implementation.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2023-09-25 10:17:22 +02:00 committed by Carles Cufí
commit b61bd2364c
5 changed files with 142 additions and 76 deletions

View file

@ -718,7 +718,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla
#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
uint32_t delay;
hal_radio_sw_switch_setup(cc, ppi, sw_tifs_toggle);
hal_radio_sw_switch_setup(sw_tifs_toggle);
/* NOTE: As constants are passed to dir_curr and dir_next, the
* compiler should optimize out the redundant code path
@ -736,7 +736,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla
hal_radio_tx_chain_delay_ns_get(phy_curr,
flags_curr));
hal_radio_b2b_txen_on_sw_switch(ppi);
hal_radio_b2b_txen_on_sw_switch(cc, ppi);
} else {
/* If RX PHY is LE Coded, calculate for S8 coding.
* Assumption being, S8 has higher delay.
@ -746,7 +746,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla
flags_next) +
hal_radio_rx_chain_delay_ns_get(phy_curr, 1));
hal_radio_txen_on_sw_switch(ppi);
hal_radio_txen_on_sw_switch(cc, ppi);
}
#if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
@ -839,7 +839,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla
flags_curr)) +
(EVENT_CLOCK_JITTER_US << 1);
hal_radio_rxen_on_sw_switch(ppi);
hal_radio_rxen_on_sw_switch(cc, ppi);
} else {
delay = HAL_RADIO_NS2US_CEIL(
hal_radio_rx_ready_delay_ns_get(phy_next,
@ -848,7 +848,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla
flags_curr)) +
(EVENT_CLOCK_JITTER_US << 1);
hal_radio_b2b_rxen_on_sw_switch(ppi);
hal_radio_b2b_rxen_on_sw_switch(cc, ppi);
}
@ -982,6 +982,26 @@ void radio_switch_complete_and_b2b_rx(uint8_t phy_curr, uint8_t flags_curr,
#endif /* !CONFIG_BT_CTLR_TIFS_HW */
}
void radio_switch_complete_and_b2b_tx_disable(void)
{
#if defined(CONFIG_BT_CTLR_TIFS_HW)
NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk);
#else /* CONFIG_BT_CTLR_TIFS_HW */
NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE);
hal_radio_sw_switch_b2b_tx_disable(sw_tifs_toggle);
#endif /* !CONFIG_BT_CTLR_TIFS_HW */
}
void radio_switch_complete_and_b2b_rx_disable(void)
{
#if defined(CONFIG_BT_CTLR_TIFS_HW)
NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk);
#else /* CONFIG_BT_CTLR_TIFS_HW */
NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE);
hal_radio_sw_switch_b2b_rx_disable(sw_tifs_toggle);
#endif /* !CONFIG_BT_CTLR_TIFS_HW */
}
void radio_switch_complete_and_disable(void)
{
#if defined(CONFIG_BT_CTLR_TIFS_HW)

View file

@ -106,6 +106,8 @@ void radio_switch_complete_and_b2b_tx(uint8_t phy_curr, uint8_t flags_curr,
uint8_t phy_next, uint8_t flags_next);
void radio_switch_complete_and_b2b_rx(uint8_t phy_curr, uint8_t flags_curr,
uint8_t phy_next, uint8_t flags_next);
void radio_switch_complete_and_b2b_tx_disable(void);
void radio_switch_complete_and_b2b_rx_disable(void);
void radio_switch_complete_and_disable(void);
uint8_t radio_phy_flags_rx_get(void);

View file

@ -455,10 +455,7 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void)
#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
static inline void hal_radio_sw_switch_setup(
uint8_t compare_reg,
uint8_t radio_enable_ppi,
uint8_t ppi_group_index)
static inline void hal_radio_sw_switch_setup(uint8_t ppi_group_index)
{
/* Set up software switch mechanism for next Radio switch. */
@ -466,7 +463,7 @@ static inline void hal_radio_sw_switch_setup(
* over PPI[<HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI>]
*/
HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT =
HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT;
HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT;
nrf_dppi_subscribe_set(NRF_DPPIC,
HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(ppi_group_index)),
HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI);
@ -476,55 +473,70 @@ static inline void hal_radio_sw_switch_setup(
nrf_dppi_subscribe_clear(NRF_DPPIC,
HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(other_grp)));
}
static inline void hal_radio_txen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
{
/* Wire SW Switch timer event <compare_reg> to the
* PPI[<radio_enable_ppi>] for enabling Radio. Do
* not wire the task; it is done by the caller of
* the function depending on the desired direction
* (TX/RX).
*/
HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg) =
HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi);
}
static inline void hal_radio_txen_on_sw_switch(uint8_t ppi)
static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,
uint8_t radio_enable_ppi)
{
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, ppi);
}
static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t ppi)
{
/* NOTE: Calling radio_tmr_start/radio_tmr_start_us/radio_tmr_start_now
* after the radio_switch_complete_and_b2b_tx() call would have
* changed the PPI channel to HAL_RADIO_ENABLE_ON_TICK_PPI as we
* cannot double buffer the subscribe buffer. Hence, lets have
* both DPPI channel enabled (other one was enabled by the DPPI
* group when the Radio End occurred) so that when both timer
* trigger one of the DPPI is correct in the radio tx
* subscription.
/* Wire SW Switch timer event <compare_reg> to the
* PPI[<radio_enable_ppi>] for enabling Radio. Do
* not wire the task; it is done by the caller of
* the function depending on the desired direction
* (TX/RX).
*/
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, ppi);
nrf_dppi_channels_enable(NRF_DPPIC, BIT(ppi));
HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi);
}
static inline void hal_radio_rxen_on_sw_switch(uint8_t ppi)
static inline void hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
{
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, ppi);
}
static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t ppi)
{
/* NOTE: Calling radio_tmr_start/radio_tmr_start_us/radio_tmr_start_now
* after the radio_switch_complete_and_b2b_rx() call would have
* changed the PPI channel to HAL_RADIO_ENABLE_ON_TICK_PPI as we
* cannot double buffer the subscribe buffer. Hence, lets have
* both DPPI channel enabled (other one was enabled by the DPPI
* group when the Radio End occurred) so that when both timer
* trigger one of the DPPI is correct in the radio rx
* subscription.
/* Wire SW Switch timer event <compare_reg> to the
* PPI[<radio_enable_ppi>] for enabling Radio. Do
* not wire the task; it is done by the caller of
* the function depending on the desired direction
* (TX/RX).
*/
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, ppi);
nrf_dppi_channels_enable(NRF_DPPIC, BIT(ppi));
HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi);
}
static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,
uint8_t radio_enable_ppi)
{
/* Wire SW Switch timer event <compare_reg> to the
* PPI[<radio_enable_ppi>] for enabling Radio. Do
* not wire the task; it is done by the caller of
* the function depending on the desired direction
* (TX/RX).
*/
HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi);
}
static inline void hal_radio_sw_switch_disable(void)
@ -540,6 +552,26 @@ static inline void hal_radio_sw_switch_disable(void)
HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1)));
}
static inline void hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)
{
hal_radio_sw_switch_disable();
uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
uint8_t radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi);
}
static inline void hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)
{
hal_radio_sw_switch_disable();
uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
uint8_t radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi);
}
static inline void hal_radio_sw_switch_cleanup(void)
{
hal_radio_sw_switch_disable();

View file

@ -420,10 +420,7 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void)
#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX \
((uint32_t)&(NRF_RADIO->TASKS_RXEN))
static inline void hal_radio_sw_switch_setup(
uint8_t compare_reg,
uint8_t radio_enable_ppi,
uint8_t ppi_group_index)
static inline void hal_radio_sw_switch_setup(uint8_t ppi_group_index)
{
/* Set up software switch mechanism for next Radio switch. */
@ -435,53 +432,58 @@ static inline void hal_radio_sw_switch_setup(
HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI,
HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT,
HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(ppi_group_index));
}
static inline void hal_radio_txen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
{
/* Wire SW Switch timer event <compare_reg> to the
* PPI[<radio_enable_ppi>] for enabling Radio. Do
* not wire the task; it is done by the caller of
* the function depending on the desired direction
* (TX/RX).
*/
nrf_ppi_event_endpoint_setup(
NRF_PPI,
radio_enable_ppi,
HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg));
nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index));
nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
}
static inline void hal_radio_txen_on_sw_switch(uint8_t ppi)
{
nrf_ppi_task_endpoint_setup(
NRF_PPI,
ppi,
HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
}
static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t ppi)
static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,
uint8_t radio_enable_ppi)
{
/* NOTE: As independent PPI are used to trigger the Radio Tx task,
* double buffers implementation works for sw_switch using PPIs,
* simply reuse the hal_radio_txen_on_sw_switch() functon to set
* the next PPIs task to be Radio Tx enable.
*/
hal_radio_txen_on_sw_switch(ppi);
hal_radio_txen_on_sw_switch(compare_reg_index, radio_enable_ppi);
}
static inline void hal_radio_rxen_on_sw_switch(uint8_t ppi)
static inline void hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
{
nrf_ppi_task_endpoint_setup(
NRF_PPI,
ppi,
HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX);
}
static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t ppi)
{
/* NOTE: As independent PPI are used to trigger the Radio Rx task,
* double buffers implementation works for sw_switch using PPIs,
* simply reuse the hal_radio_rxen_on_sw_switch() functon to set
* the next PPIs task to be Radio Rx enable.
/* Wire SW Switch timer event <compare_reg> to the
* PPI[<radio_enable_ppi>] for enabling Radio. Do
* not wire the task; it is done by the caller of
* the function depending on the desired direction
* (TX/RX).
*/
hal_radio_rxen_on_sw_switch(ppi);
nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index));
nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX);
}
static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,
uint8_t radio_enable_ppi)
{
/* NOTE: As independent PPI are used to trigger the Radio Tx task,
* double buffers implementation works for sw_switch using PPIs,
* simply reuse the hal_radio_txen_on_sw_switch() functon to set
* the next PPIs task to be Radio Tx enable.
*/
hal_radio_rxen_on_sw_switch(compare_reg_index, radio_enable_ppi);
}
static inline void hal_radio_sw_switch_disable(void)
@ -496,6 +498,16 @@ static inline void hal_radio_sw_switch_disable(void)
BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI));
}
static inline void hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)
{
hal_radio_sw_switch_disable();
}
static inline void hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)
{
hal_radio_sw_switch_disable();
}
static inline void hal_radio_sw_switch_cleanup(void)
{
hal_radio_sw_switch_disable();

View file

@ -717,7 +717,7 @@ static void isr_tx_common(void *param,
pkt_flags);
}
radio_switch_complete_and_disable();
radio_switch_complete_and_b2b_tx_disable();
radio_isr_set(isr_done_term, lll);
} else {