From 19de3372b700713cbd431c898d2fc42ce9329de7 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Sun, 9 Jul 2017 18:38:56 -0400 Subject: [PATCH 01/11] ieee802154: Minor renaming. purge_time -> purgetime --- include/nuttx/wireless/ieee802154/ieee802154_radio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nuttx/wireless/ieee802154/ieee802154_radio.h b/include/nuttx/wireless/ieee802154/ieee802154_radio.h index b6e802e0ea..7617d03685 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_radio.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_radio.h @@ -84,7 +84,7 @@ struct ieee802154_txdesc_s * control how tx done is handled */ bool framepending; /* Did the ACK have the frame pending bit * bit set */ - uint32_t purge_time; /* Time to purge transaction */ + uint32_t purgetime; /* Time to purge transaction */ /* TODO: Add slotting information for GTS transactions */ }; From 93cdae50fc6ec529eb40f3b813decf3f1fc02a33 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Sun, 9 Jul 2017 23:55:48 -0400 Subject: [PATCH 02/11] ieee802154: Improves internal timer logic to handle work serially Before, the MAC timer used a watchdog to schedule work with the high priority worker queue. However, since everything in the MAC is supposed to be serialized through the use of the high priority work queue, but the timer uses a watchdog, there are some unintended consequences. To simplify, we now use the delayed work feature of the work queue. --- wireless/ieee802154/mac802154.c | 130 ----------------------- wireless/ieee802154/mac802154_assoc.c | 16 ++- wireless/ieee802154/mac802154_internal.h | 86 ++++++++++++--- wireless/ieee802154/mac802154_poll.c | 18 +++- wireless/ieee802154/mac802154_scan.c | 5 +- 5 files changed, 106 insertions(+), 149 deletions(-) diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index 3a7989e9d8..cf7ebba212 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -92,13 +92,6 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb, static void mac802154_purge_worker(FAR void *arg); -/* Watchdog Timeout Functions */ - -static void mac802154_timeout_expiry(int argc, wdparm_t arg, ...); - -static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, - uint32_t symbols); - static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_data_ind_s *ind); static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv, @@ -1918,125 +1911,6 @@ errout: mac802154_notif_free_locked(priv, notif); } -/**************************************************************************** - * Name: mac802154_symtoticks - * - * Description: - * Helper function for converting symbols to system clock ticks - * - * Assumptions: - * priv MAC struct is locked when calling. - * - ****************************************************************************/ - -static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, - uint32_t symbols) -{ - union ieee802154_attr_u attrval; - uint32_t ret; - - /* First, get the symbol duration from the radio layer. Symbol duration is - * returned in picoseconds to ensure precision is kept when multiplying to - * get overall times. - */ - - priv->radio->getattr(priv->radio, IEEE802154_ATTR_PHY_SYMBOL_DURATION, - &attrval); - - /* After this step, ret represents microseconds */ - - ret = ((uint64_t)attrval.phy.symdur_picosec * symbols) / (1000 * 1000); - - /* This method should only be used for things that can be late. For instance, - * it's always okay to wait a little longer before disabling your receiver. - * Therefore, we force the tick count to round up. - */ - - if (ret % USEC_PER_TICK == 0) - { - ret = ret/USEC_PER_TICK; - } - else - { - ret = ret/USEC_PER_TICK; - ret++; - } - - return ret; -} - -/**************************************************************************** - * Name: mac802154_timerstart - * - * Description: - * Helper function wrapping the watchdog timer interface. Helps isolate - * different operations from having to worry about work queues and watchdog - * timers. - * - * Assumptions: - * priv MAC struct is locked when calling. - * - ****************************************************************************/ - -int mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, - uint32_t numsymbols, mac802154_worker_t worker) -{ - /* TODO: Add check to make sure timer is not already being used. I'd like to - * design this so that it absolutely never happens */ - - /* Convert the number of symbols to the number of CPU ticks */ - - uint32_t ticks = mac802154_symtoticks(priv, numsymbols); - - /* Save the function pointer to call if the timeout expires */ - - priv->timeout_worker = worker; - - /* Start the watchdog */ - - wd_start(priv->timeout, (int32_t)ticks, mac802154_timeout_expiry, - 1, (wdparm_t)priv); - - return OK; -} - -/**************************************************************************** - * Function: mac802154_timeout_expiry - * - * Description: - * The watchdog timed out. Called from the timer interrupt handler. - * - * Parameters: - * argc - The number of available arguments - * arg - The first argument - * - * Returned Value: - * None - * - * Assumptions: - * Global interrupts are disabled by the watchdog logic. - * - ****************************************************************************/ - -static void mac802154_timeout_expiry(int argc, wdparm_t arg, ...) -{ - FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; - - /* There should never be a case where the timeout is used twice at the same - * time. */ - - DEBUGASSERT(work_available(&priv->timeout_work)); - - /* Check to make sure the function pointer is still valid */ - - DEBUGASSERT(priv->timeout_worker != NULL); - - wlinfo("Timer expired\n"); - - work_queue(MAC802154_WORK, &priv->timeout_work, (worker_t)priv->timeout_worker, - priv, 0); -} - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -2092,10 +1966,6 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev) sem_init(&mac->opsem, 0, 1); - /* Setup watchdog for extraction timeout */ - - mac->timeout = wd_create(); - /* Initialize fields */ mac->radio = radiodev; diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index beaf1c34f6..42ee5c4618 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -58,7 +58,7 @@ * Private Function Prototypes ****************************************************************************/ -static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv); +static void mac802154_assoctimeout(FAR void *arg); /**************************************************************************** * Public MAC Functions @@ -858,10 +858,22 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv, * ****************************************************************************/ -static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv) +static void mac802154_assoctimeout(FAR void *arg) { + FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; FAR struct ieee802154_notif_s *notif; + /* If there is work scheduled for the rxframe_worker, we want to reschedule + * this work, so that we make sure if the frame we were waiting for was just + * received, we don't timeout + */ + + if (!work_available(&priv->rx_work)) + { + work_queue(MAC802154_WORK, &priv->timer_work, mac802154_assoctimeout, priv, 0); + return; + } + DEBUGASSERT(priv->curr_op == MAC802154_OP_ASSOC); /* If the device does not extract an association response command diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index fc097cfbf6..6fcfaaeb8e 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -139,9 +139,6 @@ enum mac802154_operation_e MAC802154_OP_AUTOEXTRACT, }; -struct ieee802154_privmac_s; /* Forward Reference */ -typedef void (*mac802154_worker_t)(FAR struct ieee802154_privmac_s *priv); - /* The privmac structure holds the internal state of the MAC and is the * underlying represention of the opaque MACHANDLE. It contains storage for * the IEEE802.15.4 MIB attributes. @@ -254,12 +251,8 @@ struct ieee802154_privmac_s struct work_s tx_work; struct work_s rx_work; - - struct work_s timeout_work; - WDOG_ID timeout; /* Timeout watchdog */ - mac802154_worker_t timeout_worker; - struct work_s purge_work; + struct work_s timer_work; /****************** Uncategorized MAC PIB attributes ***********************/ @@ -375,9 +368,6 @@ int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_txdesc_s **txdesc, bool allow_interrupt); -int mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, - uint32_t numsymbols, mac802154_worker_t); - void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_txdesc_s *txdesc); @@ -624,6 +614,77 @@ static inline void mac802154_txdesc_free(FAR struct ieee802154_privmac_s *priv, mac802154_givesem(&priv->txdesc_sem); } +/**************************************************************************** + * Name: mac802154_symtoticks + * + * Description: + * Helper function for converting symbols to system clock ticks + * + * Assumptions: + * priv MAC struct is locked when calling. + * + ****************************************************************************/ + +static inline uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, + uint32_t symbols) +{ + union ieee802154_attr_u attrval; + uint32_t ret; + + /* First, get the symbol duration from the radio layer. Symbol duration is + * returned in picoseconds to ensure precision is kept when multiplying to + * get overall times. + */ + + priv->radio->getattr(priv->radio, IEEE802154_ATTR_PHY_SYMBOL_DURATION, + &attrval); + + /* After this step, ret represents microseconds */ + + ret = ((uint64_t)attrval.phy.symdur_picosec * symbols) / (1000 * 1000); + + /* This method should only be used for things that can be late. For instance, + * it's always okay to wait a little longer before disabling your receiver. + * Therefore, we force the tick count to round up. + */ + + if (ret % USEC_PER_TICK == 0) + { + ret = ret/USEC_PER_TICK; + } + else + { + ret = ret/USEC_PER_TICK; + ret++; + } + + return ret; +} + +/**************************************************************************** + * Name: mac802154_timerstart + * + * Description: + * Helper function wrapping the watchdog timer interface. Helps isolate + * different operations from having to worry about work queues and watchdog + * timers. + * + * Assumptions: + * priv MAC struct is locked when calling. + * + ****************************************************************************/ + +static inline void mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, + uint32_t numsymbols, worker_t worker) +{ + DEBUGASSERT(work_available(&priv->timer_work)); + + /* Schedule the work, converting the number of symbols to the number of CPU ticks */ + + work_queue(MAC802154_WORK, &priv->timer_work, worker, priv, + mac802154_symtoticks(priv, numsymbols)); +} + /**************************************************************************** * Name: mac802154_timercancel * @@ -637,8 +698,7 @@ static inline void mac802154_txdesc_free(FAR struct ieee802154_privmac_s *priv, static inline int mac802154_timercancel(FAR struct ieee802154_privmac_s *priv) { - wd_cancel(priv->timeout); - priv->timeout_worker = NULL; + work_cancel(MAC802154_WORK, &priv->timer_work); wlinfo("Timer cancelled\n"); return OK; } diff --git a/wireless/ieee802154/mac802154_poll.c b/wireless/ieee802154/mac802154_poll.c index 715518e916..3271a8f92a 100644 --- a/wireless/ieee802154/mac802154_poll.c +++ b/wireless/ieee802154/mac802154_poll.c @@ -60,7 +60,7 @@ * Private Function Prototypes ****************************************************************************/ -static void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv); +static void mac802154_polltimeout(FAR void *arg); /**************************************************************************** * Public MAC Functions @@ -152,6 +152,8 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req) priv->cmd_desc = txdesc; + wlinfo("Queuing POLL.request in CSMA queue\n"); + /* Link the transaction into the CSMA transaction list */ sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue); @@ -259,10 +261,22 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv, * ****************************************************************************/ -void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv) +void mac802154_polltimeout(FAR void *arg) { + FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; FAR struct ieee802154_notif_s *notif; + /* If there is work scheduled for the rxframe_worker, we want to reschedule + * this work, so that we make sure if the frame we were waiting for was just + * received, we don't timeout + */ + + if (!work_available(&priv->rx_work)) + { + work_queue(MAC802154_WORK, &priv->timer_work, mac802154_polltimeout, priv, 0); + return; + } + DEBUGASSERT(priv->curr_op == MAC802154_OP_POLL); /* Allocate a notification struct to pass to the next highest layer. diff --git a/wireless/ieee802154/mac802154_scan.c b/wireless/ieee802154/mac802154_scan.c index c24ae0b5f1..0c6140b192 100644 --- a/wireless/ieee802154/mac802154_scan.c +++ b/wireless/ieee802154/mac802154_scan.c @@ -60,7 +60,7 @@ * Private Function Prototypes ****************************************************************************/ -static void mac802154_scantimeout(FAR struct ieee802154_privmac_s *priv); +static void mac802154_scantimeout(FAR void *arg); /**************************************************************************** * Public MAC Functions @@ -251,8 +251,9 @@ void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv, * ****************************************************************************/ -static void mac802154_scantimeout(FAR struct ieee802154_privmac_s *priv) +static void mac802154_scantimeout(FAR void *arg) { + FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; DEBUGASSERT(priv->curr_op == MAC802154_OP_SCAN); /* If we got here it means we are done scanning that channel */ From b9a9ba7dd03a57740dd08a0b015582eb13b7aa36 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Sun, 9 Jul 2017 23:57:11 -0400 Subject: [PATCH 03/11] ieee802154: Adds configuration options for verbose logging of certain features, to aid in debugging --- configs/clicker2-stm32/Kconfig | 7 +++++++ configs/clicker2-stm32/src/stm32_mrf24j40.c | 5 ++++- drivers/wireless/ieee802154/mrf24j40/mrf24j40.c | 3 +++ wireless/ieee802154/Kconfig | 14 ++++++++++++++ wireless/ieee802154/mac802154.c | 2 ++ wireless/ieee802154/mac802154_internal.h | 11 ++++++++++- 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/configs/clicker2-stm32/Kconfig b/configs/clicker2-stm32/Kconfig index 9344f015da..fb4b89d98a 100644 --- a/configs/clicker2-stm32/Kconfig +++ b/configs/clicker2-stm32/Kconfig @@ -35,4 +35,11 @@ config CLICKER2_STM32_MB2_BEE ---help--- Enable support for MRF24J40 BEE on mikroBUS2 +config CLICKER2_STM32_MRF24J40LH_VERBOSE + bool "Verbose MRF24J40 lowerhalf" + default n + depends on DEBUG_WIRELESS_INFO + ---help--- + Enable verbose syslog for MRF24J40 lowerhalf + endif # ARCH_BOARD_CLICKER2_STM32 diff --git a/configs/clicker2-stm32/src/stm32_mrf24j40.c b/configs/clicker2-stm32/src/stm32_mrf24j40.c index d523fd257b..04737b9941 100644 --- a/configs/clicker2-stm32/src/stm32_mrf24j40.c +++ b/configs/clicker2-stm32/src/stm32_mrf24j40.c @@ -193,9 +193,12 @@ static void stm32_enable_irq(FAR const struct mrf24j40_lower_s *lower, DEBUGASSERT(priv != NULL && (priv->handler != NULL || !state)); +#ifdef CONFIG_CLICKER2_STM32_MRF24J40LH_VERBOSE + wlinfo("state:%d\n", (int)state); +#endif + /* Attach and enable, or detach and disable */ - wlinfo("state:%d\n", (int)state); if (state) { (void)stm32_gpiosetevent(priv->intcfg, true, true, true, diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c index 5098e96253..a6780c1fa7 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c @@ -2381,7 +2381,10 @@ static void mrf24j40_irqworker(FAR void *arg) if ((intstat & MRF24J40_INTSTAT_WAKEIF)) { +#ifdef CONFIG_MAC802154_SFEVENT_VERBOSE wlinfo("Wake Interrupt\n"); +#endif + /* This is right before the beacon, we set the bsn here, since the MAC * uses the SLPIF (end of active portion of superframe). to make any * changes to the beacon. This assumes that any changes to the beacon diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index f01ae562d7..11e47bed07 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -83,6 +83,20 @@ config MAC802154_NPANDESC information for all unique beacons received. This is the number of unique descriptors that can be held before the scan cancels with LIMIT_REACHED. +config MAC802154_SFEVENT_VERBOSE + bool "Verbose logging related to superframe events" + default n + depends on DEBUG_WIRELESS_INFO + ---help--- + Enable verbose logging of superframe events Default: false + +config MAC802154_LOCK_VERBOSE + bool "Verbose logging related to MAC lock management" + default n + depends on DEBUG_WIRELESS_INFO + ---help--- + Enable verbose logging of MAC lock management. Default: false + config IEEE802154_IND_PREALLOC int "Number of pre-allocated meta-data structures" default 20 diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index cf7ebba212..d8a4fddc23 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -1527,7 +1527,9 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb, { case IEEE802154_SFEVENT_ENDOFACTIVE: { +#ifdef CONFIG_MAC802154_SFEVENT_VERBOSE wlinfo("End of superframe\n"); +#endif /* Check if there is any reason to update the beacon */ diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index 6fcfaaeb8e..fd1fd77568 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -581,9 +581,14 @@ static inline int mac802154_takesem(sem_t *sem, bool allowinterrupt) return OK; } +#ifdef CONFIG_MAC802154_LOCK_VERBOSE #define mac802154_unlock(dev) \ mac802154_givesem(&dev->exclsem); \ wlinfo("MAC unlocked\n"); +#else +#define mac802154_unlock(dev) \ + mac802154_givesem(&dev->exclsem); +#endif #define mac802154_lock(dev, allowinterrupt) \ mac802154_lockpriv(dev, allowinterrupt, __FUNCTION__) @@ -593,15 +598,19 @@ static inline int mac802154_lockpriv(FAR struct ieee802154_privmac_s *dev, { int ret; +#ifdef CONFIG_MAC802154_LOCK_VERBOSE wlinfo("Locking MAC: %s\n", funcname); +#endif ret = mac802154_takesem(&dev->exclsem, allowinterrupt); if (ret < 0) { - wlinfo("Failed to lock MAC\n"); + wlwarn("Failed to lock MAC\n"); } else { +#ifdef CONFIG_MAC802154_LOCK_VERBOSE wlinfo("MAC locked\n"); +#endif } return ret; From 0aabea26621fbd6eb4eeeed713ef761057220e57 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 01:19:13 -0400 Subject: [PATCH 04/11] drivers/wireless/ieee802154/mrf24j40: Fixes odd extra spacing that mysteriously got introduced --- .../wireless/ieee802154/mrf24j40/mrf24j40.c | 238 ------------------ 1 file changed, 238 deletions(-) diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c index a6780c1fa7..665cd1da19 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c @@ -1452,485 +1452,247 @@ static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, case -1: reg |= 0x02; - break; - - case 0: - reg |= 0x00; /* value 0x01 is 0.5 db, not used */ - break; - - default: return -EINVAL; - } - - mrf24j40_setreg(dev->spi, MRF24J40_RFCON3, reg); dev->txpower = save_txpwr; return OK; - } - - /**************************************************************************** - * Name: mrf24j40_setcca - * - * Description: - * Define the Clear Channel Assessement method. - * - ****************************************************************************/ - - static int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, - FAR struct ieee802154_cca_s *cca) - { - uint8_t mode; - - if (!cca->use_ed && !cca->use_cs) - { - return -EINVAL; - } - - if (cca->use_cs && cca->csth > 0x0f) - { - return -EINVAL; - } - - mode = mrf24j40_getreg(dev->spi, MRF24J40_BBREG2); - mode &= 0x03; - - if (cca->use_ed) - { - mode |= MRF24J40_BBREG2_CCAMODE_ED; - mrf24j40_setreg(dev->spi, MRF24J40_CCAEDTH, cca->edth); - } - - if (cca->use_cs) - { - mode |= MRF24J40_BBREG2_CCAMODE_CS; - mode |= cca->csth << 2; - } - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG2, mode); - - memcpy(&dev->cca, cca, sizeof(struct ieee802154_cca_s)); - return OK; - } - - /**************************************************************************** - * Name: mrf24j40_regdump - * - * Description: - * Display the value of all registers. - * - ****************************************************************************/ - - static int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev) - { - uint32_t i; - char buf[4+16*3+2+1]; - int len = 0; - - wlinfo("Short regs:\n"); - - for (i = 0; i < 0x40; i++) - { - if ((i & 15) == 0) - { - len=sprintf(buf, "%02x: ",i&0xFF); - } - - len += sprintf(buf+len, "%02x ", mrf24j40_getreg(dev->spi, i)); - if ((i & 15) == 15) - { - sprintf(buf+len, "\n"); - wlinfo("%s", buf); - } - } - - wlinfo("Long regs:\n"); for (i = 0x80000200; i < 0x80000250; i++) - { - if ((i & 15) == 0) - { - len=sprintf(buf, "%02x: ",i&0xFF); - } - - len += sprintf(buf+len, "%02x ", mrf24j40_getreg(dev->spi, i)); - if ((i & 15) == 15) - { - sprintf(buf+len, "\n"); - wlinfo("%s", buf); - } - } - - return 0; - } - - /**************************************************************************** - * Name: mrf24j40_energydetect - * - * Description: - * Measure the RSSI level for the current channel. - * - ****************************************************************************/ - - static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, - FAR uint8_t *energy) - { - uint8_t reg; - - /* Manually enable the LNA*/ - - mrf24j40_pacontrol(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); - - /* 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. - */ - - while(!(mrf24j40_getreg(dev->spi, MRF24J40_BBREG6) & 0x01)); - - /* 3. Read RSSI 0x210<7:0> – The RSSI register contains the averaged RSSI - * received power level for 8 symbol periods. - */ - - *energy = mrf24j40_getreg(dev->spi, MRF24J40_RSSI); - - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG6, 0x40); - - /* Back to automatic control */ - - mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); return OK; - } - - /**************************************************************************** - * Name: mrf24j40_norm_setup - * - * Description: - * Setup a transaction in the normal TX FIFO - * - ****************************************************************************/ - - static void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, - FAR struct iob_s *frame, bool csma) - { - uint8_t reg; - - /* Enable tx int */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg &= ~MRF24J40_INTCON_TXNIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - - /* Enable/Disable CSMA mode */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); - - if (csma) - { - reg &= ~MRF24J40_TXMCR_NOCSMA; - } - else - { - reg |= MRF24J40_TXMCR_NOCSMA; - } - - mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); - - /* Setup the FIFO */ - - mrf24j40_setup_fifo(dev, frame->io_data, frame->io_len, MRF24J40_TXNORM_FIFO); - - /* If the frame control field contains an acknowledgment request, set the - * TXNACKREQ bit. See IEEE 802.15.4/2003 7.2.1.1 page 112 for info. - */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXNCON); - - if (frame->io_data[0] & IEEE802154_FRAMECTRL_ACKREQ) - { - reg |= MRF24J40_TXNCON_TXNACKREQ; - } - else - { - reg &= ~MRF24J40_TXNCON_TXNACKREQ; - } - - mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg); - } - - /**************************************************************************** - * Name: mrf24j40_norm_trigger - * - * Description: - * Trigger the normal TX FIFO - * - ****************************************************************************/ - - static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev) - { - uint8_t reg; - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXNCON); - - - reg |= MRF24J40_TXNCON_TXNTRIG; - - - mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg); - } - - /**************************************************************************** - * Name: mrf24j40_beacon_trigger - * - * Description: - * Trigger the beacon TX FIFO - * - ****************************************************************************/ - - static inline void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev) { uint8_t reg; From deeb52cedc1d624174a8e9693ad1122e84b1257a Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 01:51:15 -0400 Subject: [PATCH 05/11] drivers/wireless/ieee802154/mrf24j40: Minor timing fix. Matches recommended value in datasheet --- drivers/wireless/ieee802154/mrf24j40/mrf24j40.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c index 665cd1da19..3e66d9f4cf 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c @@ -473,11 +473,16 @@ static int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK); - /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0x5F to set the main oscillator + /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0xC8 to set the main oscillator * (20 MHz) start-up timer value. */ - mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0x5F); + mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0xC8); + + /* Set WAKETIME to recommended value for 100kHz SLPCLK Source */ + + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2); + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00); /* Enable the SLPIF and WAKEIF flags */ From 4b7d743f32a728bd78116735103dafe07bbe1741 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 01:51:39 -0400 Subject: [PATCH 06/11] configs/clicker2-stm32: Adds support for per-function-call stack checking --- configs/clicker2-stm32/mrf24j40-mac/Make.defs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/configs/clicker2-stm32/mrf24j40-mac/Make.defs b/configs/clicker2-stm32/mrf24j40-mac/Make.defs index ab1e10dc45..da798a6481 100644 --- a/configs/clicker2-stm32/mrf24j40-mac/Make.defs +++ b/configs/clicker2-stm32/mrf24j40-mac/Make.defs @@ -75,6 +75,11 @@ ifneq ($(CONFIG_DEBUG_NOOPT),y) ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer endif +# enable precise stack overflow tracking +ifeq ($(CONFIG_ARMV7M_STACKCHECK),y) +INSTRUMENTATIONDEFINES = -finstrument-functions -ffixed-r10 +endif + ARCHCFLAGS = -fno-builtin ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef @@ -82,9 +87,9 @@ ARCHWARNINGSXX = -Wall -Wshadow -Wundef ARCHDEFINES = ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 -CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) $(INSTRUMENTATIONDEFINES) -pipe CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) -CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) $(INSTRUMENTATIONDEFINES) -pipe CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) AFLAGS = $(CFLAGS) -D__ASSEMBLY__ From 28d1db02b8ffe6169db484c1acd2f08173cd4c17 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 03:10:20 -0400 Subject: [PATCH 07/11] drivers/wireless/ieee802154/mrf24j40: Splits up driver into multiple files to make it easier to navigate --- .../wireless/ieee802154/mrf24j40/Make.defs | 3 +- .../wireless/ieee802154/mrf24j40/mrf24j40.c | 1639 +---------------- .../wireless/ieee802154/mrf24j40/mrf24j40.h | 356 ++-- .../ieee802154/mrf24j40/mrf24j40_getset.c | 425 +++++ .../ieee802154/mrf24j40/mrf24j40_getset.h | 64 + .../ieee802154/mrf24j40/mrf24j40_interrupt.c | 439 +++++ .../ieee802154/mrf24j40/mrf24j40_radif.c | 530 ++++++ .../ieee802154/mrf24j40/mrf24j40_radif.h | 71 + .../ieee802154/mrf24j40/mrf24j40_reg.h | 286 +++ .../ieee802154/mrf24j40/mrf24j40_regops.c | 189 ++ .../ieee802154/mrf24j40/mrf24j40_regops.h | 47 + 11 files changed, 2226 insertions(+), 1823 deletions(-) create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_reg.h create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.c create mode 100644 drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.h diff --git a/drivers/wireless/ieee802154/mrf24j40/Make.defs b/drivers/wireless/ieee802154/mrf24j40/Make.defs index f6871f6ce5..446f7ef293 100644 --- a/drivers/wireless/ieee802154/mrf24j40/Make.defs +++ b/drivers/wireless/ieee802154/mrf24j40/Make.defs @@ -37,7 +37,8 @@ ifeq ($(CONFIG_IEEE802154_MRF24J40),y) # Include MRF24J40 files into the build -CSRCS += mrf24j40.c +CSRCS += mrf24j40_getset.c mrf24j40_interrupt.c mrf24j40_radif.c +CSRCS += mrf24j40_regops.c mrf24j40.c # Include MRF24J40 build support diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c index 3e66d9f4cf..9dd7e7ddc1 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c @@ -54,8 +54,6 @@ #include #include #include -#include -#include #include @@ -64,45 +62,14 @@ #include #include "mrf24j40.h" +#include "mrf24j40_reg.h" +#include "mrf24j40_radif.h" +#include "mrf24j40_regops.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#ifndef CONFIG_SCHED_HPWORK -# error High priority work queue required in this driver -#endif - -#ifndef CONFIG_IEEE802154_MRF24J40_SPIMODE -# define CONFIG_IEEE802154_MRF24J40_SPIMODE SPIDEV_MODE0 -#endif - -#ifndef CONFIG_IEEE802154_MRF24J40_FREQUENCY -# define CONFIG_IEEE802154_MRF24J40_FREQUENCY 8000000 -#endif - -#ifndef CONFIG_SPI_EXCHANGE -# error CONFIG_SPI_EXCHANGE required for this driver -#endif - -/* Definitions for the device structure */ - -#define MRF24J40_RXMODE_NORMAL 0 -#define MRF24J40_RXMODE_PROMISC 1 -#define MRF24J40_RXMODE_NOCRC 2 - -#define MRF24J40_MODE_DEVICE 0 -#define MRF24J40_MODE_COORD 1 -#define MRF24J40_MODE_PANCOORD 2 - -/* Definitions for PA control on high power modules */ - -#define MRF24J40_PA_AUTO 1 -#define MRF24J40_PA_ED 2 -#define MRF24J40_PA_SLEEP 3 - -#define MRF24J40_GTS_SLOTS 2 - /* Clock configuration macros */ #define MRF24J40_SLPCLKPER_100KHZ ((1000 * 1000 * 1000)/100000) /* 10ns */ @@ -121,634 +88,11 @@ ((MRF24J40_BEACONINTERVAL_NSEC(bo) - MRF24J40_REMCNT_NSEC) / \ clkper) -/* Formula for calculating default macMaxFrameWaitTime is on pg. 130 - * - * For PHYs other than CSS and UWB, the attribute phyMaxFrameDuration is given by: - * - * phyMaxFrameDuration = phySHRDuration + - * ceiling([aMaxPHYPacketSize + 1] x phySymbolsPerOctet) - * - * where ceiling() is a function that returns the smallest integer value greater - * than or equal to its argument value. [1] pg. 158 -*/ - -#define MRF24J40_DEFAULT_MAX_FRAME_WAITTIME 1824 - -#define MRF24J40_SYMBOL_DURATION_PS 16000000 - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* A MRF24J40 device instance */ - -struct mrf24j40_radio_s -{ - struct ieee802154_radio_s radio; /* The public device instance */ - FAR struct ieee802154_radiocb_s *radiocb; /* Registered callbacks */ - - /* Low-level MCU-specific support */ - - FAR const struct mrf24j40_lower_s *lower; - FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ - - 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 */ - - sem_t exclsem; /* Exclusive access to this struct */ - - /* MAC Attributes */ - - struct ieee802154_addr_s addr; - - uint8_t chan; /* 11 to 26 for the 2.4 GHz band */ - uint8_t devmode; /* device mode: device, coord, pancoord */ - uint8_t paenabled; /* enable usage of PA */ - uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ - int32_t txpower; /* TX power in mBm = dBm/100 */ - struct ieee802154_cca_s cca; /* Clear channel assessement method */ - - /* MAC PIB attributes */ - - uint32_t max_frame_waittime; - - struct ieee802154_txdesc_s *txdelayed_desc; - struct ieee802154_txdesc_s *csma_desc; - bool txdelayed_busy : 1; - bool csma_busy : 1; - bool reschedule_csma : 1; - - bool rxenabled : 1; - - uint8_t bsn; - - struct ieee802154_txdesc_s *gts_desc[MRF24J40_GTS_SLOTS]; - bool gts_busy[MRF24J40_GTS_SLOTS]; -}; - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/* Internal operations */ - -static void mrf24j40_spi_lock(FAR struct spi_dev_s *spi); - -static void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr, - uint8_t val); -static uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr); - -static int mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev); -static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, - uint8_t so); -static int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode); - -static int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode); -static int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev); - -static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev); -static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev); -static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, - uint8_t gts_num); - -static void mrf24j40_irqworker(FAR void *arg); -static int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg); - -static void mrf24j40_dopoll_csma(FAR void *arg); -static void mrf24j40_dopoll_gts(FAR void *arg); - -static void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, - FAR struct iob_s *frame, bool csma); -static void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, - FAR struct iob_s *frame); -static void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *buf, uint8_t length, uint32_t fifo_addr); - -static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev); -static inline void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev); - -static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, - uint8_t chan); -static int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *panid); -static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *saddr); -static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *eaddr); -static int mrf24j40_setcoordsaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *saddr); -static int mrf24j40_setcoordeaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *eaddr); -static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev, - uint8_t mode); -static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, - int32_t txpwr); -static int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, - FAR struct ieee802154_cca_s *cca); -static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, - FAR uint8_t *energy); -static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols); - -/* Driver operations */ - -static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_radiocb_s *radiocb); -static int mrf24j40_reset(FAR struct ieee802154_radio_s *radio); -static int mrf24j40_getattr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_attr_e attr, - FAR union ieee802154_attr_u *attrval); -static int mrf24j40_setattr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_attr_e attr, - FAR const union ieee802154_attr_u *attrval); -static int mrf24j40_txnotify(FAR struct ieee802154_radio_s *radio, bool gts); -static int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_txdesc_s *txdesc, - uint32_t symboldelay); -static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *dev, bool enable); -static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio, - FAR const struct ieee802154_superframespec_s *sfspec, - FAR struct ieee802154_beaconframe_s *beacon); -static int mrf24j40_beaconupdate(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_beaconframe_s *beacon); -static int mrf24j40_beaconstop(FAR struct ieee802154_radio_s *radio); -static int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio, - FAR const struct ieee802154_superframespec_s *sfspec); - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static const uint8_t g_allones[8] = -{ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/**************************************************************************** - * Radio Interface Functions - ****************************************************************************/ - -static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_radiocb_s *radiocb) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - - DEBUGASSERT(dev != NULL); - dev->radiocb = radiocb; - return OK; -} - -/**************************************************************************** - * Function: mrf24j40_txnotify - * - * Description: - * Driver callback invoked when new TX data is available. This is a - * stimulus perform an out-of-cycle poll and, thereby, reduce the TX - * latency. - * - * Parameters: - * radio - Reference to the radio driver state structure - * - * Returned Value: - * None - * - * Assumptions: - * - ****************************************************************************/ - -static int mrf24j40_txnotify(FAR struct ieee802154_radio_s *radio, bool gts) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - - if (gts) - { - /* Is our single work structure available? It may not be if there are - * pending interrupt actions and we will have to ignore the Tx - * availability action. - */ - - if (work_available(&dev->gts_pollwork)) - { - /* Schedule to serialize the poll on the worker thread. */ - - work_queue(HPWORK, &dev->gts_pollwork, mrf24j40_dopoll_gts, dev, 0); - } - } - else - { - /* Is our single work structure available? It may not be if there are - * pending interrupt actions and we will have to ignore the Tx - * availability action. - */ - - if (work_available(&dev->csma_pollwork)) - { - /* Schedule to serialize the poll on the worker thread. */ - - work_queue(HPWORK, &dev->csma_pollwork, mrf24j40_dopoll_csma, dev, 0); - } - } - - return OK; -} - -/**************************************************************************** - * Function: mrf24j40_txdelayed - * - * Description: - * Transmit a packet without regard to supeframe structure after a certain - * number of symbols. This function is used to send Data Request responses. - * It can also be used to send data immediately if the delay is set to 0. - * - * Parameters: - * radio - Reference to the radio driver state structure - * - * Returned Value: - * None - * - * Assumptions: - * - ****************************************************************************/ - -static int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_txdesc_s *txdesc, - uint32_t symboldelay) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - uint8_t reg; - - /* Get exclusive access to the radio device */ - - if (sem_wait(&dev->exclsem) != 0) - { - return -EINTR; - } - - /* There should never be more than one of these transactions at once. */ - - DEBUGASSERT(!dev->txdelayed_busy); - - dev->txdelayed_desc = txdesc; - dev->txdelayed_busy = true; - - /* Disable the TX norm interrupt and clear it */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg |= MRF24J40_INTCON_TXNIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - - /* If after disabling the interrupt, the irqworker is not scheduled, there - * are no interrupts to worry about. However, if there is work scheduled, - * we need to process it before going any further. - */ - - if (!work_available(&dev->irqwork)) - { - work_cancel(HPWORK, &dev->irqwork); - sem_post(&dev->exclsem); - mrf24j40_irqworker((FAR void *)dev); - - /* Get exclusive access to the radio device */ - - if (sem_wait(&dev->exclsem) != 0) - { - return -EINTR; - } - } - - if (dev->csma_busy) - { - dev->reschedule_csma = true; - } - - mrf24j40_norm_setup(dev, txdesc->frame, false); - - if (symboldelay == 0) - { - mrf24j40_norm_trigger(dev); - } - else - { - mrf24j40_mactimer(dev, symboldelay); - } - - sem_post(&dev->exclsem); - - return OK; -} - -static int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - struct ieee802154_cca_s cca; - int reg; - - /* Software reset */ - - mrf24j40_setreg(dev->spi, MRF24J40_SOFTRST , 0x07); /* 00000111 Reset */ - while(mrf24j40_getreg(dev->spi, MRF24J40_SOFTRST) & 0x07); - - /* Apply recommended settings */ - - mrf24j40_setreg(dev->spi, MRF24J40_PACON2 , 0x98); /* 10011000 Enable FIFO (default), TXONTS=6 (recommended), TXONT<8:7>=0 */ - mrf24j40_setreg(dev->spi, MRF24J40_TXSTBL , 0x95); /* 10010101 set the SIFS period. RFSTBL=9, MSIFS=5, aMinSIFSPeriod=14 (min 12) */ - mrf24j40_setreg(dev->spi, MRF24J40_TXPEND , 0x7C); /* 01111100 set the LIFS period, MLIFS=1Fh=31 aMinLIFSPeriod=40 (min 40) */ - mrf24j40_setreg(dev->spi, MRF24J40_TXTIME , 0x30); /* 00110000 set the turnaround time, TURNTIME=3 aTurnAroundTime=12 */ - mrf24j40_setreg(dev->spi, MRF24J40_RFCON1 , 0x02); /* 00000010 VCO optimization, recommended value */ - mrf24j40_setreg(dev->spi, MRF24J40_RFCON2 , 0x80); /* 10000000 Enable PLL */ - mrf24j40_setreg(dev->spi, MRF24J40_RFCON6 , 0x90); /* 10010000 TX filter enable, fast 20M recovery, No bat monitor*/ - mrf24j40_setreg(dev->spi, MRF24J40_RFCON7 , 0x80); /* 10000000 Sleep clock on internal 100 kHz */ - mrf24j40_setreg(dev->spi, MRF24J40_RFCON8 , 0x10); /* 00010000 VCO control bit, as recommended */ - mrf24j40_setreg(dev->spi, MRF24J40_SLPCON1, 0x01); /* 00000001 no CLKOUT, default divisor */ - mrf24j40_setreg(dev->spi, MRF24J40_BBREG6 , 0x40); /* 01000000 Append RSSI to rx packets */ - - /* Set this in reset since it can exist for all device modes. See pg 101 */ - - mrf24j40_setreg(dev->spi, MRF24J40_FRMOFFSET, 0x15); - - /* For now, we want to always just have the frame pending bit set when - * acknowledging a Data Request command. The standard says that the coordinator - * can do this if it needs time to figure out whether it has data or not - */ - - mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK); - - /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0xC8 to set the main oscillator - * (20 MHz) start-up timer value. - */ - - mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0xC8); - - /* Set WAKETIME to recommended value for 100kHz SLPCLK Source */ - - mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2); - mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00); - - /* Enable the SLPIF and WAKEIF flags */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg &= ~(MRF24J40_INTCON_SLPIE | MRF24J40_INTCON_WAKEIE); - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - - dev->rxenabled = false; - - mrf24j40_setchannel(dev, 11); - mrf24j40_setpanid(dev, g_allones); - mrf24j40_setsaddr(dev, g_allones); - mrf24j40_seteaddr(dev, g_allones); - - dev->max_frame_waittime = MRF24J40_DEFAULT_MAX_FRAME_WAITTIME; - dev->bsn = 0; - - /* Default device params */ - - cca.use_ed = 1; - cca.use_cs = 0; - cca.edth = 0x60; /* CCA mode ED, no carrier sense, recommenced ED threshold -69 dBm */ - mrf24j40_setcca(dev, &cca); - - mrf24j40_setrxmode(dev, MRF24J40_RXMODE_NORMAL); - - mrf24j40_settxpower(dev, 0); /*16. Set transmitter power .*/ - - mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - - return OK; -} - -static int mrf24j40_getattr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_attr_e attr, - FAR union ieee802154_attr_u *attrval) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - int ret; - - switch (attr) - { - case IEEE802154_ATTR_MAC_EADDR: - { - memcpy(&attrval->mac.eaddr[0], &dev->addr.eaddr[0], 8); - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME: - { - attrval->mac.max_frame_waittime = dev->max_frame_waittime; - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_PHY_SYMBOL_DURATION: - { - attrval->phy.symdur_picosec = MRF24J40_SYMBOL_DURATION_PS; - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_PHY_CHAN: - { - attrval->phy.chan = dev->chan; - ret = IEEE802154_STATUS_SUCCESS; - } - - default: - ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; - } - - return ret; -} - -static int mrf24j40_setattr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_attr_e attr, - FAR const union ieee802154_attr_u *attrval) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - int ret; - - switch (attr) - { - case IEEE802154_ATTR_MAC_PANID: - { - mrf24j40_setpanid(dev, attrval->mac.panid); - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_MAC_SADDR: - { - mrf24j40_setsaddr(dev, attrval->mac.saddr); - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_MAC_EADDR: - { - mrf24j40_seteaddr(dev, attrval->mac.eaddr); - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_MAC_COORD_SADDR: - { - mrf24j40_setcoordsaddr(dev, attrval->mac.coordsaddr); - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_MAC_COORD_EADDR: - { - mrf24j40_setcoordeaddr(dev, attrval->mac.coordeaddr); - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - case IEEE802154_ATTR_MAC_PROMISCUOUS_MODE: - { - if (attrval->mac.promisc_mode) - { - mrf24j40_setrxmode(dev, MRF24J40_RXMODE_PROMISC); - } - else - { - mrf24j40_setrxmode(dev, MRF24J40_RXMODE_NORMAL); - } - - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - - case IEEE802154_ATTR_PHY_CHAN: - { - mrf24j40_setchannel(dev, attrval->phy.chan); - ret = IEEE802154_STATUS_SUCCESS; - } - break; - - default: - ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; - break; - } - return ret; -} - -static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio, - FAR const struct ieee802154_superframespec_s *sfspec, - FAR struct ieee802154_beaconframe_s *beacon) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - int reg; - - if (sfspec->pancoord) - { - /* Set the PANCOORD (RXMCR 0x00<3>) bit = 1to configure as PAN coordinator */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR); - reg |= MRF24J40_RXMCR_PANCOORD; - mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg); - - /* Set the SLOTTED (TXMCR 0x11<5>) bit = 1 to use Slotted CSMA-CA mode */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); - reg |= MRF24J40_TXMCR_SLOTTED; - mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); - - /* Load the beacon frame into the TXBFIFO (0x080-0x0FF). */ - - mrf24j40_setup_fifo(dev, beacon->bf_data, beacon->bf_len, MRF24J40_BEACON_FIFO); - - /* The radio layer is responsible for setting the BSN. */ - - dev->bsn = 0; - mrf24j40_setreg(dev->spi, MRF24J40_BEACON_FIFO + 4, dev->bsn++); - - /* Set the TXBMSK (TXBCON1 0x25<7>) bit = 1 to mask the beacon interrupt - * mask - */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1); - reg |= MRF24J40_TXBCON1_TXBMSK; - mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg); - - /* Set INTL (WAKECON 0x22<5:0>) value to 0x03. */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_WAKECON); - reg &= ~MRF24J40_WAKECON_INTL; - reg |= 0x03 & MRF24J40_WAKECON_INTL; - mrf24j40_setreg(dev->spi, MRF24J40_WAKECON, reg); - - /* Program the CAP end slot (ESLOTG1 0x13<3:0>) value. */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_ESLOTG1); - reg &= ~MRF24J40_ESLOTG1_CAP; - reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP; - mrf24j40_setreg(dev->spi, MRF24J40_ESLOTG1, reg); - - /* TODO: Add GTS related code. See pg 100 of datasheet */ - - mrf24j40_setorder(dev, sfspec->beaconorder, sfspec->sforder); - } - else - { - return -ENOTTY; - } - - return OK; -} - -static int mrf24j40_beaconupdate(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_beaconframe_s *beacon) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - - mrf24j40_setup_fifo(dev, beacon->bf_data, beacon->bf_len, MRF24J40_BEACON_FIFO); - mrf24j40_beacon_trigger(dev); - - return OK; -} - -static int mrf24j40_beaconstop(FAR struct ieee802154_radio_s *radio) -{ - return -ENOTTY; -} - -static int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio, - FAR const struct ieee802154_superframespec_s *sfspec) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - int reg; - - /* If we are operating on a beacon-enabled network, use slotted CSMA */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); - if (sfspec->beaconorder < 15) - { - reg |= MRF24J40_TXMCR_SLOTTED; - } - else - { - reg &= ~MRF24J40_TXMCR_SLOTTED; - } - mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); - - mrf24j40_setorder(dev, sfspec->beaconorder, sfspec->sforder); - - /* Program the CAP end slot (ESLOTG1 0x13<3:0>) value. */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_ESLOTG1); - reg &= ~MRF24J40_ESLOTG1_CAP; - reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP; - mrf24j40_setreg(dev->spi, MRF24J40_ESLOTG1, reg); - - return OK; -} - /**************************************************************************** * Internal Functions ****************************************************************************/ -static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols) +void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols) { uint16_t nhalfsym; uint8_t reg; @@ -798,7 +142,7 @@ static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols) * ****************************************************************************/ -static void mrf24j40_dopoll_csma(FAR void *arg) +void mrf24j40_dopoll_csma(FAR void *arg) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; int len = 0; @@ -854,7 +198,7 @@ static void mrf24j40_dopoll_csma(FAR void *arg) * ****************************************************************************/ -static void mrf24j40_dopoll_gts(FAR void *arg) +void mrf24j40_dopoll_gts(FAR void *arg) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; int gts = 0; @@ -886,147 +230,6 @@ static void mrf24j40_dopoll_gts(FAR void *arg) sem_post(&dev->exclsem); } -/**************************************************************************** - * Name: mrf24j40_spi_lock - * - * Description: - * Acquire exclusive access to the shared SPI bus. - * - ****************************************************************************/ - -static void mrf24j40_spi_lock(FAR struct spi_dev_s *spi) -{ - SPI_LOCK(spi, 1); - SPI_SETBITS(spi, 8); - SPI_SETMODE(spi, CONFIG_IEEE802154_MRF24J40_SPIMODE); - SPI_SETFREQUENCY(spi, CONFIG_IEEE802154_MRF24J40_FREQUENCY); -} - -/**************************************************************************** - * Name: mrf24j40_spi_unlock - * - * Description: - * Release exclusive access to the shared SPI bus. - * - ****************************************************************************/ - -static inline void mrf24j40_spi_unlock(FAR struct spi_dev_s *spi) -{ - SPI_LOCK(spi,0); -} - -/**************************************************************************** - * Name: mrf24j40_setreg - * - * Description: - * Define the value of an MRF24J40 device register - * - ****************************************************************************/ - -static void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr, - uint8_t val) -{ - uint8_t buf[3]; - int len; - - if (!(addr&0x80000000)) - { - addr &= 0x3F; /* 6-bit address */ - addr <<= 1; - addr |= 0x01; /* writing */ - buf[0] = addr; - len = 1; - } - else - { - addr &= 0x3FF; /* 10-bit address */ - addr <<= 5; - addr |= 0x8010; /* writing long */ - buf[0] = (addr >> 8); - buf[1] = (addr & 0xFF); - len = 2; - } - - buf[len++] = val; - - mrf24j40_spi_lock(spi); - SPI_SELECT(spi, SPIDEV_IEEE802154(0), true); - SPI_SNDBLOCK(spi, buf, len); - SPI_SELECT(spi, SPIDEV_IEEE802154(0), false); - mrf24j40_spi_unlock(spi); -} - -/**************************************************************************** - * Name: mrf24j40_getreg - * - * Description: - * Return the value of an MRF24J40 device register* - * - ****************************************************************************/ - -static uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr) -{ - uint8_t buf[3]; - uint8_t rx[3]; - int len; - - if (!(addr&0x80000000)) - { - /* 6-bit address */ - - addr &= 0x3F; - addr <<= 1; - buf[0] = addr; - len = 1; - } - else - { - /* 10-bit address */ - - addr &= 0x3FF; - addr <<= 5; - addr |= 0x8000; - buf[0] = (addr >> 8); - buf[1] = (addr & 0xFF); - len = 2; - } - - buf[len++] = 0xFF; /* dummy */ - - mrf24j40_spi_lock (spi); - SPI_SELECT (spi, SPIDEV_IEEE802154(0), true); - SPI_EXCHANGE (spi, buf, rx, len); - SPI_SELECT (spi, SPIDEV_IEEE802154(0), false); - mrf24j40_spi_unlock(spi); - - /* wlinfo("r[%04X]=%02X\n", addr, rx[len - 1]); */ - return rx[len - 1]; -} - -/**************************************************************************** - * Name: mrf24j40_resetrfsm - * - * Description: - * Reset the RF state machine. Required at boot, after channel change, - * and probably after PA settings. - * - ****************************************************************************/ - -static int mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev) -{ - uint8_t reg; - - reg = mrf24j40_getreg(dev->spi, MRF24J40_RFCTL); - reg |= 0x04; - mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); - - reg &= ~0x04; - mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); - up_udelay(200); - - return OK; -} - /**************************************************************************** * Name: mrf24j40_setorder * @@ -1034,8 +237,7 @@ static int mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev) * Configures the timers and sets the ORDER register ****************************************************************************/ -static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, - uint8_t so) +void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, uint8_t so) { uint32_t maincnt = 0; uint32_t slpcal = 0; @@ -1109,7 +311,7 @@ static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, * GPIO 3: PA power enable (not required on MB) ****************************************************************************/ -static int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode) +int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode) { if (!dev->paenabled) { @@ -1143,433 +345,6 @@ static int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode) return OK; } -/**************************************************************************** - * Name: mrf24j40_setrxmode - * - * Description: - * Set the RX mode (normal, promiscuous, no CRC) - * - ****************************************************************************/ - -static int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode) -{ - uint8_t reg; - - if (mode < MRF24J40_RXMODE_NORMAL || mode > MRF24J40_RXMODE_NOCRC) - { - return -EINVAL; - } - - reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR); - reg &= ~0x03; - reg |= mode; - - /* Set mode options */ - - if (mode != MRF24J40_RXMODE_NORMAL) - { - /* Promisc and error modes: Disable auto ACK */ - - reg |= MRF24J40_RXMCR_NOACKRSP; - } - else - { - /* Normal mode : enable auto-ACK */ - - reg &= ~MRF24J40_RXMCR_NOACKRSP; - } - - mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg); - - dev->rxmode = mode; - wlinfo("%u\n", (unsigned)mode); - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_setchannel - * - * Description: - * Define the current radio channel the device is operating on. - * In the 2.4 GHz, there are 16 channels, each 2 MHz wide, 5 MHz spacing: - * Chan MHz Chan MHz Chan MHz Chan MHz - * 11 2405 15 2425 19 2445 23 2465 - * 12 2410 16 2430 20 2450 24 2470 - * 13 2415 17 2435 21 2455 25 2475 - * 14 2420 18 2440 22 2460 26 2480 - * - ****************************************************************************/ - -static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, uint8_t chan) -{ - if (chan < 11 || chan > 26) - { - wlerr("ERROR: Invalid chan: %d\n",chan); - return -EINVAL; - } - - /* 15. Set channel – See Section 3.4 “Channel Selection”. */ - - mrf24j40_setreg(dev->spi, MRF24J40_RFCON0, (chan - 11) << 4 | 0x03); - - /* 17. RFCTL (0x36) = 0x04 – Reset RF state machine. - * 18. RFCTL (0x36) = 0x00. - */ - - mrf24j40_resetrfsm(dev); - - dev->chan = chan; - wlinfo("%u\n", (unsigned)chan); - - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_setpanid - * - * Description: - * Define the PAN ID the device is operating on. - * - ****************************************************************************/ - -static int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *panid) -{ - mrf24j40_setreg(dev->spi, MRF24J40_PANIDL, panid[0]); - mrf24j40_setreg(dev->spi, MRF24J40_PANIDH, panid[1]); - - IEEE802154_PANIDCOPY(dev->addr.panid, panid); - wlinfo("%02X:%02X\n", panid[0], panid[1]); - - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_setsaddr - * - * Description: - * Define the device short address. The following addresses are special: - * FFFEh : Broadcast - * FFFFh : Unspecified - * - ****************************************************************************/ - -static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *saddr) -{ - mrf24j40_setreg(dev->spi, MRF24J40_SADRL, saddr[0]); - mrf24j40_setreg(dev->spi, MRF24J40_SADRH, saddr[1]); - - IEEE802154_SADDRCOPY(dev->addr.saddr, saddr); - - wlinfo("%02X:%02X\n", saddr[0], saddr[1]); - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_seteaddr - * - * Description: - * Define the device extended address. The following addresses are special: - * FFFFFFFFFFFFFFFFh : Unspecified - * - ****************************************************************************/ - -static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *eaddr) -{ - int i; - - for (i = 0; i < 8; i++) - { - mrf24j40_setreg(dev->spi, MRF24J40_EADR0 + i, eaddr[i]); - dev->addr.eaddr[i] = eaddr[i]; - } - wlinfo("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", eaddr[0], eaddr[1], - eaddr[2], eaddr[3], eaddr[4], eaddr[5], eaddr[6], eaddr[7]); - - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_setcoordsaddr - * - * Description: - * Define the coordinator short address. The following addresses are special: - * FFFEh : Broadcast - * FFFFh : Unspecified - * - ****************************************************************************/ - -static int mrf24j40_setcoordsaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *saddr) -{ - mrf24j40_setreg(dev->spi, MRF24J40_ASSOSADR0, saddr[0]); - mrf24j40_setreg(dev->spi, MRF24J40_ASSOSADR1, saddr[1]); - - IEEE802154_SADDRCOPY(dev->addr.saddr, saddr); - - wlinfo("%02X:%02X\n", saddr[0], saddr[1]); - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_setcoordeaddr - * - * Description: - * Define the coordinator extended address. The following addresses are special: - * FFFFFFFFFFFFFFFFh : Unspecified - * - ****************************************************************************/ - -static int mrf24j40_setcoordeaddr(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *eaddr) -{ - int i; - - for (i = 0; i < 8; i++) - { - mrf24j40_setreg(dev->spi, MRF24J40_ASSOEADR0 + i, eaddr[i]); - dev->addr.eaddr[i] = eaddr[i]; - } - - wlinfo("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", eaddr[0], eaddr[1], - eaddr[2], eaddr[3], eaddr[4], eaddr[5], eaddr[6], eaddr[7]); - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_setdevmode - * - * Description: - * Define the device behaviour: normal end device or coordinator - * - ****************************************************************************/ - -static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev, - uint8_t mode) -{ - int ret = OK; - uint8_t reg; - - /* Disable slotted mode until I decide to implement slotted mode */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); - reg &= ~MRF24J40_TXMCR_SLOTTED; - mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); - mrf24j40_setreg(dev->spi, MRF24J40_ORDER, 0xFF); - - /* Define dev mode */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR); - - if (mode == MRF24J40_MODE_PANCOORD) - { - reg |= MRF24J40_RXMCR_PANCOORD; - reg &= ~MRF24J40_RXMCR_COORD; - } - else if (mode == MRF24J40_MODE_COORD) - { - reg |= MRF24J40_RXMCR_COORD; - reg &= ~MRF24J40_RXMCR_PANCOORD; - } - else if (mode == MRF24J40_MODE_DEVICE) - { - reg &= ~MRF24J40_RXMCR_PANCOORD; - reg &= ~MRF24J40_RXMCR_COORD; - } - else - { - return -EINVAL; - } - - mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg); - dev->devmode = mode; - return ret; -} - -/**************************************************************************** - * Name: mrf24j40_settxpower - * - * Description: - * Define the transmit power. Value is passed in mBm, it is rounded to - * the nearest value. Some MRF modules have a power amplifier, this routine - * does not care about this. We only change the CHIP output power. - * - ****************************************************************************/ - -static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, - int32_t txpwr) -{ - uint8_t reg; - int save_txpwr = txpwr; - - if (txpwr <= -3000 && txpwr > -3630) - { - reg = 0xC0; - txpwr += 3000; - } - else if (txpwr <= -2000) - { - reg = 0x80; - txpwr += 2000; - } - else if (txpwr <= -1000) - { - reg = 0x40; - txpwr += 1000; - } - else if (txpwr <= 0) - { - reg = 0x00; - } - else - { - return -EINVAL; - } - - wlinfo("Remaining attenuation: %d mBm\n",txpwr); - - switch(txpwr/100) - { - case -9: - case -8: - case -7: - case -6: - reg |= 0x07; - break; - - case -5: - reg |= 0x06; - break; - - case -4: - reg |= 0x05; - break; - - case -3: - reg |= 0x04; - break; - - case -2: - reg |= 0x03; - break; - - case -1: - reg |= 0x02; - break; - - case 0: - reg |= 0x00; /* value 0x01 is 0.5 db, not used */ - break; - - default: - - return -EINVAL; - } - - mrf24j40_setreg(dev->spi, MRF24J40_RFCON3, reg); - - dev->txpower = save_txpwr; - - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_setcca - * - * Description: - * Define the Clear Channel Assessement method. - * - ****************************************************************************/ - -static int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, - FAR struct ieee802154_cca_s *cca) -{ - uint8_t mode; - - if (!cca->use_ed && !cca->use_cs) - { - return -EINVAL; - } - - if (cca->use_cs && cca->csth > 0x0f) - { - return -EINVAL; - } - - mode = mrf24j40_getreg(dev->spi, MRF24J40_BBREG2); - mode &= 0x03; - - if (cca->use_ed) - { - mode |= MRF24J40_BBREG2_CCAMODE_ED; - mrf24j40_setreg(dev->spi, MRF24J40_CCAEDTH, cca->edth); - } - - if (cca->use_cs) - { - mode |= MRF24J40_BBREG2_CCAMODE_CS; - mode |= cca->csth << 2; - } - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG2, mode); - - memcpy(&dev->cca, cca, sizeof(struct ieee802154_cca_s)); - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_regdump - * - * Description: - * Display the value of all registers. - * - ****************************************************************************/ - -static int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev) -{ - uint32_t i; - char buf[4+16*3+2+1]; - int len = 0; - - wlinfo("Short regs:\n"); - - for (i = 0; i < 0x40; i++) - { - if ((i & 15) == 0) - { - len=sprintf(buf, "%02x: ",i&0xFF); - } - - len += sprintf(buf+len, "%02x ", mrf24j40_getreg(dev->spi, i)); - if ((i & 15) == 15) - { - sprintf(buf+len, "\n"); - wlinfo("%s", buf); - } - } - - wlinfo("Long regs:\n"); - - for (i = 0x80000200; i < 0x80000250; i++) - { - if ((i & 15) == 0) - { - len=sprintf(buf, "%02x: ",i&0xFF); - } - - len += sprintf(buf+len, "%02x ", mrf24j40_getreg(dev->spi, i)); - if ((i & 15) == 15) - { - sprintf(buf+len, "\n"); - wlinfo("%s", buf); - } - } - - return 0; -} - /**************************************************************************** * Name: mrf24j40_energydetect * @@ -1578,8 +353,7 @@ static int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev) * ****************************************************************************/ -static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, - FAR uint8_t *energy) +int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *energy) { uint8_t reg; @@ -1625,8 +399,8 @@ static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, * ****************************************************************************/ -static void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, - FAR struct iob_s *frame, bool csma) +void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, + FAR struct iob_s *frame, bool csma) { uint8_t reg; @@ -1681,7 +455,7 @@ static void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, * ****************************************************************************/ -static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev) +void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev) { uint8_t reg; @@ -1698,7 +472,7 @@ static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev) * ****************************************************************************/ -static inline void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev) +void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev) { uint8_t reg; @@ -1717,8 +491,8 @@ static inline void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev) * ****************************************************************************/ -static void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo, - FAR struct iob_s *frame) +void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo, + FAR struct iob_s *frame) { } @@ -1730,9 +504,8 @@ static void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo, * ****************************************************************************/ -static void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *buf, uint8_t length, - uint32_t fifo_addr) +void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, FAR const uint8_t *buf, + uint8_t length, uint32_t fifo_addr) { int hlen = 3; /* Include frame control and seq number */ @@ -1784,146 +557,6 @@ static void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, } } -/**************************************************************************** - * Name: mrf24j40_irqwork_txnorm - * - * Description: - * Manage completion of packet transmission. - * - ****************************************************************************/ - -static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev) -{ - uint8_t reg; - enum ieee802154_status_e status; - bool framepending; - - /* Disable tx int */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg |= MRF24J40_INTCON_TXNIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - - /* Get the status from the device and copy the status into the tx desc. - * The status for the normal FIFO is represented with bit TXNSTAT where - * 0=success, 1= failure. - */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); - - /* TXNSTAT = 0: Transmission was successful - * TXNSTAT = 1: Transmission failed, retry count exceeded - */ - - if (reg & MRF24J40_TXSTAT_TXNSTAT) - { - /* The number of retries of the most recent transmission is contained in the - * TXNRETRY (TXSTAT 0x24<7:6>) bits. The CCAFAIL (TXSTAT 0x24<5>) bit = 1 - * indicates if the failed transmission was due to the channel busy - * (CSMA-CA timed out). - */ - - if (reg & MRF24J40_TXSTAT_CCAFAIL) - { - status = IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE; - } - else - { - status = IEEE802154_STATUS_NO_ACK; - } - } - else - { - status = IEEE802154_STATUS_SUCCESS; - } - - framepending = (mrf24j40_getreg(dev->spi, MRF24J40_TXNCON) & - MRF24J40_TXNCON_FPSTAT); - - if (dev->txdelayed_busy) - - { - /* Inform the next layer of the transmission success/failure */ - - dev->txdelayed_desc->conf->status = status; - dev->txdelayed_desc->framepending = framepending; - dev->radiocb->txdone(dev->radiocb, dev->txdelayed_desc); - - dev->txdelayed_busy = false; - - if (dev->reschedule_csma) - { - mrf24j40_norm_setup(dev, dev->csma_desc->frame, true); - mrf24j40_norm_trigger(dev); - dev->reschedule_csma = false; - } - } - else - { - /* Inform the next layer of the transmission success/failure */ - - dev->csma_desc->conf->status = status; - dev->csma_desc->framepending = framepending; - dev->radiocb->txdone(dev->radiocb, dev->csma_desc); - - /* We are now done with the transaction */ - - dev->csma_busy = 0; - - /* Must unlock the radio before calling poll */ - - sem_post(&dev->exclsem); - mrf24j40_dopoll_csma(dev); - while (sem_wait(&dev->exclsem) != 0) { } - } -} - -/**************************************************************************** - * Name: mrf24j40_irqwork_gts - * - * Description: - * Manage completion of packet transmission. - * - ****************************************************************************/ - -static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, - uint8_t gts) -{ - uint8_t txstat; - - /* Disable tx int */ - - txstat = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - txstat |= MRF24J40_INTCON_TXNIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, txstat); - - /* Get the status from the device and copy the status into the tx desc. - * The status for the normal FIFO is represented with bit TXNSTAT where - * 0=success, 1= failure. - */ - - txstat = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); - - if (gts == 0) - { - dev->csma_desc->conf->status = txstat & MRF24J40_TXSTAT_TXG1STAT; - } - else if (gts == 1) - { - dev->csma_desc->conf->status = txstat & MRF24J40_TXSTAT_TXG2STAT; - } - - /* Inform the next layer of the transmission success/failure */ - - dev->radiocb->txdone(dev->radiocb, dev->gts_desc[gts]); - - /* We are now done with the transaction */ - - dev->gts_busy[gts]= 0; - - mrf24j40_dopoll_gts(dev); -} - /**************************************************************************** * Name: mrf24j40_rxenable * @@ -1932,7 +565,7 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, * ****************************************************************************/ -static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable) +int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; uint8_t reg; @@ -1975,241 +608,25 @@ static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable) } /**************************************************************************** - * Name: mrf24j40_irqwork_rx + * Name: mrf24j40_resetrfsm * * Description: - * Manage packet reception. + * Reset the RF state machine. Required at boot, after channel change, + * and probably after PA settings. * ****************************************************************************/ -static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) - +void mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev) { - FAR struct ieee802154_data_ind_s *ind; - uint32_t addr; - uint32_t index; - uint8_t reg; - - wlinfo("RX interrupt\n"); - - /* Disable rx int */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg |= MRF24J40_INTCON_RXIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - - /* Disable packet reception. See pg. 109 of datasheet */ - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, MRF24J40_BBREG1_RXDECINV); - - /* Allocate a data_ind to put the frame in */ - - ind = ieee802154_ind_allocate(); - if (ind == NULL) - { - wlerr("ERROR: Unable to allocate data_ind. Discarding frame\n"); - goto done; - } - - /* Read packet */ - - addr = MRF24J40_RXBUF_BASE; - - ind->frame->io_len = mrf24j40_getreg(dev->spi, addr++); - - for (index = 0; index < ind->frame->io_len; index++) - { - ind->frame->io_data[index] = mrf24j40_getreg(dev->spi, addr++); - } - - ind->lqi = mrf24j40_getreg(dev->spi, addr++); - ind->rssi = mrf24j40_getreg(dev->spi, addr++); - - /* Reduce len by 2, we only receive frames with correct crc, no check - * required. - */ - - ind->frame->io_len -= 2; - - /* Callback the receiver in the next highest layer */ - - dev->radiocb->rxframe(dev->radiocb, ind); - -done: - /* Enable reception of next packet by flushing the fifo. - * This is an MRF24J40 errata (no. 1). - */ - - mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, 1); - - /* Only enable RX interrupt if we are to be listening when IDLE */ - - if (dev->rxenabled) - { - /* Enable packet reception */ - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0); - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg &= ~MRF24J40_INTCON_RXIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - } -} - -/**************************************************************************** - * Name: mrf24j40_irqworker - * - * Description: - * Perform interrupt handling logic outside of the interrupt handler (on - * the work queue thread). - * - * Parameters: - * arg - The reference to the driver structure (cast to void*) - * - * Returned Value: - * None - * - * Assumptions: - * - ****************************************************************************/ - -static void mrf24j40_irqworker(FAR void *arg) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; - uint8_t intstat; uint8_t reg; - DEBUGASSERT(dev); - DEBUGASSERT(dev->spi); + reg = mrf24j40_getreg(dev->spi, MRF24J40_RFCTL); + reg |= 0x04; + mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); - /* Get exclusive access to the driver */ - - while (sem_wait(&dev->exclsem) != 0) { } - - /* Read and store INTSTAT - this clears the register. */ - - intstat = mrf24j40_getreg(dev->spi, MRF24J40_INTSTAT); - - /* Do work according to the pending interrupts */ - - if ((intstat & MRF24J40_INTSTAT_HSYMTMRIF)) - { - /* As of now the only use for the MAC timer is for delayed transactions. - * Therefore, all we do here is trigger the TX norm FIFO - */ - - mrf24j40_norm_trigger(dev); - - /* Timers are one-shot, so disable the interrupt */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg |= MRF24J40_INTCON_HSYMTMRIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - } - - if ((intstat & MRF24J40_INTSTAT_RXIF) && dev->rxenabled) - { - /* A packet was received, retrieve it */ - - mrf24j40_irqwork_rx(dev); - } - - if ((intstat & MRF24J40_INTSTAT_TXNIF)) - { - /* A packet was transmitted or failed*/ - - mrf24j40_irqwork_txnorm(dev); - } - - if ((intstat & MRF24J40_INTSTAT_TXG1IF)) - { - /* A packet was transmitted or failed*/ - - mrf24j40_irqwork_txgts(dev, 0); - } - - if ((intstat & MRF24J40_INTSTAT_TXG1IF)) - { - /* A packet was transmitted or failed*/ - - mrf24j40_irqwork_txgts(dev, 1); - } - - if ((intstat & MRF24J40_INTSTAT_SLPIF)) - { - dev->radiocb->sfevent(dev->radiocb, IEEE802154_SFEVENT_ENDOFACTIVE); - - /* Acknowledge the alert and put the device to sleep */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_SLPACK); - reg |= MRF24J40_SLPACK_SLPACK; - mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, reg); - } - - if ((intstat & MRF24J40_INTSTAT_WAKEIF)) - { -#ifdef CONFIG_MAC802154_SFEVENT_VERBOSE - wlinfo("Wake Interrupt\n"); -#endif - - /* This is right before the beacon, we set the bsn here, since the MAC - * uses the SLPIF (end of active portion of superframe). to make any - * changes to the beacon. This assumes that any changes to the beacon - * be in by the time that this interrupt fires. - */ - - mrf24j40_setreg(dev->spi, MRF24J40_BEACON_FIFO + 4, dev->bsn++); - mrf24j40_beacon_trigger(dev); - } - - /* Unlock the radio device */ - - sem_post(&dev->exclsem); - - /* Re-enable GPIO interrupts */ - - dev->lower->enable(dev->lower, true); -} - -/**************************************************************************** - * Name: mrf24j40_interrupt - * - * Description: - * Hardware interrupt handler - * - * Parameters: - * irq - Number of the IRQ that generated the interrupt - * context - Interrupt register state save info (architecture-specific) - * - * Returned Value: - * OK on success - * - * Assumptions: - * - ****************************************************************************/ - -static int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; - - DEBUGASSERT(dev != NULL); - - /* In complex environments, we cannot do SPI transfers from the interrupt - * handler because semaphores are probably used to lock the SPI bus. In - * this case, we will defer processing to the worker thread. This is also - * much kinder in the use of system resources and is, therefore, probably - * a good thing to do in any event. - */ - - DEBUGASSERT(work_available(&dev->irqwork)); - - /* Notice that further GPIO interrupts are disabled until the work is - * actually performed. This is to prevent overrun of the worker thread. - * Interrupts are re-enabled in enc_irqworker() when the work is completed. - */ - - dev->lower->enable(dev->lower, false); - return work_queue(HPWORK, &dev->irqwork, mrf24j40_irqworker, (FAR void *)dev, 0); + reg &= ~0x04; + mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); + up_udelay(200); } /**************************************************************************** diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h index c21c2e9f38..1a3c15da09 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h @@ -33,258 +33,192 @@ * ****************************************************************************/ -#ifndef __DRIVERS_WIRELESS_IEEE802154_MRF24J40_MRF24J40_H -#define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_MRF24J40_H +#ifndef __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H +#define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H -/* MRF24J40 Registers *******************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ -#define MRF24J40_RXMCR 0x00 -#define MRF24J40_PANIDL 0x01 -#define MRF24J40_PANIDH 0x02 -#define MRF24J40_SADRL 0x03 -#define MRF24J40_SADRH 0x04 -#define MRF24J40_EADR0 0x05 -#define MRF24J40_EADR1 0x06 -#define MRF24J40_EADR2 0x07 -#define MRF24J40_EADR3 0x08 -#define MRF24J40_EADR4 0x09 -#define MRF24J40_EADR5 0x0A -#define MRF24J40_EADR6 0x0B -#define MRF24J40_EADR7 0x0C -#define MRF24J40_RXFLUSH 0x0D -#define MRF24J40_ORDER 0x10 -#define MRF24J40_TXMCR 0x11 -#define MRF24J40_ACKTMOUT 0x12 -#define MRF24J40_ESLOTG1 0x13 -#define MRF24J40_SYMTICKL 0x14 -#define MRF24J40_SYMTICKH 0x15 -#define MRF24J40_PACON0 0x16 -#define MRF24J40_PACON1 0x17 -#define MRF24J40_PACON2 0x18 -#define MRF24J40_TXBCON0 0x1A -#define MRF24J40_TXNCON 0x1B -#define MRF24J40_TXG1CON 0x1C -#define MRF24J40_TXG2CON 0x1D -#define MRF24J40_ESLOTG23 0x1E -#define MRF24J40_ESLOTG45 0x1F -#define MRF24J40_ESLOTG67 0x20 -#define MRF24J40_TXPEND 0x21 -#define MRF24J40_WAKECON 0x22 -#define MRF24J40_FRMOFFSET 0x23 -#define MRF24J40_TXSTAT 0x24 -#define MRF24J40_TXBCON1 0x25 -#define MRF24J40_GATECLK 0x26 -#define MRF24J40_TXTIME 0x27 -#define MRF24J40_HSYMTMRL 0x28 -#define MRF24J40_HSYMTMRH 0x29 -#define MRF24J40_SOFTRST 0x2A -#define MRF24J40_SECCON0 0x2C -#define MRF24J40_SECCON1 0x2C -#define MRF24J40_TXSTBL 0x2E -#define MRF24J40_RXSR 0x30 -#define MRF24J40_INTSTAT 0x31 -#define MRF24J40_INTCON 0x32 -#define MRF24J40_GPIO 0x33 -#define MRF24J40_TRISGPIO 0x34 -#define MRF24J40_SLPACK 0x35 -#define MRF24J40_RFCTL 0x36 -#define MRF24J40_SECCR2 0x37 -#define MRF24J40_BBREG0 0x38 -#define MRF24J40_BBREG1 0x39 -#define MRF24J40_BBREG2 0x3A -#define MRF24J40_BBREG3 0x3B -#define MRF24J40_BBREG4 0x3C -#define MRF24J40_BBREG6 0x3E -#define MRF24J40_CCAEDTH 0x3F +#include -#define MRF24J40_FIFO_BASE 0x80000000 -#define MRF24J40_LONGREG_BASE 0x80000200 -#define MRF24J40_RXBUF_BASE 0x80000300 +#include +#include +#include -#define MRF24J40_TXNORM_FIFO (MRF24J40_FIFO_BASE + 0x000) -#define MRF24J40_BEACON_FIFO (MRF24J40_FIFO_BASE + 0x080) -#define MRF24J40_GTS1_FIFO (MRF24J40_FIFO_BASE + 0x100) -#define MRF24J40_GTS2_FIFO (MRF24J40_FIFO_BASE + 0x180) +#include +#include -#define MRF24J40_RFCON0 (MRF24J40_LONGREG_BASE + 0x00) -#define MRF24J40_RFCON1 (MRF24J40_LONGREG_BASE + 0x01) -#define MRF24J40_RFCON2 (MRF24J40_LONGREG_BASE + 0x02) -#define MRF24J40_RFCON3 (MRF24J40_LONGREG_BASE + 0x03) -#define MRF24J40_RFCON5 (MRF24J40_LONGREG_BASE + 0x05) -#define MRF24J40_RFCON6 (MRF24J40_LONGREG_BASE + 0x06) -#define MRF24J40_RFCON7 (MRF24J40_LONGREG_BASE + 0x07) -#define MRF24J40_RFCON8 (MRF24J40_LONGREG_BASE + 0x08) -#define MRF24J40_SLPCAL0 (MRF24J40_LONGREG_BASE + 0x09) -#define MRF24J40_SLPCAL1 (MRF24J40_LONGREG_BASE + 0x0A) -#define MRF24J40_SLPCAL2 (MRF24J40_LONGREG_BASE + 0x0B) -#define MRF24J40_RFSTATE (MRF24J40_LONGREG_BASE + 0x0F) -#define MRF24J40_RSSI (MRF24J40_LONGREG_BASE + 0x10) -#define MRF24J40_SLPCON0 (MRF24J40_LONGREG_BASE + 0x11) -#define MRF24J40_SLPCON1 (MRF24J40_LONGREG_BASE + 0x20) -#define MRF24J40_WAKETIMEL (MRF24J40_LONGREG_BASE + 0x22) -#define MRF24J40_WAKETIMEH (MRF24J40_LONGREG_BASE + 0x23) -#define MRF24J40_REMCNTL (MRF24J40_LONGREG_BASE + 0x24) -#define MRF24J40_REMCNTH (MRF24J40_LONGREG_BASE + 0x25) -#define MRF24J40_MAINCNT0 (MRF24J40_LONGREG_BASE + 0x26) -#define MRF24J40_MAINCNT1 (MRF24J40_LONGREG_BASE + 0x27) -#define MRF24J40_MAINCNT2 (MRF24J40_LONGREG_BASE + 0x28) -#define MRF24J40_MAINCNT3 (MRF24J40_LONGREG_BASE + 0x29) -#define MRF24J40_TESTMODE (MRF24J40_LONGREG_BASE + 0x2F) -#define MRF24J40_ASSOEADR0 (MRF24J40_LONGREG_BASE + 0x30) -#define MRF24J40_ASSOEADR1 (MRF24J40_LONGREG_BASE + 0x31) -#define MRF24J40_ASSOEADR2 (MRF24J40_LONGREG_BASE + 0x32) -#define MRF24J40_ASSOEADR3 (MRF24J40_LONGREG_BASE + 0x33) -#define MRF24J40_ASSOEADR4 (MRF24J40_LONGREG_BASE + 0x34) -#define MRF24J40_ASSOEADR5 (MRF24J40_LONGREG_BASE + 0x35) -#define MRF24J40_ASSOEADR6 (MRF24J40_LONGREG_BASE + 0x36) -#define MRF24J40_ASSOEADR7 (MRF24J40_LONGREG_BASE + 0x37) -#define MRF24J40_ASSOSADR0 (MRF24J40_LONGREG_BASE + 0x38) -#define MRF24J40_ASSOSADR1 (MRF24J40_LONGREG_BASE + 0x39) -#define MRF24J40_UPNONCE0 (MRF24J40_LONGREG_BASE + 0x40) -#define MRF24J40_UPNONCE1 (MRF24J40_LONGREG_BASE + 0x41) -#define MRF24J40_UPNONCE2 (MRF24J40_LONGREG_BASE + 0x42) -#define MRF24J40_UPNONCE3 (MRF24J40_LONGREG_BASE + 0x43) -#define MRF24J40_UPNONCE4 (MRF24J40_LONGREG_BASE + 0x44) -#define MRF24J40_UPNONCE5 (MRF24J40_LONGREG_BASE + 0x45) -#define MRF24J40_UPNONCE6 (MRF24J40_LONGREG_BASE + 0x46) -#define MRF24J40_UPNONCE7 (MRF24J40_LONGREG_BASE + 0x47) -#define MRF24J40_UPNONCE8 (MRF24J40_LONGREG_BASE + 0x48) -#define MRF24J40_UPNONCE9 (MRF24J40_LONGREG_BASE + 0x49) -#define MRF24J40_UPNONCE10 (MRF24J40_LONGREG_BASE + 0x4A) -#define MRF24J40_UPNONCE11 (MRF24J40_LONGREG_BASE + 0x4B) -#define MRF24J40_UPNONCE12 (MRF24J40_LONGREG_BASE + 0x4C) +#include +#include -/* INTSTAT bits */ +/* NuttX implementation defines **********************************************/ -#define MRF24J40_INTSTAT_TXNIF (1 << 0) -#define MRF24J40_INTSTAT_TXG1IF (1 << 1) -#define MRF24J40_INTSTAT_TXG2IF (1 << 2) -#define MRF24J40_INTSTAT_RXIF (1 << 3) -#define MRF24J40_INTSTAT_SECIF (1 << 4) -#define MRF24J40_INTSTAT_HSYMTMRIF (1 << 5) -#define MRF24J40_INTSTAT_WAKEIF (1 << 6) -#define MRF24J40_INTSTAT_SLPIF (1 << 7) +#define MRF24J40_GTS_SLOTS 2 -/* RXMCR bits */ +/* Definitions for the device structure */ -#define MRF24J40_RXMCR_PROMI (1 << 0) /* Enable promisc mode (rx all valid packets) */ -#define MRF24J40_RXMCR_ERRPKT 0x02 /* Do not check CRC */ -#define MRF24J40_RXMCR_COORD 0x04 /* Enable coordinator mode ??? DIFFERENCE ??? - not used in datasheet! */ -#define MRF24J40_RXMCR_PANCOORD 0x08 /* Enable PAN coordinator mode ??? DIFFERENCE ??? */ -#define MRF24J40_RXMCR_NOACKRSP 0x20 /* Enable auto ACK when a packet is rxed */ +#define MRF24J40_RXMODE_NORMAL 0 +#define MRF24J40_RXMODE_PROMISC 1 +#define MRF24J40_RXMODE_NOCRC 2 -/* TXMCR bits */ +#define MRF24J40_MODE_DEVICE 0 +#define MRF24J40_MODE_COORD 1 +#define MRF24J40_MODE_PANCOORD 2 -#define MRF24J40_TXMCR_CSMABF0 (1 << 0) -#define MRF24J40_TXMCR_CSMABF1 0x02 -#define MRF24J40_TXMCR_CSMABF2 0x04 -#define MRF24J40_TXMCR_MACMINBE0 0x08 -#define MRF24J40_TXMCR_MACMINBE1 0x10 -#define MRF24J40_TXMCR_SLOTTED 0x20 -#define MRF24J40_TXMCR_BATLIFEXT 0x40 -#define MRF24J40_TXMCR_NOCSMA 0x80 +/* Definitions for PA control on high power modules */ -/* ACKTMOUT bits */ +#define MRF24J40_PA_AUTO 1 +#define MRF24J40_PA_ED 2 +#define MRF24J40_PA_SLEEP 3 -#define MRF24J40_ACKTMOUT_MAWD 0xEF -#define MRF24J40_ACKTMOUT_DRPACK 0x80 +/* Formula for calculating default macMaxFrameWaitTime is on pg. 130 + * + * For PHYs other than CSS and UWB, the attribute phyMaxFrameDuration is given by: + * + * phyMaxFrameDuration = phySHRDuration + + * ceiling([aMaxPHYPacketSize + 1] x phySymbolsPerOctet) + * + * where ceiling() is a function that returns the smallest integer value greater + * than or equal to its argument value. [1] pg. 158 +*/ -/* INTCON bits */ +#define MRF24J40_DEFAULT_MAX_FRAME_WAITTIME 1824 -#define MRF24J40_INTCON_SLPIE 0x80 -#define MRF24J40_INTCON_WAKEIE 0x40 -#define MRF24J40_INTCON_HSYMTMRIE 0x20 -#define MRF24J40_INTCON_SECIE 0x10 -#define MRF24J40_INTCON_RXIE 0x08 -#define MRF24J40_INTCON_TXG2IE 0x04 -#define MRF24J40_INTCON_TXG1IE 0x02 -#define MRF24J40_INTCON_TXNIE (1 << 0) +#define MRF24J40_SYMBOL_DURATION_PS 16000000 -/* BBREG1 bits */ +/* Configuration *************************************************************/ -#define MRF24J40_BBREG1_RXDECINV 0x04 /* Enable/Disable packet reception */ +#ifndef CONFIG_SCHED_HPWORK +# error High priority work queue required in this driver +#endif -/* BBREG2 bits */ +#ifndef CONFIG_IEEE802154_MRF24J40_SPIMODE +# define CONFIG_IEEE802154_MRF24J40_SPIMODE SPIDEV_MODE0 +#endif -#define MRF24J40_BBREG2_CCAMODE_ED 0x80 -#define MRF24J40_BBREG2_CCAMODE_CS 0x40 +#ifndef CONFIG_IEEE802154_MRF24J40_FREQUENCY +# define CONFIG_IEEE802154_MRF24J40_FREQUENCY 8000000 +#endif -/* TXNCON bits */ +#ifndef CONFIG_SPI_EXCHANGE +# error CONFIG_SPI_EXCHANGE required for this driver +#endif -#define MRF24J40_TXNCON_TXNTRIG (1 << 0) /* Trigger packet tx, automatically cleared */ -#define MRF24J40_TXNCON_TXNSECEN 0x02 /* Enable security */ -#define MRF24J40_TXNCON_TXNACKREQ 0x04 /* An ACK is requested for this pkt */ -#define MRF24J40_TXNCON_INDIRECT 0x08 /* Activate indirect tx bit (for coordinators) */ -#define MRF24J40_TXNCON_FPSTAT 0x10 /* Status of the frame pending big in txed acks */ +/**************************************************************************** + * Private Types + ****************************************************************************/ -/* TXSTAT bits */ +/* A MRF24J40 device instance */ -#define MRF24J40_TXSTAT_TXNSTAT (1 << 0) -#define MRF24J40_TXSTAT_TXG1STAT (1 << 1) -#define MRF24J40_TXSTAT_TXG2STAT (1 << 2) -#define MRF24J40_TXSTAT_CCAFAIL (1 << 5) -#define MRF24J40_TXSTAT_X_SHIFT 6 -#define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT) +struct mrf24j40_radio_s +{ + struct ieee802154_radio_s radio; /* The public device instance */ + FAR struct ieee802154_radiocb_s *radiocb; /* Registered callbacks */ -/* TXBCON0 bits */ + /* Low-level MCU-specific support */ -#define MRF24J40_TXBCON0_TXBTRIG 0x01 -#define MRF24J40_TXBCON0_TXBSECEN 0x02 + FAR const struct mrf24j40_lower_s *lower; + FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ -/* TXBCON1 bits */ + 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 */ -#define MRF24J40_TXBCON1_RSSINUM 0x30 -#define MRF24J40_TXBCON1_NWU_BCN 0x40 -#define MRF24J40_TXBCON1_TXBMSK 0x80 + sem_t exclsem; /* Exclusive access to this struct */ -/* WAKECON bits */ + /* MAC Attributes */ -#define MRF24J40_WAKECON_INTL 0x3F -#define MRF24J40_WAKECON_REGWAKE 0x40 -#define MRF24J40_WAKECON_IMMWAKE 0x80 + struct ieee802154_addr_s addr; -/* WAKECON bits */ + uint8_t chan; /* 11 to 26 for the 2.4 GHz band */ + uint8_t devmode; /* device mode: device, coord, pancoord */ + uint8_t paenabled; /* enable usage of PA */ + uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ + int32_t txpower; /* TX power in mBm = dBm/100 */ + struct ieee802154_cca_s cca; /* Clear channel assessement method */ -#define MRF24J40_WAKECON_INTL 0x3F -#define MRF24J40_WAKECON_REGWAKE 0x40 -#define MRF24J40_WAKECON_IMMWAKE 0x80 + /* MAC PIB attributes */ -/* ESLOTG1 bits */ + uint32_t max_frame_waittime; -#define MRF24J40_ESLOTG1_CAP 0x0F -#define MRF24J40_ESLOTG1_GTS1 0xF0 + struct ieee802154_txdesc_s *txdelayed_desc; + struct ieee802154_txdesc_s *csma_desc; + bool txdelayed_busy : 1; + bool csma_busy : 1; + bool reschedule_csma : 1; -/* SLPCAL2 bits */ + bool rxenabled : 1; -#define MRF24J40_SLPCAL2_SLPCAL 0x0F -#define MRF24J40_SLPCAL2_SLPCALEN 0x10 -#define MRF24J40_SLPCAL2_SLPCALRDY 0x80 + uint8_t bsn; -/* RFCON7 bits */ + struct ieee802154_txdesc_s *gts_desc[MRF24J40_GTS_SLOTS]; + bool gts_busy[MRF24J40_GTS_SLOTS]; +}; -#define MRF24J40_RFCON7_SEL_32KHZ 0x40 -#define MRF24J40_RFCON7_SEL_100KHZ 0x80 +/**************************************************************************** + * Internal Function Prototypes + ****************************************************************************/ -/* SLPACK bits */ +int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg); +void mrf24j40_irqworker(FAR void *arg); -#define MRF24J40_SLPACK_WAKECNT0_6 0x7F -#define MRF24J40_SLPACK_SLPACK 0x80 +void mrf24j40_dopoll_csma(FAR void *arg); +void mrf24j40_dopoll_gts(FAR void *arg); -/* RXFLUSH bits */ +void mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev); -#define MRF24J40_RXFLUSH_RXFLUSH 0x01 -#define MRF24J40_RXFLUSH_BCNONLY 0x02 -#define MRF24J40_RXFLUSH_DATAONLY 0x04 -#define MRF24J40_RXFLUSH_CMDONLY 0x08 -#define MRF24J40_RXFLUSH_WAKEPAD 0x20 -#define MRF24J40_RXFLUSH_WAKEPOL 0x40 +void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, uint8_t so); -#define MRF24J40_RXFLUSH_SHIFT_RXFLUSH 0 -#define MRF24J40_RXFLUSH_SHIFT_BCNONLY 1 -#define MRF24J40_RXFLUSH_SHIFT_DATAONLY 2 -#define MRF24J40_RXFLUSH_SHIFT_CMDONLY 3 -#define MRF24J40_RXFLUSH_SHIFT_WAKEPAD 5 -#define MRF24J40_RXFLUSH_SHIFT_WAKEPOL 6 +int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode); +int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *energy); -#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_MRF24J40_H */ +int mrf24j40_rxenable(FAR struct ieee802154_radio_s *dev, bool enable); + +void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, + FAR struct iob_s *frame, bool csma); +void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, + FAR struct iob_s *frame); +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); +void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev); + +void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols); + +/**************************************************************************** + * Internal Helpers + ****************************************************************************/ + +/**************************************************************************** + * Name: mrf24j40_spi_lock + * + * Description: + * Acquire exclusive access to the shared SPI bus. + * + ****************************************************************************/ + +static inline void mrf24j40_spi_lock(FAR struct spi_dev_s *spi) +{ + SPI_LOCK(spi, 1); + SPI_SETBITS(spi, 8); + SPI_SETMODE(spi, CONFIG_IEEE802154_MRF24J40_SPIMODE); + SPI_SETFREQUENCY(spi, CONFIG_IEEE802154_MRF24J40_FREQUENCY); +} + +/**************************************************************************** + * Name: mrf24j40_spi_unlock + * + * Description: + * Release exclusive access to the shared SPI bus. + * + ****************************************************************************/ + +static inline void mrf24j40_spi_unlock(FAR struct spi_dev_s *spi) +{ + SPI_LOCK(spi,0); +} + +#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H */ diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c new file mode 100644 index 0000000000..a4b92ad666 --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c @@ -0,0 +1,425 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c + * + * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "mrf24j40.h" +#include "mrf24j40_reg.h" +#include "mrf24j40_regops.h" +#include "mrf24j40_getset.h" + +/**************************************************************************** + * Name: mrf24j40_setrxmode + * + * Description: + * Set the RX mode (normal, promiscuous, no CRC) + * + ****************************************************************************/ + +int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode) +{ + uint8_t reg; + + if (mode < MRF24J40_RXMODE_NORMAL || mode > MRF24J40_RXMODE_NOCRC) + { + return -EINVAL; + } + + reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR); + reg &= ~0x03; + reg |= mode; + + /* Set mode options */ + + if (mode != MRF24J40_RXMODE_NORMAL) + { + /* Promisc and error modes: Disable auto ACK */ + + reg |= MRF24J40_RXMCR_NOACKRSP; + } + else + { + /* Normal mode : enable auto-ACK */ + + reg &= ~MRF24J40_RXMCR_NOACKRSP; + } + + mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg); + + dev->rxmode = mode; + wlinfo("%u\n", (unsigned)mode); + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_setchannel + * + * Description: + * Define the current radio channel the device is operating on. + * In the 2.4 GHz, there are 16 channels, each 2 MHz wide, 5 MHz spacing: + * Chan MHz Chan MHz Chan MHz Chan MHz + * 11 2405 15 2425 19 2445 23 2465 + * 12 2410 16 2430 20 2450 24 2470 + * 13 2415 17 2435 21 2455 25 2475 + * 14 2420 18 2440 22 2460 26 2480 + * + ****************************************************************************/ + +int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, uint8_t chan) +{ + if (chan < 11 || chan > 26) + { + wlerr("ERROR: Invalid chan: %d\n",chan); + return -EINVAL; + } + + /* 15. Set channel – See Section 3.4 “Channel Selection”. */ + + mrf24j40_setreg(dev->spi, MRF24J40_RFCON0, (chan - 11) << 4 | 0x03); + + /* 17. RFCTL (0x36) = 0x04 – Reset RF state machine. + * 18. RFCTL (0x36) = 0x00. + */ + + mrf24j40_resetrfsm(dev); + + dev->chan = chan; + wlinfo("%u\n", (unsigned)chan); + + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_setpanid + * + * Description: + * Define the PAN ID the device is operating on. + * + ****************************************************************************/ + +int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *panid) +{ + mrf24j40_setreg(dev->spi, MRF24J40_PANIDL, panid[0]); + mrf24j40_setreg(dev->spi, MRF24J40_PANIDH, panid[1]); + + IEEE802154_PANIDCOPY(dev->addr.panid, panid); + wlinfo("%02X:%02X\n", panid[0], panid[1]); + + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_setsaddr + * + * Description: + * Define the device short address. The following addresses are special: + * FFFEh : Broadcast + * FFFFh : Unspecified + * + ****************************************************************************/ + +int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *saddr) +{ + mrf24j40_setreg(dev->spi, MRF24J40_SADRL, saddr[0]); + mrf24j40_setreg(dev->spi, MRF24J40_SADRH, saddr[1]); + + IEEE802154_SADDRCOPY(dev->addr.saddr, saddr); + + wlinfo("%02X:%02X\n", saddr[0], saddr[1]); + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_seteaddr + * + * Description: + * Define the device extended address. The following addresses are special: + * FFFFFFFFFFFFFFFFh : Unspecified + * + ****************************************************************************/ + +int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *eaddr) +{ + int i; + + for (i = 0; i < 8; i++) + { + mrf24j40_setreg(dev->spi, MRF24J40_EADR0 + i, eaddr[i]); + dev->addr.eaddr[i] = eaddr[i]; + } + wlinfo("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", eaddr[0], eaddr[1], + eaddr[2], eaddr[3], eaddr[4], eaddr[5], eaddr[6], eaddr[7]); + + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_setcoordsaddr + * + * Description: + * Define the coordinator short address. The following addresses are special: + * FFFEh : Broadcast + * FFFFh : Unspecified + * + ****************************************************************************/ + +int mrf24j40_setcoordsaddr(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *saddr) +{ + mrf24j40_setreg(dev->spi, MRF24J40_ASSOSADR0, saddr[0]); + mrf24j40_setreg(dev->spi, MRF24J40_ASSOSADR1, saddr[1]); + + IEEE802154_SADDRCOPY(dev->addr.saddr, saddr); + + wlinfo("%02X:%02X\n", saddr[0], saddr[1]); + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_setcoordeaddr + * + * Description: + * Define the coordinator extended address. The following addresses are special: + * FFFFFFFFFFFFFFFFh : Unspecified + * + ****************************************************************************/ + +int mrf24j40_setcoordeaddr(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *eaddr) +{ + int i; + + for (i = 0; i < 8; i++) + { + mrf24j40_setreg(dev->spi, MRF24J40_ASSOEADR0 + i, eaddr[i]); + dev->addr.eaddr[i] = eaddr[i]; + } + + wlinfo("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", eaddr[0], eaddr[1], + eaddr[2], eaddr[3], eaddr[4], eaddr[5], eaddr[6], eaddr[7]); + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_setdevmode + * + * Description: + * Define the device behaviour: normal end device or coordinator + * + ****************************************************************************/ + +int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev, + uint8_t mode) +{ + int ret = OK; + uint8_t reg; + + /* Disable slotted mode until I decide to implement slotted mode */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); + reg &= ~MRF24J40_TXMCR_SLOTTED; + mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); + mrf24j40_setreg(dev->spi, MRF24J40_ORDER, 0xFF); + + /* Define dev mode */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR); + + if (mode == MRF24J40_MODE_PANCOORD) + { + reg |= MRF24J40_RXMCR_PANCOORD; + reg &= ~MRF24J40_RXMCR_COORD; + } + else if (mode == MRF24J40_MODE_COORD) + { + reg |= MRF24J40_RXMCR_COORD; + reg &= ~MRF24J40_RXMCR_PANCOORD; + } + else if (mode == MRF24J40_MODE_DEVICE) + { + reg &= ~MRF24J40_RXMCR_PANCOORD; + reg &= ~MRF24J40_RXMCR_COORD; + } + else + { + return -EINVAL; + } + + mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg); + dev->devmode = mode; + return ret; +} + +/**************************************************************************** + * Name: mrf24j40_settxpower + * + * Description: + * Define the transmit power. Value is passed in mBm, it is rounded to + * the nearest value. Some MRF modules have a power amplifier, this routine + * does not care about this. We only change the CHIP output power. + * + ****************************************************************************/ + +int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, + int32_t txpwr) +{ + uint8_t reg; + int save_txpwr = txpwr; + + if (txpwr <= -3000 && txpwr > -3630) + { + reg = 0xC0; + txpwr += 3000; + } + else if (txpwr <= -2000) + { + reg = 0x80; + txpwr += 2000; + } + else if (txpwr <= -1000) + { + reg = 0x40; + txpwr += 1000; + } + else if (txpwr <= 0) + { + reg = 0x00; + } + else + { + return -EINVAL; + } + + wlinfo("Remaining attenuation: %d mBm\n",txpwr); + + switch(txpwr/100) + { + case -9: + case -8: + case -7: + case -6: + reg |= 0x07; + break; + + case -5: + reg |= 0x06; + break; + + case -4: + reg |= 0x05; + break; + + case -3: + reg |= 0x04; + break; + + case -2: + reg |= 0x03; + break; + + case -1: + reg |= 0x02; + break; + + case 0: + reg |= 0x00; /* value 0x01 is 0.5 db, not used */ + break; + + default: + + return -EINVAL; + } + + mrf24j40_setreg(dev->spi, MRF24J40_RFCON3, reg); + + dev->txpower = save_txpwr; + + return OK; +} + +/**************************************************************************** + * Name: mrf24j40_setcca + * + * Description: + * Define the Clear Channel Assessement method. + * + ****************************************************************************/ + +int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, + FAR struct ieee802154_cca_s *cca) +{ + uint8_t mode; + + if (!cca->use_ed && !cca->use_cs) + { + return -EINVAL; + } + + if (cca->use_cs && cca->csth > 0x0f) + { + return -EINVAL; + } + + mode = mrf24j40_getreg(dev->spi, MRF24J40_BBREG2); + mode &= 0x03; + + if (cca->use_ed) + { + mode |= MRF24J40_BBREG2_CCAMODE_ED; + mrf24j40_setreg(dev->spi, MRF24J40_CCAEDTH, cca->edth); + } + + if (cca->use_cs) + { + mode |= MRF24J40_BBREG2_CCAMODE_CS; + mode |= cca->csth << 2; + } + + mrf24j40_setreg(dev->spi, MRF24J40_BBREG2, mode); + + memcpy(&dev->cca, cca, sizeof(struct ieee802154_cca_s)); + return OK; +} diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h new file mode 100644 index 0000000000..999ce92875 --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h + * + * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_WIRELESS_IEEE802154_MRF24J40_GETSET_H +#define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_GETSET_H + +int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode); + +int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, uint8_t chan); + +int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *dev, FAR const uint8_t *panid); + +int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev, FAR const uint8_t *saddr); + +int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev, FAR const uint8_t *eaddr); + +int mrf24j40_setcoordsaddr(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *saddr); + +int mrf24j40_setcoordeaddr(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *eaddr); + +int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev, uint8_t mode); + +int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, int32_t txpwr); + +int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, + FAR struct ieee802154_cca_s *cca); + +#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_GETSET_H */ \ No newline at end of file diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c new file mode 100644 index 0000000000..673aba7c34 --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c @@ -0,0 +1,439 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c + * + * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include + +#include + +#include "mrf24j40.h" +#include "mrf24j40_reg.h" +#include "mrf24j40_regops.h" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev); +static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev); +static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, + uint8_t gts_num); + +/**************************************************************************** + * Name: mrf24j40_irqwork_txnorm + * + * Description: + * Manage completion of packet transmission. + * + ****************************************************************************/ + +static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev) +{ + uint8_t reg; + enum ieee802154_status_e status; + bool framepending; + + /* Disable tx int */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_TXNIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + /* Get the status from the device and copy the status into the tx desc. + * The status for the normal FIFO is represented with bit TXNSTAT where + * 0=success, 1= failure. + */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); + + /* TXNSTAT = 0: Transmission was successful + * TXNSTAT = 1: Transmission failed, retry count exceeded + */ + + if (reg & MRF24J40_TXSTAT_TXNSTAT) + { + /* The number of retries of the most recent transmission is contained in the + * TXNRETRY (TXSTAT 0x24<7:6>) bits. The CCAFAIL (TXSTAT 0x24<5>) bit = 1 + * indicates if the failed transmission was due to the channel busy + * (CSMA-CA timed out). + */ + + if (reg & MRF24J40_TXSTAT_CCAFAIL) + { + status = IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE; + } + else + { + status = IEEE802154_STATUS_NO_ACK; + } + } + else + { + status = IEEE802154_STATUS_SUCCESS; + } + + framepending = (mrf24j40_getreg(dev->spi, MRF24J40_TXNCON) & + MRF24J40_TXNCON_FPSTAT); + + if (dev->txdelayed_busy) + + { + /* Inform the next layer of the transmission success/failure */ + + dev->txdelayed_desc->conf->status = status; + dev->txdelayed_desc->framepending = framepending; + dev->radiocb->txdone(dev->radiocb, dev->txdelayed_desc); + + dev->txdelayed_busy = false; + + if (dev->reschedule_csma) + { + mrf24j40_norm_setup(dev, dev->csma_desc->frame, true); + mrf24j40_norm_trigger(dev); + dev->reschedule_csma = false; + } + } + else + { + /* Inform the next layer of the transmission success/failure */ + + dev->csma_desc->conf->status = status; + dev->csma_desc->framepending = framepending; + dev->radiocb->txdone(dev->radiocb, dev->csma_desc); + + /* We are now done with the transaction */ + + dev->csma_busy = 0; + + /* Must unlock the radio before calling poll */ + + sem_post(&dev->exclsem); + mrf24j40_dopoll_csma(dev); + while (sem_wait(&dev->exclsem) != 0) { } + } +} + +/**************************************************************************** + * Name: mrf24j40_irqwork_gts + * + * Description: + * Manage completion of packet transmission. + * + ****************************************************************************/ + +static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, + uint8_t gts) +{ + uint8_t txstat; + + /* Disable tx int */ + + txstat = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + txstat |= MRF24J40_INTCON_TXNIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, txstat); + + /* Get the status from the device and copy the status into the tx desc. + * The status for the normal FIFO is represented with bit TXNSTAT where + * 0=success, 1= failure. + */ + + txstat = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); + + if (gts == 0) + { + dev->csma_desc->conf->status = txstat & MRF24J40_TXSTAT_TXG1STAT; + } + else if (gts == 1) + { + dev->csma_desc->conf->status = txstat & MRF24J40_TXSTAT_TXG2STAT; + } + + /* Inform the next layer of the transmission success/failure */ + + dev->radiocb->txdone(dev->radiocb, dev->gts_desc[gts]); + + /* We are now done with the transaction */ + + dev->gts_busy[gts]= 0; + + mrf24j40_dopoll_gts(dev); +} + +/**************************************************************************** + * Name: mrf24j40_irqwork_rx + * + * Description: + * Manage packet reception. + * + ****************************************************************************/ + +static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) + +{ + FAR struct ieee802154_data_ind_s *ind; + uint32_t addr; + uint32_t index; + uint8_t reg; + + wlinfo("RX interrupt\n"); + + /* Disable rx int */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_RXIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + /* Disable packet reception. See pg. 109 of datasheet */ + + mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, MRF24J40_BBREG1_RXDECINV); + + /* Allocate a data_ind to put the frame in */ + + ind = ieee802154_ind_allocate(); + if (ind == NULL) + { + wlerr("ERROR: Unable to allocate data_ind. Discarding frame\n"); + goto done; + } + + /* Read packet */ + + addr = MRF24J40_RXBUF_BASE; + + ind->frame->io_len = mrf24j40_getreg(dev->spi, addr++); + + for (index = 0; index < ind->frame->io_len; index++) + { + ind->frame->io_data[index] = mrf24j40_getreg(dev->spi, addr++); + } + + ind->lqi = mrf24j40_getreg(dev->spi, addr++); + ind->rssi = mrf24j40_getreg(dev->spi, addr++); + + /* Reduce len by 2, we only receive frames with correct crc, no check + * required. + */ + + ind->frame->io_len -= 2; + + /* Callback the receiver in the next highest layer */ + + dev->radiocb->rxframe(dev->radiocb, ind); + +done: + /* Enable reception of next packet by flushing the fifo. + * This is an MRF24J40 errata (no. 1). + */ + + mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, 1); + + /* Only enable RX interrupt if we are to be listening when IDLE */ + + if (dev->rxenabled) + { + /* Enable packet reception */ + + mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0); + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg &= ~MRF24J40_INTCON_RXIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + } +} + +/**************************************************************************** + * Name: mrf24j40_irqworker + * + * Description: + * Perform interrupt handling logic outside of the interrupt handler (on + * the work queue thread). + * + * Parameters: + * arg - The reference to the driver structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void mrf24j40_irqworker(FAR void *arg) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; + uint8_t intstat; + uint8_t reg; + + DEBUGASSERT(dev); + DEBUGASSERT(dev->spi); + + /* Get exclusive access to the driver */ + + while (sem_wait(&dev->exclsem) != 0) { } + + /* Read and store INTSTAT - this clears the register. */ + + intstat = mrf24j40_getreg(dev->spi, MRF24J40_INTSTAT); + + /* Do work according to the pending interrupts */ + + if ((intstat & MRF24J40_INTSTAT_HSYMTMRIF)) + { + /* As of now the only use for the MAC timer is for delayed transactions. + * Therefore, all we do here is trigger the TX norm FIFO + */ + + mrf24j40_norm_trigger(dev); + + /* Timers are one-shot, so disable the interrupt */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_HSYMTMRIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + } + + if ((intstat & MRF24J40_INTSTAT_RXIF) && dev->rxenabled) + { + /* A packet was received, retrieve it */ + + mrf24j40_irqwork_rx(dev); + } + + if ((intstat & MRF24J40_INTSTAT_TXNIF)) + { + /* A packet was transmitted or failed*/ + + mrf24j40_irqwork_txnorm(dev); + } + + if ((intstat & MRF24J40_INTSTAT_TXG1IF)) + { + /* A packet was transmitted or failed*/ + + mrf24j40_irqwork_txgts(dev, 0); + } + + if ((intstat & MRF24J40_INTSTAT_TXG1IF)) + { + /* A packet was transmitted or failed*/ + + mrf24j40_irqwork_txgts(dev, 1); + } + + if ((intstat & MRF24J40_INTSTAT_SLPIF)) + { + dev->radiocb->sfevent(dev->radiocb, IEEE802154_SFEVENT_ENDOFACTIVE); + + /* Acknowledge the alert and put the device to sleep */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_SLPACK); + reg |= MRF24J40_SLPACK_SLPACK; + mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, reg); + } + + if ((intstat & MRF24J40_INTSTAT_WAKEIF)) + { +#ifdef CONFIG_MAC802154_SFEVENT_VERBOSE + wlinfo("Wake Interrupt\n"); +#endif + + /* This is right before the beacon, we set the bsn here, since the MAC + * uses the SLPIF (end of active portion of superframe). to make any + * changes to the beacon. This assumes that any changes to the beacon + * be in by the time that this interrupt fires. + */ + + mrf24j40_setreg(dev->spi, MRF24J40_BEACON_FIFO + 4, dev->bsn++); + mrf24j40_beacon_trigger(dev); + } + + /* Unlock the radio device */ + + sem_post(&dev->exclsem); + + /* Re-enable GPIO interrupts */ + + dev->lower->enable(dev->lower, true); +} + +/**************************************************************************** + * Name: mrf24j40_interrupt + * + * Description: + * Hardware interrupt handler + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; + + DEBUGASSERT(dev != NULL); + + /* In complex environments, we cannot do SPI transfers from the interrupt + * handler because semaphores are probably used to lock the SPI bus. In + * this case, we will defer processing to the worker thread. This is also + * much kinder in the use of system resources and is, therefore, probably + * a good thing to do in any event. + */ + + DEBUGASSERT(work_available(&dev->irqwork)); + + /* Notice that further GPIO interrupts are disabled until the work is + * actually performed. This is to prevent overrun of the worker thread. + * Interrupts are re-enabled in enc_irqworker() when the work is completed. + */ + + dev->lower->enable(dev->lower, false); + return work_queue(HPWORK, &dev->irqwork, mrf24j40_irqworker, (FAR void *)dev, 0); +} diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c new file mode 100644 index 0000000000..1f23d2188a --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c @@ -0,0 +1,530 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c + * + * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "mrf24j40.h" +#include "mrf24j40_reg.h" +#include "mrf24j40_getset.h" +#include "mrf24j40_regops.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_allones[8] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/**************************************************************************** + * Radio Interface Functions + ****************************************************************************/ + +int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_radiocb_s *radiocb) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + + DEBUGASSERT(dev != NULL); + dev->radiocb = radiocb; + return OK; +} + +/**************************************************************************** + * Function: mrf24j40_txnotify + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * radio - Reference to the radio driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int mrf24j40_txnotify(FAR struct ieee802154_radio_s *radio, bool gts) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + + if (gts) + { + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ + + if (work_available(&dev->gts_pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->gts_pollwork, mrf24j40_dopoll_gts, dev, 0); + } + } + else + { + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ + + if (work_available(&dev->csma_pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->csma_pollwork, mrf24j40_dopoll_csma, dev, 0); + } + } + + return OK; +} + +/**************************************************************************** + * Function: mrf24j40_txdelayed + * + * Description: + * Transmit a packet without regard to supeframe structure after a certain + * number of symbols. This function is used to send Data Request responses. + * It can also be used to send data immediately if the delay is set to 0. + * + * Parameters: + * radio - Reference to the radio driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_txdesc_s *txdesc, + uint32_t symboldelay) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + uint8_t reg; + + /* Get exclusive access to the radio device */ + + if (sem_wait(&dev->exclsem) != 0) + { + return -EINTR; + } + + /* There should never be more than one of these transactions at once. */ + + DEBUGASSERT(!dev->txdelayed_busy); + + dev->txdelayed_desc = txdesc; + dev->txdelayed_busy = true; + + /* Disable the TX norm interrupt and clear it */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_TXNIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + /* If after disabling the interrupt, the irqworker is not scheduled, there + * are no interrupts to worry about. However, if there is work scheduled, + * we need to process it before going any further. + * FIXME: I think this could be done cleaner. + */ + + if (!work_available(&dev->irqwork)) + { + sem_post(&dev->exclsem); + mrf24j40_irqworker((FAR void *)dev); + + /* Get exclusive access to the radio device */ + + if (sem_wait(&dev->exclsem) != 0) + { + return -EINTR; + } + } + + if (dev->csma_busy) + { + dev->reschedule_csma = true; + } + + mrf24j40_norm_setup(dev, txdesc->frame, false); + + if (symboldelay == 0) + { + mrf24j40_norm_trigger(dev); + } + else + { + mrf24j40_mactimer(dev, symboldelay); + } + + sem_post(&dev->exclsem); + + return OK; +} + +int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + struct ieee802154_cca_s cca; + int reg; + + /* Software reset */ + + mrf24j40_setreg(dev->spi, MRF24J40_SOFTRST , 0x07); /* 00000111 Reset */ + while(mrf24j40_getreg(dev->spi, MRF24J40_SOFTRST) & 0x07); + + /* Apply recommended settings */ + + mrf24j40_setreg(dev->spi, MRF24J40_PACON2 , 0x98); /* 10011000 Enable FIFO (default), TXONTS=6 (recommended), TXONT<8:7>=0 */ + mrf24j40_setreg(dev->spi, MRF24J40_TXSTBL , 0x95); /* 10010101 set the SIFS period. RFSTBL=9, MSIFS=5, aMinSIFSPeriod=14 (min 12) */ + mrf24j40_setreg(dev->spi, MRF24J40_TXPEND , 0x7C); /* 01111100 set the LIFS period, MLIFS=1Fh=31 aMinLIFSPeriod=40 (min 40) */ + mrf24j40_setreg(dev->spi, MRF24J40_TXTIME , 0x30); /* 00110000 set the turnaround time, TURNTIME=3 aTurnAroundTime=12 */ + mrf24j40_setreg(dev->spi, MRF24J40_RFCON1 , 0x02); /* 00000010 VCO optimization, recommended value */ + mrf24j40_setreg(dev->spi, MRF24J40_RFCON2 , 0x80); /* 10000000 Enable PLL */ + mrf24j40_setreg(dev->spi, MRF24J40_RFCON6 , 0x90); /* 10010000 TX filter enable, fast 20M recovery, No bat monitor*/ + mrf24j40_setreg(dev->spi, MRF24J40_RFCON7 , 0x80); /* 10000000 Sleep clock on internal 100 kHz */ + mrf24j40_setreg(dev->spi, MRF24J40_RFCON8 , 0x10); /* 00010000 VCO control bit, as recommended */ + mrf24j40_setreg(dev->spi, MRF24J40_SLPCON1, 0x01); /* 00000001 no CLKOUT, default divisor */ + mrf24j40_setreg(dev->spi, MRF24J40_BBREG6 , 0x40); /* 01000000 Append RSSI to rx packets */ + + /* Set this in reset since it can exist for all device modes. See pg 101 */ + + mrf24j40_setreg(dev->spi, MRF24J40_FRMOFFSET, 0x15); + + /* For now, we want to always just have the frame pending bit set when + * acknowledging a Data Request command. The standard says that the coordinator + * can do this if it needs time to figure out whether it has data or not + */ + + mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK); + + /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0xC8 to set the main oscillator + * (20 MHz) start-up timer value. + */ + + mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0xC8); + + /* Set WAKETIME to recommended value for 100kHz SLPCLK Source */ + + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2); + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00); + + /* Enable the SLPIF and WAKEIF flags */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg &= ~(MRF24J40_INTCON_SLPIE | MRF24J40_INTCON_WAKEIE); + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + dev->rxenabled = false; + + mrf24j40_setchannel(dev, 11); + mrf24j40_setpanid(dev, g_allones); + mrf24j40_setsaddr(dev, g_allones); + mrf24j40_seteaddr(dev, g_allones); + + dev->max_frame_waittime = MRF24J40_DEFAULT_MAX_FRAME_WAITTIME; + dev->bsn = 0; + + /* Default device params */ + + cca.use_ed = 1; + cca.use_cs = 0; + cca.edth = 0x60; /* CCA mode ED, no carrier sense, recommenced ED threshold -69 dBm */ + mrf24j40_setcca(dev, &cca); + + mrf24j40_setrxmode(dev, MRF24J40_RXMODE_NORMAL); + + mrf24j40_settxpower(dev, 0); /*16. Set transmitter power .*/ + + mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); + + return OK; +} + +int mrf24j40_getattr(FAR struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + FAR union ieee802154_attr_u *attrval) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + int ret; + + switch (attr) + { + case IEEE802154_ATTR_MAC_EADDR: + { + memcpy(&attrval->mac.eaddr[0], &dev->addr.eaddr[0], 8); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME: + { + attrval->mac.max_frame_waittime = dev->max_frame_waittime; + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_PHY_SYMBOL_DURATION: + { + attrval->phy.symdur_picosec = MRF24J40_SYMBOL_DURATION_PS; + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_PHY_CHAN: + { + attrval->phy.chan = dev->chan; + ret = IEEE802154_STATUS_SUCCESS; + } + + default: + ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; + } + + return ret; +} + +int mrf24j40_setattr(FAR struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + FAR const union ieee802154_attr_u *attrval) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + int ret; + + switch (attr) + { + case IEEE802154_ATTR_MAC_PANID: + { + mrf24j40_setpanid(dev, attrval->mac.panid); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_MAC_SADDR: + { + mrf24j40_setsaddr(dev, attrval->mac.saddr); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_MAC_EADDR: + { + mrf24j40_seteaddr(dev, attrval->mac.eaddr); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_MAC_COORD_SADDR: + { + mrf24j40_setcoordsaddr(dev, attrval->mac.coordsaddr); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_MAC_COORD_EADDR: + { + mrf24j40_setcoordeaddr(dev, attrval->mac.coordeaddr); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + case IEEE802154_ATTR_MAC_PROMISCUOUS_MODE: + { + if (attrval->mac.promisc_mode) + { + mrf24j40_setrxmode(dev, MRF24J40_RXMODE_PROMISC); + } + else + { + mrf24j40_setrxmode(dev, MRF24J40_RXMODE_NORMAL); + } + + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + + case IEEE802154_ATTR_PHY_CHAN: + { + mrf24j40_setchannel(dev, attrval->phy.chan); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + + default: + ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; + break; + } + return ret; +} + +int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio, + FAR const struct ieee802154_superframespec_s *sfspec, + FAR struct ieee802154_beaconframe_s *beacon) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + int reg; + + if (sfspec->pancoord) + { + /* Set the PANCOORD (RXMCR 0x00<3>) bit = 1to configure as PAN coordinator */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR); + reg |= MRF24J40_RXMCR_PANCOORD; + mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg); + + /* Set the SLOTTED (TXMCR 0x11<5>) bit = 1 to use Slotted CSMA-CA mode */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); + reg |= MRF24J40_TXMCR_SLOTTED; + mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); + + /* Load the beacon frame into the TXBFIFO (0x080-0x0FF). */ + + mrf24j40_setup_fifo(dev, beacon->bf_data, beacon->bf_len, MRF24J40_BEACON_FIFO); + + /* The radio layer is responsible for setting the BSN. */ + + dev->bsn = 0; + mrf24j40_setreg(dev->spi, MRF24J40_BEACON_FIFO + 4, dev->bsn++); + + /* Set the TXBMSK (TXBCON1 0x25<7>) bit = 1 to mask the beacon interrupt + * mask + */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1); + reg |= MRF24J40_TXBCON1_TXBMSK; + mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg); + + /* Set INTL (WAKECON 0x22<5:0>) value to 0x03. */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_WAKECON); + reg &= ~MRF24J40_WAKECON_INTL; + reg |= 0x03 & MRF24J40_WAKECON_INTL; + mrf24j40_setreg(dev->spi, MRF24J40_WAKECON, reg); + + /* Program the CAP end slot (ESLOTG1 0x13<3:0>) value. */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_ESLOTG1); + reg &= ~MRF24J40_ESLOTG1_CAP; + reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP; + mrf24j40_setreg(dev->spi, MRF24J40_ESLOTG1, reg); + + /* TODO: Add GTS related code. See pg 100 of datasheet */ + + mrf24j40_setorder(dev, sfspec->beaconorder, sfspec->sforder); + } + else + { + return -ENOTTY; + } + + return OK; +} + +int mrf24j40_beaconupdate(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_beaconframe_s *beacon) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + + mrf24j40_setup_fifo(dev, beacon->bf_data, beacon->bf_len, MRF24J40_BEACON_FIFO); + mrf24j40_beacon_trigger(dev); + + return OK; +} + +int mrf24j40_beaconstop(FAR struct ieee802154_radio_s *radio) +{ + return -ENOTTY; +} + +int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio, + FAR const struct ieee802154_superframespec_s *sfspec) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + int reg; + + /* If we are operating on a beacon-enabled network, use slotted CSMA */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); + if (sfspec->beaconorder < 15) + { + reg |= MRF24J40_TXMCR_SLOTTED; + } + else + { + reg &= ~MRF24J40_TXMCR_SLOTTED; + } + mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); + + mrf24j40_setorder(dev, sfspec->beaconorder, sfspec->sforder); + + /* Program the CAP end slot (ESLOTG1 0x13<3:0>) value. */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_ESLOTG1); + reg &= ~MRF24J40_ESLOTG1_CAP; + reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP; + mrf24j40_setreg(dev->spi, MRF24J40_ESLOTG1, reg); + + return OK; +} diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h new file mode 100644 index 0000000000..3eb678c603 --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_WIRELESS_IEEE802154_MRF24J40_RADIF_H +#define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_RADIF_H + +int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_radiocb_s *radiocb); + +int mrf24j40_reset(FAR struct ieee802154_radio_s *radio); + +int mrf24j40_getattr(FAR struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + FAR union ieee802154_attr_u *attrval); + +int mrf24j40_setattr(FAR struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + FAR const union ieee802154_attr_u *attrval); + +int mrf24j40_txnotify(FAR struct ieee802154_radio_s *radio, bool gts); + +int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_txdesc_s *txdesc, + uint32_t symboldelay); + + +int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio, + FAR const struct ieee802154_superframespec_s *sfspec, + FAR struct ieee802154_beaconframe_s *beacon); + +int mrf24j40_beaconupdate(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_beaconframe_s *beacon); + +int mrf24j40_beaconstop(FAR struct ieee802154_radio_s *radio); + +int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio, + FAR const struct ieee802154_superframespec_s *sfspec); + +#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_RADIF_H */ \ No newline at end of file diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_reg.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_reg.h new file mode 100644 index 0000000000..4d45545b27 --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_reg.h @@ -0,0 +1,286 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_reg.h + * + * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* MRF24J40 Registers *******************************************************/ + +#define MRF24J40_RXMCR 0x00 +#define MRF24J40_PANIDL 0x01 +#define MRF24J40_PANIDH 0x02 +#define MRF24J40_SADRL 0x03 +#define MRF24J40_SADRH 0x04 +#define MRF24J40_EADR0 0x05 +#define MRF24J40_EADR1 0x06 +#define MRF24J40_EADR2 0x07 +#define MRF24J40_EADR3 0x08 +#define MRF24J40_EADR4 0x09 +#define MRF24J40_EADR5 0x0A +#define MRF24J40_EADR6 0x0B +#define MRF24J40_EADR7 0x0C +#define MRF24J40_RXFLUSH 0x0D +#define MRF24J40_ORDER 0x10 +#define MRF24J40_TXMCR 0x11 +#define MRF24J40_ACKTMOUT 0x12 +#define MRF24J40_ESLOTG1 0x13 +#define MRF24J40_SYMTICKL 0x14 +#define MRF24J40_SYMTICKH 0x15 +#define MRF24J40_PACON0 0x16 +#define MRF24J40_PACON1 0x17 +#define MRF24J40_PACON2 0x18 +#define MRF24J40_TXBCON0 0x1A +#define MRF24J40_TXNCON 0x1B +#define MRF24J40_TXG1CON 0x1C +#define MRF24J40_TXG2CON 0x1D +#define MRF24J40_ESLOTG23 0x1E +#define MRF24J40_ESLOTG45 0x1F +#define MRF24J40_ESLOTG67 0x20 +#define MRF24J40_TXPEND 0x21 +#define MRF24J40_WAKECON 0x22 +#define MRF24J40_FRMOFFSET 0x23 +#define MRF24J40_TXSTAT 0x24 +#define MRF24J40_TXBCON1 0x25 +#define MRF24J40_GATECLK 0x26 +#define MRF24J40_TXTIME 0x27 +#define MRF24J40_HSYMTMRL 0x28 +#define MRF24J40_HSYMTMRH 0x29 +#define MRF24J40_SOFTRST 0x2A +#define MRF24J40_SECCON0 0x2C +#define MRF24J40_SECCON1 0x2C +#define MRF24J40_TXSTBL 0x2E +#define MRF24J40_RXSR 0x30 +#define MRF24J40_INTSTAT 0x31 +#define MRF24J40_INTCON 0x32 +#define MRF24J40_GPIO 0x33 +#define MRF24J40_TRISGPIO 0x34 +#define MRF24J40_SLPACK 0x35 +#define MRF24J40_RFCTL 0x36 +#define MRF24J40_SECCR2 0x37 +#define MRF24J40_BBREG0 0x38 +#define MRF24J40_BBREG1 0x39 +#define MRF24J40_BBREG2 0x3A +#define MRF24J40_BBREG3 0x3B +#define MRF24J40_BBREG4 0x3C +#define MRF24J40_BBREG6 0x3E +#define MRF24J40_CCAEDTH 0x3F + +#define MRF24J40_FIFO_BASE 0x80000000 +#define MRF24J40_LONGREG_BASE 0x80000200 +#define MRF24J40_RXBUF_BASE 0x80000300 + +#define MRF24J40_TXNORM_FIFO (MRF24J40_FIFO_BASE + 0x000) +#define MRF24J40_BEACON_FIFO (MRF24J40_FIFO_BASE + 0x080) +#define MRF24J40_GTS1_FIFO (MRF24J40_FIFO_BASE + 0x100) +#define MRF24J40_GTS2_FIFO (MRF24J40_FIFO_BASE + 0x180) + +#define MRF24J40_RFCON0 (MRF24J40_LONGREG_BASE + 0x00) +#define MRF24J40_RFCON1 (MRF24J40_LONGREG_BASE + 0x01) +#define MRF24J40_RFCON2 (MRF24J40_LONGREG_BASE + 0x02) +#define MRF24J40_RFCON3 (MRF24J40_LONGREG_BASE + 0x03) +#define MRF24J40_RFCON5 (MRF24J40_LONGREG_BASE + 0x05) +#define MRF24J40_RFCON6 (MRF24J40_LONGREG_BASE + 0x06) +#define MRF24J40_RFCON7 (MRF24J40_LONGREG_BASE + 0x07) +#define MRF24J40_RFCON8 (MRF24J40_LONGREG_BASE + 0x08) +#define MRF24J40_SLPCAL0 (MRF24J40_LONGREG_BASE + 0x09) +#define MRF24J40_SLPCAL1 (MRF24J40_LONGREG_BASE + 0x0A) +#define MRF24J40_SLPCAL2 (MRF24J40_LONGREG_BASE + 0x0B) +#define MRF24J40_RFSTATE (MRF24J40_LONGREG_BASE + 0x0F) +#define MRF24J40_RSSI (MRF24J40_LONGREG_BASE + 0x10) +#define MRF24J40_SLPCON0 (MRF24J40_LONGREG_BASE + 0x11) +#define MRF24J40_SLPCON1 (MRF24J40_LONGREG_BASE + 0x20) +#define MRF24J40_WAKETIMEL (MRF24J40_LONGREG_BASE + 0x22) +#define MRF24J40_WAKETIMEH (MRF24J40_LONGREG_BASE + 0x23) +#define MRF24J40_REMCNTL (MRF24J40_LONGREG_BASE + 0x24) +#define MRF24J40_REMCNTH (MRF24J40_LONGREG_BASE + 0x25) +#define MRF24J40_MAINCNT0 (MRF24J40_LONGREG_BASE + 0x26) +#define MRF24J40_MAINCNT1 (MRF24J40_LONGREG_BASE + 0x27) +#define MRF24J40_MAINCNT2 (MRF24J40_LONGREG_BASE + 0x28) +#define MRF24J40_MAINCNT3 (MRF24J40_LONGREG_BASE + 0x29) +#define MRF24J40_TESTMODE (MRF24J40_LONGREG_BASE + 0x2F) +#define MRF24J40_ASSOEADR0 (MRF24J40_LONGREG_BASE + 0x30) +#define MRF24J40_ASSOEADR1 (MRF24J40_LONGREG_BASE + 0x31) +#define MRF24J40_ASSOEADR2 (MRF24J40_LONGREG_BASE + 0x32) +#define MRF24J40_ASSOEADR3 (MRF24J40_LONGREG_BASE + 0x33) +#define MRF24J40_ASSOEADR4 (MRF24J40_LONGREG_BASE + 0x34) +#define MRF24J40_ASSOEADR5 (MRF24J40_LONGREG_BASE + 0x35) +#define MRF24J40_ASSOEADR6 (MRF24J40_LONGREG_BASE + 0x36) +#define MRF24J40_ASSOEADR7 (MRF24J40_LONGREG_BASE + 0x37) +#define MRF24J40_ASSOSADR0 (MRF24J40_LONGREG_BASE + 0x38) +#define MRF24J40_ASSOSADR1 (MRF24J40_LONGREG_BASE + 0x39) +#define MRF24J40_UPNONCE0 (MRF24J40_LONGREG_BASE + 0x40) +#define MRF24J40_UPNONCE1 (MRF24J40_LONGREG_BASE + 0x41) +#define MRF24J40_UPNONCE2 (MRF24J40_LONGREG_BASE + 0x42) +#define MRF24J40_UPNONCE3 (MRF24J40_LONGREG_BASE + 0x43) +#define MRF24J40_UPNONCE4 (MRF24J40_LONGREG_BASE + 0x44) +#define MRF24J40_UPNONCE5 (MRF24J40_LONGREG_BASE + 0x45) +#define MRF24J40_UPNONCE6 (MRF24J40_LONGREG_BASE + 0x46) +#define MRF24J40_UPNONCE7 (MRF24J40_LONGREG_BASE + 0x47) +#define MRF24J40_UPNONCE8 (MRF24J40_LONGREG_BASE + 0x48) +#define MRF24J40_UPNONCE9 (MRF24J40_LONGREG_BASE + 0x49) +#define MRF24J40_UPNONCE10 (MRF24J40_LONGREG_BASE + 0x4A) +#define MRF24J40_UPNONCE11 (MRF24J40_LONGREG_BASE + 0x4B) +#define MRF24J40_UPNONCE12 (MRF24J40_LONGREG_BASE + 0x4C) + +/* INTSTAT bits */ + +#define MRF24J40_INTSTAT_TXNIF (1 << 0) +#define MRF24J40_INTSTAT_TXG1IF (1 << 1) +#define MRF24J40_INTSTAT_TXG2IF (1 << 2) +#define MRF24J40_INTSTAT_RXIF (1 << 3) +#define MRF24J40_INTSTAT_SECIF (1 << 4) +#define MRF24J40_INTSTAT_HSYMTMRIF (1 << 5) +#define MRF24J40_INTSTAT_WAKEIF (1 << 6) +#define MRF24J40_INTSTAT_SLPIF (1 << 7) + +/* RXMCR bits */ + +#define MRF24J40_RXMCR_PROMI (1 << 0) /* Enable promisc mode (rx all valid packets) */ +#define MRF24J40_RXMCR_ERRPKT 0x02 /* Do not check CRC */ +#define MRF24J40_RXMCR_COORD 0x04 /* Enable coordinator mode ??? DIFFERENCE ??? - not used in datasheet! */ +#define MRF24J40_RXMCR_PANCOORD 0x08 /* Enable PAN coordinator mode ??? DIFFERENCE ??? */ +#define MRF24J40_RXMCR_NOACKRSP 0x20 /* Enable auto ACK when a packet is rxed */ + +/* TXMCR bits */ + +#define MRF24J40_TXMCR_CSMABF0 (1 << 0) +#define MRF24J40_TXMCR_CSMABF1 0x02 +#define MRF24J40_TXMCR_CSMABF2 0x04 +#define MRF24J40_TXMCR_MACMINBE0 0x08 +#define MRF24J40_TXMCR_MACMINBE1 0x10 +#define MRF24J40_TXMCR_SLOTTED 0x20 +#define MRF24J40_TXMCR_BATLIFEXT 0x40 +#define MRF24J40_TXMCR_NOCSMA 0x80 + +/* ACKTMOUT bits */ + +#define MRF24J40_ACKTMOUT_MAWD 0xEF +#define MRF24J40_ACKTMOUT_DRPACK 0x80 + +/* INTCON bits */ + +#define MRF24J40_INTCON_SLPIE 0x80 +#define MRF24J40_INTCON_WAKEIE 0x40 +#define MRF24J40_INTCON_HSYMTMRIE 0x20 +#define MRF24J40_INTCON_SECIE 0x10 +#define MRF24J40_INTCON_RXIE 0x08 +#define MRF24J40_INTCON_TXG2IE 0x04 +#define MRF24J40_INTCON_TXG1IE 0x02 +#define MRF24J40_INTCON_TXNIE (1 << 0) + +/* BBREG1 bits */ + +#define MRF24J40_BBREG1_RXDECINV 0x04 /* Enable/Disable packet reception */ + +/* BBREG2 bits */ + +#define MRF24J40_BBREG2_CCAMODE_ED 0x80 +#define MRF24J40_BBREG2_CCAMODE_CS 0x40 + +/* TXNCON bits */ + +#define MRF24J40_TXNCON_TXNTRIG (1 << 0) /* Trigger packet tx, automatically cleared */ +#define MRF24J40_TXNCON_TXNSECEN 0x02 /* Enable security */ +#define MRF24J40_TXNCON_TXNACKREQ 0x04 /* An ACK is requested for this pkt */ +#define MRF24J40_TXNCON_INDIRECT 0x08 /* Activate indirect tx bit (for coordinators) */ +#define MRF24J40_TXNCON_FPSTAT 0x10 /* Status of the frame pending big in txed acks */ + +/* TXSTAT bits */ + +#define MRF24J40_TXSTAT_TXNSTAT (1 << 0) +#define MRF24J40_TXSTAT_TXG1STAT (1 << 1) +#define MRF24J40_TXSTAT_TXG2STAT (1 << 2) +#define MRF24J40_TXSTAT_CCAFAIL (1 << 5) +#define MRF24J40_TXSTAT_X_SHIFT 6 +#define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT) + +/* TXBCON0 bits */ + +#define MRF24J40_TXBCON0_TXBTRIG 0x01 +#define MRF24J40_TXBCON0_TXBSECEN 0x02 + +/* TXBCON1 bits */ + +#define MRF24J40_TXBCON1_RSSINUM 0x30 +#define MRF24J40_TXBCON1_NWU_BCN 0x40 +#define MRF24J40_TXBCON1_TXBMSK 0x80 + +/* WAKECON bits */ + +#define MRF24J40_WAKECON_INTL 0x3F +#define MRF24J40_WAKECON_REGWAKE 0x40 +#define MRF24J40_WAKECON_IMMWAKE 0x80 + +/* WAKECON bits */ + +#define MRF24J40_WAKECON_INTL 0x3F +#define MRF24J40_WAKECON_REGWAKE 0x40 +#define MRF24J40_WAKECON_IMMWAKE 0x80 + +/* ESLOTG1 bits */ + +#define MRF24J40_ESLOTG1_CAP 0x0F +#define MRF24J40_ESLOTG1_GTS1 0xF0 + +/* SLPCAL2 bits */ + +#define MRF24J40_SLPCAL2_SLPCAL 0x0F +#define MRF24J40_SLPCAL2_SLPCALEN 0x10 +#define MRF24J40_SLPCAL2_SLPCALRDY 0x80 + +/* RFCON7 bits */ + +#define MRF24J40_RFCON7_SEL_32KHZ 0x40 +#define MRF24J40_RFCON7_SEL_100KHZ 0x80 + +/* SLPACK bits */ + +#define MRF24J40_SLPACK_WAKECNT0_6 0x7F +#define MRF24J40_SLPACK_SLPACK 0x80 + +/* RXFLUSH bits */ + +#define MRF24J40_RXFLUSH_RXFLUSH 0x01 +#define MRF24J40_RXFLUSH_BCNONLY 0x02 +#define MRF24J40_RXFLUSH_DATAONLY 0x04 +#define MRF24J40_RXFLUSH_CMDONLY 0x08 +#define MRF24J40_RXFLUSH_WAKEPAD 0x20 +#define MRF24J40_RXFLUSH_WAKEPOL 0x40 + +#define MRF24J40_RXFLUSH_SHIFT_RXFLUSH 0 +#define MRF24J40_RXFLUSH_SHIFT_BCNONLY 1 +#define MRF24J40_RXFLUSH_SHIFT_DATAONLY 2 +#define MRF24J40_RXFLUSH_SHIFT_CMDONLY 3 +#define MRF24J40_RXFLUSH_SHIFT_WAKEPAD 5 +#define MRF24J40_RXFLUSH_SHIFT_WAKEPOL 6 diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.c new file mode 100644 index 0000000000..16fb2b0fcf --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.c @@ -0,0 +1,189 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.c + + * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "mrf24j40.h" +#include "mrf24j40_regops.h" + +/**************************************************************************** + * Internal Driver Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mrf24j40_setreg + * + * Description: + * Define the value of an MRF24J40 device register + * + ****************************************************************************/ + +void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr, uint8_t val) +{ + uint8_t buf[3]; + int len; + + if (!(addr&0x80000000)) + { + addr &= 0x3F; /* 6-bit address */ + addr <<= 1; + addr |= 0x01; /* writing */ + buf[0] = addr; + len = 1; + } + else + { + addr &= 0x3FF; /* 10-bit address */ + addr <<= 5; + addr |= 0x8010; /* writing long */ + buf[0] = (addr >> 8); + buf[1] = (addr & 0xFF); + len = 2; + } + + buf[len++] = val; + + mrf24j40_spi_lock(spi); + SPI_SELECT(spi, SPIDEV_IEEE802154(0), true); + SPI_SNDBLOCK(spi, buf, len); + SPI_SELECT(spi, SPIDEV_IEEE802154(0), false); + mrf24j40_spi_unlock(spi); +} + +/**************************************************************************** + * Name: mrf24j40_getreg + * + * Description: + * Return the value of an MRF24J40 device register* + * + ****************************************************************************/ + +uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr) +{ + uint8_t buf[3]; + uint8_t rx[3]; + int len; + + if (!(addr&0x80000000)) + { + /* 6-bit address */ + + addr &= 0x3F; + addr <<= 1; + buf[0] = addr; + len = 1; + } + else + { + /* 10-bit address */ + + addr &= 0x3FF; + addr <<= 5; + addr |= 0x8000; + buf[0] = (addr >> 8); + buf[1] = (addr & 0xFF); + len = 2; + } + + buf[len++] = 0xFF; /* dummy */ + + mrf24j40_spi_lock (spi); + SPI_SELECT (spi, SPIDEV_IEEE802154(0), true); + SPI_EXCHANGE (spi, buf, rx, len); + SPI_SELECT (spi, SPIDEV_IEEE802154(0), false); + mrf24j40_spi_unlock(spi); + + /* wlinfo("r[%04X]=%02X\n", addr, rx[len - 1]); */ + return rx[len - 1]; +} + +/**************************************************************************** + * Name: mrf24j40_regdump + * + * Description: + * Display the value of all registers. + * + ****************************************************************************/ + +int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev) +{ + uint32_t i; + char buf[4+16*3+2+1]; + int len = 0; + + wlinfo("Short regs:\n"); + + for (i = 0; i < 0x40; i++) + { + if ((i & 15) == 0) + { + len=sprintf(buf, "%02x: ",i&0xFF); + } + + len += sprintf(buf+len, "%02x ", mrf24j40_getreg(dev->spi, i)); + if ((i & 15) == 15) + { + sprintf(buf+len, "\n"); + wlinfo("%s", buf); + } + } + + wlinfo("Long regs:\n"); + + for (i = 0x80000200; i < 0x80000250; i++) + { + if ((i & 15) == 0) + { + len=sprintf(buf, "%02x: ",i&0xFF); + } + + len += sprintf(buf+len, "%02x ", mrf24j40_getreg(dev->spi, i)); + if ((i & 15) == 15) + { + sprintf(buf+len, "\n"); + wlinfo("%s", buf); + } + } + + return 0; +} diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.h new file mode 100644 index 0000000000..b70cf41762 --- /dev/null +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/mrf24j40/mrf24j40_regops.h + * + * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_WIRELESS_IEEE802154_MRF24J40_REGOPS_H +#define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_REGOPS_H + +void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr, uint8_t val); + +uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr); + +int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev); + +#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_REGOPS_H */ \ No newline at end of file From bbf37a0db80f0f465062017477c229bf27a36223 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 12:38:39 -0400 Subject: [PATCH 08/11] drivers/wireless/ieee802154/mrf24j40: Fixes issue with non-beacon enabled mode --- .../wireless/ieee802154/mrf24j40/mrf24j40.c | 22 ++++++++++++++----- .../ieee802154/mrf24j40/mrf24j40_radif.c | 10 --------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c index 9dd7e7ddc1..94e5b7e2df 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c @@ -242,6 +242,8 @@ void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, uint8_t so) uint32_t maincnt = 0; uint32_t slpcal = 0; + wlinfo("bo: %d, so: %d\n", bo, so); + /* Calibrate the Sleep Clock (SLPCLK) frequency. Refer to Section 3.15.1.2 * “Sleep Clock Calibration”. */ @@ -277,12 +279,22 @@ void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, uint8_t so) slpcal |= (mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL1) << 8); slpcal |= ((mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) << 16) & 0x0F); - /* Program the Beacon Interval into the Main Counter, MAINCNT (0x229<1:0>, - * 0x228, 0x227, 0x226), and Remain Counter, REMCNT (0x225, 0x224), - * according to BO and SO values. Refer to Section 3.15.1.3 “Sleep Mode - * Counters” - */ + /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0xC8 to set the main oscillator + * (20 MHz) start-up timer value. + */ + mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0xC8); + + /* Set WAKETIME to recommended value for 100kHz SLPCLK Source */ + + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2); + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00); + + /* Program the Beacon Interval into the Main Counter, MAINCNT (0x229<1:0>, + * 0x228, 0x227, 0x226), and Remain Counter, REMCNT (0x225, 0x224), + * according to BO and SO values. Refer to Section 3.15.1.3 “Sleep Mode + * Counters” + */ mrf24j40_setreg(dev->spi, MRF24J40_REMCNTL, (MRF24J40_REMCNT & 0xFF)); mrf24j40_setreg(dev->spi, MRF24J40_REMCNTH, ((MRF24J40_REMCNT >> 8) & 0xFF)); diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c index 1f23d2188a..ae6df003f5 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c @@ -258,16 +258,6 @@ int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK); - /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0xC8 to set the main oscillator - * (20 MHz) start-up timer value. - */ - - mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0xC8); - - /* Set WAKETIME to recommended value for 100kHz SLPCLK Source */ - - mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2); - mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00); /* Enable the SLPIF and WAKEIF flags */ From fce023b1460eca8b8f0d23b178e8d977b01b25ea Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 13:04:27 -0400 Subject: [PATCH 09/11] wireless/ieee802154: Removes trailing whitespace --- wireless/ieee802154/mac802154_assoc.c | 2 +- wireless/ieee802154/mac802154_poll.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index 42ee5c4618..c5448ca1fb 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -867,7 +867,7 @@ static void mac802154_assoctimeout(FAR void *arg) * this work, so that we make sure if the frame we were waiting for was just * received, we don't timeout */ - + if (!work_available(&priv->rx_work)) { work_queue(MAC802154_WORK, &priv->timer_work, mac802154_assoctimeout, priv, 0); diff --git a/wireless/ieee802154/mac802154_poll.c b/wireless/ieee802154/mac802154_poll.c index 3271a8f92a..a7d61f4a0d 100644 --- a/wireless/ieee802154/mac802154_poll.c +++ b/wireless/ieee802154/mac802154_poll.c @@ -270,7 +270,7 @@ void mac802154_polltimeout(FAR void *arg) * this work, so that we make sure if the frame we were waiting for was just * received, we don't timeout */ - + if (!work_available(&priv->rx_work)) { work_queue(MAC802154_WORK, &priv->timer_work, mac802154_polltimeout, priv, 0); From 6e680bb9670c9233319ec29287af1e8d0c584a76 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 19:45:29 -0400 Subject: [PATCH 10/11] ieee802154: Fixes warning for unused variable --- wireless/ieee802154/mac802154_ioctl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wireless/ieee802154/mac802154_ioctl.c b/wireless/ieee802154/mac802154_ioctl.c index 20ab2557fd..75269b2648 100644 --- a/wireless/ieee802154/mac802154_ioctl.c +++ b/wireless/ieee802154/mac802154_ioctl.c @@ -74,14 +74,12 @@ int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) { - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; int ret = -EINVAL; FAR union ieee802154_macarg_u *macarg = (FAR union ieee802154_macarg_u *)((uintptr_t)arg); - DEBUGASSERT(priv != NULL); + DEBUGASSERT(mac != NULL); /* Check for IOCTLs aimed at the IEEE802.15.4 MAC layer */ From 7ff2f90247de2706549c3ddc33dd57d9dc3727eb Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Mon, 10 Jul 2017 19:47:02 -0400 Subject: [PATCH 11/11] configs/clicker2-stm32/mrf24j40-mac: Updates stack size to 2048 to avoid random stack overflows when logging is enabled --- configs/clicker2-stm32/mrf24j40-mac/defconfig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/configs/clicker2-stm32/mrf24j40-mac/defconfig b/configs/clicker2-stm32/mrf24j40-mac/defconfig index 00e30e6183..109b2bc704 100644 --- a/configs/clicker2-stm32/mrf24j40-mac/defconfig +++ b/configs/clicker2-stm32/mrf24j40-mac/defconfig @@ -1,12 +1,11 @@ -# CONFIG_NSH_CMDOPT_DF_H is not set -CONFIG_ARCH_BOARD_CLICKER2_STM32=y +CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="clicker2-stm32" +CONFIG_ARCH_BOARD_CLICKER2_STM32=y CONFIG_ARCH_BUTTONS=y -CONFIG_ARCH_CHIP_STM32=y CONFIG_ARCH_CHIP_STM32F407VG=y +CONFIG_ARCH_CHIP_STM32=y CONFIG_ARCH_IRQBUTTONS=y CONFIG_ARCH_STACKDUMP=y -CONFIG_ARCH="arm" CONFIG_BOARD_INITIALIZE=y CONFIG_BOARD_LOOPSPERMSEC=16717 CONFIG_BUILTIN=y @@ -17,8 +16,9 @@ CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y CONFIG_EXAMPLES_NSH=y CONFIG_FS_PROCFS=y CONFIG_FS_WRITABLE=y -CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_HAVE_CXX=y +CONFIG_IDLETHREAD_STACKSIZE=2048 CONFIG_IEEE802154_I8SAK=y CONFIG_IEEE802154_MACDEV=y CONFIG_IEEE802154_MRF24J40=y @@ -30,6 +30,7 @@ CONFIG_NFILE_DESCRIPTORS=8 CONFIG_NFILE_STREAMS=8 CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y +# CONFIG_NSH_CMDOPT_DF_H is not set CONFIG_NSH_DISABLE_GET=y CONFIG_NSH_DISABLE_IFUPDOWN=y CONFIG_NSH_DISABLE_PUT=y @@ -44,8 +45,8 @@ CONFIG_RAM_SIZE=131072 CONFIG_RAM_START=0x20000000 CONFIG_RAW_BINARY=y CONFIG_RR_INTERVAL=200 -CONFIG_SCHED_HPWORK=y CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_HPWORK=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y CONFIG_START_YEAR=2013