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

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

commit 957fe178af5ac23516f941a2c24ecdc15154b66f
Author: raiden00pl <[email protected]>
AuthorDate: Thu Oct 22 16:59:21 2026 +0200

    drivers/wireless/ieee802154/mrf24j40: implement the energy detect
    
    energydetect() returned -ENOTTY, so the MAC energy scan failed.  Enable
    the LNA for the scan, sample the averaged RSSI (datasheet 3.6.1) from a
    work until the scan duration ends, each wait bounded by the averaging
    time, and report the highest value.  A reset ends the scan.
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 drivers/wireless/ieee802154/mrf24j40/mrf24j40.c    | 61 +++++---------
 drivers/wireless/ieee802154/mrf24j40/mrf24j40.h    |  9 +++
 .../wireless/ieee802154/mrf24j40/mrf24j40_radif.c  | 92 +++++++++++++++++++++-
 3 files changed, 121 insertions(+), 41 deletions(-)

diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c 
b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c
index ac55272d41b..4c2851c9aa4 100644
--- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c
+++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c
@@ -35,6 +35,7 @@
 
 #include <sys/types.h>
 
+#include <nuttx/arch.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/wqueue.h>
 #include <nuttx/mm/iob.h>
@@ -54,70 +55,50 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-#if 0
-static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev,
-                                 FAR uint8_t *energy);
-#endif
-
-/****************************************************************************
- * Private Functions
+ * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: mrf24j40_energydetect
+ * Name: mrf24j40_rssi
  *
  * Description:
- *   Measure the RSSI level for the current channel.
+ *   Measure the averaged RSSI level for the current channel (datasheet
+ *   3.6.1), the LNA is enabled by the caller.
  *
  ****************************************************************************/
 
-#if 0
-static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev,
-                                 FAR uint8_t *energy)
+int mrf24j40_rssi(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *rssi)
 {
-  uint8_t reg;
-
-  /* Manually enable the LNA */
-
-  mrf24j40_setpamode(dev, MRF24J40_PA_ED);
-
-  /* Set RSSI average duration to 8 symbols */
-
-  reg  = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1);
-  reg |= 0x30;
-  mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg);
+  int wait;
 
   /* 1. Set RSSIMODE1 0x3E<7> - Initiate RSSI calculation. */
 
   mrf24j40_setreg(dev->spi, MRF24J40_BBREG6, 0x80);
 
   /* 2. Wait until RSSIRDY 0x3E<0> is set to '1' - RSSI calculation is
-   *    complete.
+   *    complete.  The RSSI is averaged over MRF24J40_RSSI_SYMBOLS, wait
+   *    at most twice as long.
    */
 
-  while (!(mrf24j40_getreg(dev->spi, MRF24J40_BBREG6) & 0x01));
+  for (wait = 0; wait < 2 * MRF24J40_RSSI_SYMBOLS; wait++)
+    {
+      if (mrf24j40_getreg(dev->spi, MRF24J40_BBREG6) & 0x01)
+        {
+          break;
+        }
+
+      up_udelay(IEEE802154_SYMBOL_US);
+    }
 
   /* 3. Read RSSI 0x210<7:0> - The RSSI register contains the averaged RSSI
-   *    received power level for 8 symbol periods.
+   *    received power level.
    */
 
-  *energy = mrf24j40_getreg(dev->spi, MRF24J40_RSSI);
+  *rssi = mrf24j40_getreg(dev->spi, MRF24J40_RSSI);
   mrf24j40_setreg(dev->spi, MRF24J40_BBREG6, 0x40);
 
-  /* Back to automatic control */
-
-  mrf24j40_setpamode(dev, MRF24J40_PA_AUTO);
-
-  return OK;
+  return wait < 2 * MRF24J40_RSSI_SYMBOLS ? OK : -ETIMEDOUT;
 }
-#endif
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
 
 /****************************************************************************
  * Function: mrf24j40_dopoll_csma
diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h 
b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h
index fcd2c368b43..113371fe1f3 100644
--- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h
+++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h
@@ -61,6 +61,10 @@
 #define MRF24J40_PA_ED     2
 #define MRF24J40_PA_SLEEP  3
 
+/* Symbols the RSSI is averaged over, TXBCON1 RSSINUM = 11 */
+
+#define MRF24J40_RSSI_SYMBOLS 8
+
 /* Formula for calculating default macMaxFrameWaitTime is on pg. 130
  *
  * For PHYs other than CSS and UWB, the attribute phyMaxFrameDuration
@@ -121,6 +125,10 @@ struct mrf24j40_radio_s
   struct work_s irqwork;       /* For deferring interrupt work to work queue */
   struct work_s csma_pollwork; /* For deferring poll work to the work queue */
   struct work_s gts_pollwork;  /* For deferring poll work to the work queue */
