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);
