From 5de98708c1b5f76f3154dedb3825d3dc0bbe2269 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 4 Jun 2018 13:58:51 +0200 Subject: [PATCH] nimble/phy: Fix late wfr setup wfr is set using CC[0] or CC[2] as reference, but since CPU may be halted for a brief moment between timer capture and wfr calculations it may happen that TIMER0 already counted past calculated value and compare will not occur as expected. This can leave radio stuck in RX state, e.g. in case we are advertising and waiting for scan/connect req after TX. To fix this we'll just check if wfr is set past current TIMER0 counter value and if so, we'll disable radio manually as if wfr fired. This is similar to 06cfc0b0 but happens for reverse transition. --- nimble/drivers/nrf52/src/ble_phy.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c index fd6634ecb..35758bb5a 100644 --- a/nimble/drivers/nrf52/src/ble_phy.c +++ b/nimble/drivers/nrf52/src/ble_phy.c @@ -673,6 +673,24 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) /* Enable the disabled interrupt so we time out on events compare */ NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; + + /* + * It may happen that if CPU is halted for a brief moment (e.g. during flash + * erase or write), TIMER0 already counted past CC[3] and thus wfr will not + * fire as expected. In case this happened, let's just disable PPIs for wfr + * and trigger wfr manually (i.e. disable radio). + * + * Note that the same applies to RX start time set in CC[0] but since it + * should fire earlier than wfr, fixing wfr is enough. + * + * CC[1] is only used as a reference on RX start, we do not need it here so + * it can be used to read TIMER0 counter. + */ + NRF_TIMER0->TASKS_CAPTURE[1] = 1; + if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) { + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; + NRF_RADIO->TASKS_DISABLE = 1; + } } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)