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

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit ac75328e122bd4b3fb0a2076cc80663a5230abc8
Author: raiden00pl <[email protected]>
AuthorDate: Fri Oct 16 17:11:02 2026 +0200

    arch/arm/nrf52: fix ACK handling
    
    While waiting for an ACK, nrf52_radioi8_state_rx() skips the frame
    filter but still sent an ACK for every received frame with the AR field
    set, also for frames addressed to other devices. Any received frame with
    a length of 5 was taken as the ACK, without checking the frame type, the
    FCS or the sequence number, and any other frame ended the wait with
    NO_ACK and left the ACK wait timer running.
    
    Ignore frames that are not a valid ACK and keep waiting
    (IEEE 802.15.4-2011 5.1.6.2), and fail the attempt on an ACK with
    another sequence number (5.1.6.4.3).
    
    The ACK wait was 44 symbols. 6.4.3 defines macAckWaitDuration as
    aUnitBackoffPeriod + aTurnaroundTime + phySHRDuration +
    ceiling(6 * phySymbolsPerOctet), 54 symbols for the 2.4 GHz O-QPSK PHY.
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 arch/arm/src/nrf52/nrf52_ieee802154_radio.c | 31 ++++++++++++++++++++++-------
 arch/arm/src/nrf52/nrf52_ieee802154_radio.h | 13 +++++++-----
 2 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_radio.c 
b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
index 77b71110d6b..282a8aeb3f0 100644
--- a/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
@@ -1748,9 +1748,12 @@ static void nrf52_radioi8_state_rx(struct 
nrf52_radioi8_dev_s *dev)
     }
 #endif
 
-  /* Start ACK handling now - this must be done in isr */
+  /* Start ACK handling now - this must be done in isr.  Frames are not
+   * filtered while we wait for our ACK, so they are not acknowledged.
+   */
 
-  if (dev->state.rxmode == NRF52_RXMODE_NORMAL &&
+  if (dev->radio->state.waitack == false &&
+      dev->state.rxmode == NRF52_RXMODE_NORMAL &&
       rxbuf[1] & IEEE802154_FRAMECTRL_ACKREQ &&
       rxbuf[0] != IEEE802154_ACK_FRAME_SIZE)
     {
@@ -1776,10 +1779,21 @@ static void nrf52_radioi8_state_rx(struct 
nrf52_radioi8_dev_s *dev)
         }
     }
 
-  /* We wait for TX ACK and this frame is ACK - confirm TX to MAC */
+  /* We wait for TX ACK and this is not a valid ACK frame - ignore it and
+   * keep waiting for the ACK (IEEE 802.15.4-2011 5.1.6.2, 5.1.6.4.3).
+   */
+
+  else if (rxbuf[0] != IEEE802154_ACK_FRAME_SIZE ||
+           (rxbuf[1] & IEEE802154_FRAMECTRL_FTYPE) != IEEE802154_FRAME_ACK ||
+           !NRF52_RADIO_GETREG(dev->radio->lower,
+                               NRF52_RADIO_CRCSTATUS_OFFSET))
+    {
+      dev->macops.rxenable((struct ieee802154_radio_s *)dev, true);
+    }
+
+  /* We wait for TX ACK and this is our ACK - confirm TX to MAC */
 
-  else if (rxbuf[0] == IEEE802154_ACK_FRAME_SIZE &&
-           dev->radio->state.waitack == true)
+  else if (rxbuf[3] == dev->radio->txbuf[3])
     {
       nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RXACKDONE, 0);
 
@@ -1804,13 +1818,16 @@ static void nrf52_radioi8_state_rx(struct 
nrf52_radioi8_dev_s *dev)
         }
     }
 
-  /* We wait for TX ACK and this is not ACK - notify TX failure */
+  /* We wait for TX ACK and the ACK has another sequence number - notify TX
+   * failure
+   */
 
   else
     {
-      /* Clear flag */
+      /* Clear flag and stop the ACK wait timer */
 
       dev->radio->state.waitack = false;
+      dev->tim->ops->stop(dev);
 
       /* And notify MAC */
 
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_radio.h 
b/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
index f5d09166720..6319dce9699 100644
--- a/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
@@ -47,11 +47,14 @@
 #define IEEE802154_MAX_BE             (5)
 #define IEEE802154_CW0                (2)
 
-/* ACK_SYM + turnaround symbols + backoff */
-
-#define IEEE802154_ACK_WAIT           (12+                              \
-                                       IEEE802154_TURN_AROUND_TIME+     \
-                                       IEEE802154_UNIT_BACKOFF_PERIOD)
+/* macAckWaitDuration: aUnitBackoffPeriod + aTurnaroundTime +
+ * phySHRDuration (10) + ceiling(6 * phySymbolsPerOctet (2)), in symbols
+ * (IEEE 802.15.4-2011 6.4.3)
+ */
+
+#define IEEE802154_ACK_WAIT           (IEEE802154_UNIT_BACKOFF_PERIOD + \
+                                       IEEE802154_TURN_AROUND_TIME +    \
+                                       10 + 12)
 
 /****************************************************************************
  * Public Types

Reply via email to