You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2022/02/12 11:13:01 UTC

[mynewt-nimble] 02/02: nimble/phy/cmac: Fix race on rx-tx

This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit dbed9d46d551847f7580c22a1e56f088dfb47941
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Wed Feb 2 10:49:17 2022 +0100

    nimble/phy/cmac: Fix race on rx-tx
    
    On rx-tx transition we disable Frame and Field interrupts so they do
    not mess up tx setup process - they are reenabled in ble_phy_tx.
    
    However, after recent optimizations we are sometimes too fast and
    ble_phy_tx can be called before interrupts are disabled. This means
    there's nothing to enable interrupts again and this will trigger a
    CMAC error since we are not processing interrupts on time.
    
    To fix this we add flag to check whether ble_phy_tx already finished
    setup so there's no need to disable interrupts on transition.
---
 nimble/drivers/dialog_cmac/src/ble_phy.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/nimble/drivers/dialog_cmac/src/ble_phy.c b/nimble/drivers/dialog_cmac/src/ble_phy.c
index e36a31c..9c9d878 100644
--- a/nimble/drivers/dialog_cmac/src/ble_phy.c
+++ b/nimble/drivers/dialog_cmac/src/ble_phy.c
@@ -262,6 +262,7 @@ struct ble_phy_data {
     struct ble_mbuf_hdr rxhdr;
     ble_phy_tx_end_func txend_cb;
     void *txend_arg;
+    uint8_t phy_tx_set;
 };
 
 static struct ble_phy_data g_ble_phy_data;
@@ -647,6 +648,8 @@ ble_phy_irq_frame_tx_exc_bs_stop(void)
                                  CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk;
     }
 
+    g_ble_phy_data.phy_tx_set = 0;
+
     if (g_ble_phy_data.txend_cb) {
         ble_phy_sw_mac_handover(SW_MAC_EXC_TXEND_CB);
         return;
@@ -897,13 +900,16 @@ ble_phy_irq_frame_rx_exc_phy_to_idle_4this(void)
 #endif
     rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel];
     ble_rf_setup_tx(rf_chan, g_ble_phy_data.phy_mode_tx);
+
     g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
 
     /* We do not want FIELD/FRAME interrupts until ble_phy_tx() has pushed all
      * fields.
      */
-    NVIC_DisableIRQ(FRAME_IRQn);
-    NVIC_DisableIRQ(FIELD_IRQn);
+    if (!g_ble_phy_data.phy_tx_set) {
+        NVIC_DisableIRQ(FRAME_IRQn);
+        NVIC_DisableIRQ(FIELD_IRQn);
+    }
 }
 
 static void
@@ -1278,6 +1284,7 @@ ble_phy_disable(void)
     NVIC_EnableIRQ(FIELD_IRQn);
 
     g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+    g_ble_phy_data.phy_tx_set = 0;
 }
 
 static void
@@ -1460,6 +1467,8 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
         rc = BLE_ERR_SUCCESS;
     }
 
+    g_ble_phy_data.phy_tx_set = 1;
+
     /* Now we can handle BS_CTRL */
     NVIC_EnableIRQ(FRAME_IRQn);
     NVIC_EnableIRQ(FIELD_IRQn);