Merge pull request #910 from andrzej-kaczmarek/cmac-tx-late-one-more-attempt

nimble/phy: Fix tx_late handling
diff --git a/nimble/drivers/dialog_cmac/src/ble_phy.c b/nimble/drivers/dialog_cmac/src/ble_phy.c
index d5767c5..ab0f885 100644
--- a/nimble/drivers/dialog_cmac/src/ble_phy.c
+++ b/nimble/drivers/dialog_cmac/src/ble_phy.c
@@ -46,6 +46,9 @@
     STATS_SECT_ENTRY(tx_good)
     STATS_SECT_ENTRY(tx_fail)
     STATS_SECT_ENTRY(tx_late)
+    STATS_SECT_ENTRY(tx_late_sched)
+    STATS_SECT_ENTRY(tx_late_frame)
+    STATS_SECT_ENTRY(tx_late_field)
     STATS_SECT_ENTRY(tx_bytes)
     STATS_SECT_ENTRY(rx_starts)
     STATS_SECT_ENTRY(rx_aborts)
@@ -63,6 +66,9 @@
     STATS_NAME(ble_phy_stats, tx_good)
     STATS_NAME(ble_phy_stats, tx_fail)
     STATS_NAME(ble_phy_stats, tx_late)
+    STATS_NAME(ble_phy_stats, tx_late_sched)
+    STATS_NAME(ble_phy_stats, tx_late_frame)
+    STATS_NAME(ble_phy_stats, tx_late_field)
     STATS_NAME(ble_phy_stats, tx_bytes)
     STATS_NAME(ble_phy_stats, rx_starts)
     STATS_NAME(ble_phy_stats, rx_aborts)
@@ -1242,6 +1248,15 @@
     g_ble_phy_encrypt_data.ai[0] = 0x01;
 #endif
 
+    /*
+     * Disable FIELD1, FIELD2 and FRAME errors since they can happen
+     * sometimes if we are too late on scheduling and trigger CMAC
+     * error. We can detect if tx_late happened and recover properly.
+     */
+    CMAC->CM_ERROR_DIS_REG |= CMAC_CM_ERROR_DIS_REG_CM_FIELD1_ERR_Msk |
+                              CMAC_CM_ERROR_DIS_REG_CM_FIELD2_ERR_Msk |
+                              CMAC_CM_ERROR_DIS_REG_CM_FRAME_ERR_Msk;
+
     return 0;
 }
 
@@ -1274,8 +1289,6 @@
     os_arch_cmac_bs_ctrl_irq_unblock();
     g_sw_mac_exc = 0;
 
-    CMAC->CM_ERROR_DIS_REG = 0;
-
     ble_rf_stop();
 
     /*
@@ -1455,6 +1468,7 @@
     if (CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk) {
         ble_phy_disable();
         g_ble_phy_data.end_transition = BLE_PHY_TRANSITION_NONE;
+        STATS_INC(ble_phy_stats, tx_late_field);
         STATS_INC(ble_phy_stats, tx_late);
         rc = BLE_PHY_ERR_RADIO_STATE;
     } else {
@@ -1467,7 +1481,6 @@
     }
 
     /* Now we can handle BS_CTRL */
-    CMAC->CM_ERROR_DIS_REG &= ~CMAC_CM_ERROR_DIS_REG_CM_FIELD1_ERR_Msk;
     NVIC_EnableIRQ(FRAME_IRQn);
     NVIC_EnableIRQ(FIELD_IRQn);
 
@@ -1499,20 +1512,17 @@
     assert((int32_t)(ll_val32 - cmac_timer_read32()) < 1024);
 
     /*
-     * We do not want FIELD/FRAME interrupts or FIELD1_ERR until ble_phy_tx()
-     * has finished pushing all the fields. Also we do not want premature
-     * FRAME_ERR so disable it until we program FRAME1 properly. If we won't
-     * make configuration on time, assume tx_late and abort TX.
+     * We do not want FIELD/FRAME interrupts until ble_phy_tx() has
+     * pushed all fields.
      */
     NVIC_DisableIRQ(FRAME_IRQn);
     NVIC_DisableIRQ(FIELD_IRQn);
-    CMAC->CM_ERROR_DIS_REG |= CMAC_CM_ERROR_DIS_REG_CM_FIELD1_ERR_Msk |
-                              CMAC_CM_ERROR_DIS_REG_CM_FRAME_ERR_Msk;
 
     CMAC->CM_LL_TIMER1_9_0_EQ_X_REG = ll_val32;
     CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_TMR1_9_0_EQ_X_Msk;
 
     if ((int32_t)(ll_val32 - cmac_timer_read32()) < 0) {
+        STATS_INC(ble_phy_stats, tx_late_sched);
         goto tx_late;
     }
 
@@ -1529,10 +1539,10 @@
      * need to assume tx_late and abort.
      */
     if (CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) {
+        STATS_INC(ble_phy_stats, tx_late_frame);
         goto tx_late;
     }
 
-    CMAC->CM_ERROR_DIS_REG &= ~CMAC_CM_ERROR_DIS_REG_CM_FRAME_ERR_Msk;
     rc = 0;
 
     goto done;