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 fe32cd0f649ec510a392e4b0d45489b5466fcca2
Author: raiden00pl <[email protected]>
AuthorDate: Fri Oct 16 11:11:05 2026 +0200

    arch/arm/nrf52: fix energy detection
    
    EDCNT is the number of 8-symbol ED iterations minus one (the Nordic
    nrf_802154 driver writes the iteration count minus one), but the driver
    wrote the requested number of symbols into it, so every ED measurement
    lasted 8 times longer than requested: an ED scan of 2 channels took
    32.2 s instead of 5.2 s.
    
    ED is started by the READY event, but TASKS_RXEN has no effect while
    the radio is already receiving, so an ED scan on a node with RX enabled
    never completed and blocked the MAC. Disable the radio first and
    restore RX when the scan is finished.
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 arch/arm/src/nrf52/nrf52_ieee802154_radio.c | 40 ++++++++++++++++++++++++++++-
 arch/arm/src/nrf52/nrf52_ieee802154_radio.h |  1 +
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_radio.c 
b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
index ca46bf9f29e..3028efe9faf 100644
--- a/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
@@ -51,6 +51,10 @@
 
 #define NRF52_ED_RSSISCALE            (4)
 
+/* One ED iteration lasts 8 symbols (128 us) */
+
+#define NRF52_ED_ITER_SYMBOLS         (8)
+
 /* ED configuration:
  *   - IRQ on EDEND event (sampling of energy detection complete)
  *   - shortcut between READY and EDSTART
@@ -725,10 +729,35 @@ static int nrf52_radioi8_energydetect(struct 
nrf52_radioi8_dev_s *dev,
                                       uint32_t nsymbols)
 {
   struct nrf52_radio_dev_s *lower = NULL;
+  uint32_t                  edcnt = 0;
 
   DEBUGASSERT(dev);
   lower = dev->radio->lower;
 
+  /* ED lasts (EDCNT + 1) iterations */
+
+  edcnt = nsymbols / NRF52_ED_ITER_SYMBOLS;
+  if (edcnt > 0)
+    {
+      edcnt -= 1;
+    }
+
+  if (edcnt > RADIO_EDCNT_MASK)
+    {
+      edcnt = RADIO_EDCNT_MASK;
+    }
+
+  /* ED starts on the READY event, RXEN has no effect if RX is active */
+
+  if (dev->radio->state.rxenabled)
+    {
+      dev->radio->state.edrestore = true;
+      dev->radio->ops->rxenable(dev, false);
+    }
+
+  while (NRF52_RADIO_GETREG(lower, NRF52_RADIO_STATE_OFFSET) !=
+         RADIO_STATE_DISABLED);
+
   /* Clear events */
 
   NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_EDEND_OFFSET, 0);
@@ -742,7 +771,7 @@ static int nrf52_radioi8_energydetect(struct 
nrf52_radioi8_dev_s *dev,
 
   /* Configure ED symbols */
 
-  NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EDCNT_OFFSET, nsymbols);
+  NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EDCNT_OFFSET, edcnt);
 
   /* Set state to ENERGY_DETECT (ED) */
 
@@ -1616,6 +1645,15 @@ static void nrf52_radioi8_work_ed(void *arg)
   /* Callback the receiver in the next highest layer */
 
   dev->radiocb->edresult(dev->radiocb, ed);
+
+  /* Restore RX if it was enabled and no next ED was started */
+
+  if (dev->radio->state.edrestore &&
+      dev->radio->state.state != NRF52_RADIO_STATE_ED)
+    {
+      dev->radio->state.edrestore = false;
+      dev->radio->ops->rxenable(dev, true);
+    }
 }
 
 /****************************************************************************
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_radio.h 
b/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
index 7bb45774258..c64525300f0 100644
--- a/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
@@ -88,6 +88,7 @@ struct nrf52_radioi8_radio_data_s
 
   bool     rxenabled;           /* RX enabled now */
   bool     rxrestore;           /* RX needs to be restored */
+  bool     edrestore;           /* RX needs to be restored after ED */
   bool     rxlong;              /* Last RX frame was long */
 
   /* TX state */

Reply via email to