+  struct work_s edwork;        /* Energy detect sampling */
+
+  clock_t ed_end;              /* End of the energy detect, in ticks */
+  uint8_t edmax;               /* Highest RSSI of the energy detect */
 
   mutex_t       lock;          /* Exclusive access to this struct */
 
@@ -209,6 +217,7 @@ void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev,
               FAR const uint8_t *buf, uint8_t length, uint32_t fifo_addr);
 
 void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev);
+int mrf24j40_rssi(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *rssi);
 void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev);
 
 #endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_MRF24J40_H */
diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c 
b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c
index af9395b1271..9a7fd3e70e9 100644
--- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c
+++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c
@@ -27,12 +27,15 @@
 #include <nuttx/config.h>
 
 #include <assert.h>
+#include <errno.h>
 #include <nuttx/debug.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
 
 #include <nuttx/arch.h>
+#include <nuttx/clock.h>
+#include <nuttx/wqueue.h>
 #include <nuttx/wireless/ieee802154/ieee802154_radio.h>
 #include <nuttx/wireless/ieee802154/ieee802154_mac.h>
 #include <nuttx/wireless/ieee802154/mrf24j40.h>
@@ -46,6 +49,10 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* RSSI samples taken by one energy detect work before it yields */
+
+#define MRF24J40_ED_SAMPLES 8
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -411,10 +418,83 @@ int mrf24j40_rxenable(FAR struct ieee802154_radio_s 
*radio, bool enable)
   return OK;
 }
 
+/****************************************************************************
+ * Name: mrf24j40_edworker
+ *
+ * Description:
+ *   Sample the RSSI until the end of the energy detect.
+ *
+ ****************************************************************************/
+
+static void mrf24j40_edworker(FAR void *arg)
+{
+  FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg;
+  uint8_t rssi;
+  int ret = OK;
+  int i;
+
+  nxmutex_lock(&dev->lock);
+
+  for (i = 0; i < MRF24J40_ED_SAMPLES && ret == OK; i++)
+    {
+      ret = mrf24j40_rssi(dev, &rssi);
+      if (ret == OK && rssi > dev->edmax)
+        {
+          dev->edmax = rssi;
+        }
+    }
+
+  if (ret == OK && !clock_compare(dev->ed_end, clock_systime_ticks()))
+    {
+      nxmutex_unlock(&dev->lock);
+      work_queue(HPWORK, &dev->edwork, mrf24j40_edworker, dev, 1);
+      return;
+    }
+
+  /* Done, or the RSSI did not get ready: the LNA is back under automatic
+   * control and the highest value so far is reported
+   */
+
+  mrf24j40_setpamode(dev, MRF24J40_PA_AUTO);
+  nxmutex_unlock(&dev->lock);
+
+  if (ret < 0)
+    {
+      wlerr("ERROR: RSSI not ready: %d\n", ret);
+    }
+
+  dev->radiocb->edresult(dev->radiocb, dev->edmax);
+}
+
 int mrf24j40_energydetect(FAR struct ieee802154_radio_s *radio,
                           uint32_t nsymbols)
 {
-  return -ENOTTY;
+  FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
+  int ret;
+
+  ret = nxmutex_lock(&dev->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (!work_available(&dev->edwork))
+    {
+      nxmutex_unlock(&dev->lock);
+      return -EBUSY;
+    }
+
+  /* The LNA is enabled for the whole energy detect */
+
+  mrf24j40_setpamode(dev, MRF24J40_PA_ED);
+
+  dev->edmax  = 0;
+  dev->ed_end = clock_systime_ticks() +
+                USEC2TICK(nsymbols * IEEE802154_SYMBOL_US);
+
+  nxmutex_unlock(&dev->lock);
+
+  return work_queue(HPWORK, &dev->edwork, mrf24j40_edworker, dev, 0);
 }
 
 int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
@@ -424,6 +504,10 @@ int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
   uint8_t eaddr[8];
   int reg;
 
+  /* An energy detect in progress ends here */
+
+  work_cancel_sync(HPWORK, &dev->edwork);
+
   /* Software reset */
 
   mrf24j40_setreg(dev->spi, MRF24J40_SOFTRST  , 0x07); /* 00000111 Reset */
@@ -488,6 +572,12 @@ int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
 
   mrf24j40_setorder(dev, 15, 15);
 
+  /* The RSSI is averaged over MRF24J40_RSSI_SYMBOLS (TXBCON1 RSSINUM) */
+
+  reg  = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1);
+  reg |= MRF24J40_TXBCON1_RSSINUM;
+  mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg);
+
   dev->rxenabled = false;
 
   mrf24j40_setchannel(dev, 11);

Reply via email to