Merge branch 'beacon802154'

This commit is contained in:
Gregory Nutt 2017-07-20 08:36:13 -06:00
commit 4fde6fc654
50 changed files with 4630 additions and 3593 deletions

View File

@ -35,4 +35,11 @@ config CLICKER2_STM32_MB2_BEE
---help--- ---help---
Enable support for MRF24J40 BEE on mikroBUS2 Enable support for MRF24J40 BEE on mikroBUS2
config CLICKER2_STM32_MRF24J40LH_VERBOSE
bool "Verbose MRF24J40 lowerhalf"
default n
depends on IEEE802154_MRF24J40 && DEBUG_WIRELESS_INFO
---help---
Enable verbose syslog for MRF24J40 lowerhalf
endif # ARCH_BOARD_CLICKER2_STM32 endif # ARCH_BOARD_CLICKER2_STM32

View File

@ -1,12 +1,11 @@
# CONFIG_NSH_CMDOPT_DF_H is not set CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD_CLICKER2_STM32=y
CONFIG_ARCH_BOARD="clicker2-stm32" CONFIG_ARCH_BOARD="clicker2-stm32"
CONFIG_ARCH_BOARD_CLICKER2_STM32=y
CONFIG_ARCH_BUTTONS=y CONFIG_ARCH_BUTTONS=y
CONFIG_ARCH_CHIP_STM32=y
CONFIG_ARCH_CHIP_STM32F407VG=y CONFIG_ARCH_CHIP_STM32F407VG=y
CONFIG_ARCH_CHIP_STM32=y
CONFIG_ARCH_IRQBUTTONS=y CONFIG_ARCH_IRQBUTTONS=y
CONFIG_ARCH_STACKDUMP=y CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH="arm"
CONFIG_BOARD_INITIALIZE=y CONFIG_BOARD_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=16717 CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y CONFIG_BUILTIN=y
@ -17,8 +16,9 @@ CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y
CONFIG_EXAMPLES_NSH=y CONFIG_EXAMPLES_NSH=y
CONFIG_FS_PROCFS=y CONFIG_FS_PROCFS=y
CONFIG_FS_WRITABLE=y CONFIG_FS_WRITABLE=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_HAVE_CXX=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_IEEE802154_I8SAK=y CONFIG_IEEE802154_I8SAK=y
CONFIG_IEEE802154_MACDEV=y CONFIG_IEEE802154_MACDEV=y
CONFIG_IEEE802154_MRF24J40=y CONFIG_IEEE802154_MRF24J40=y
@ -30,6 +30,7 @@ CONFIG_NFILE_DESCRIPTORS=8
CONFIG_NFILE_STREAMS=8 CONFIG_NFILE_STREAMS=8
CONFIG_NSH_ARCHINIT=y CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_BUILTIN_APPS=y
# CONFIG_NSH_CMDOPT_DF_H is not set
CONFIG_NSH_DISABLE_GET=y CONFIG_NSH_DISABLE_GET=y
CONFIG_NSH_DISABLE_IFUPDOWN=y CONFIG_NSH_DISABLE_IFUPDOWN=y
CONFIG_NSH_DISABLE_PUT=y CONFIG_NSH_DISABLE_PUT=y
@ -44,8 +45,8 @@ CONFIG_RAM_SIZE=131072
CONFIG_RAM_START=0x20000000 CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200 CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_HPWORKPRIORITY=192 CONFIG_SCHED_HPWORKPRIORITY=192
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y CONFIG_SDCLONE_DISABLE=y
CONFIG_START_YEAR=2013 CONFIG_START_YEAR=2013

View File

@ -75,6 +75,11 @@ ifneq ($(CONFIG_DEBUG_NOOPT),y)
ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer
endif endif
# enable precise stack overflow tracking
ifeq ($(CONFIG_ARMV7M_STACKCHECK),y)
INSTRUMENTATIONDEFINES = -finstrument-functions -ffixed-r10
endif
ARCHCFLAGS = -fno-builtin ARCHCFLAGS = -fno-builtin
ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti
ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
@ -82,9 +87,9 @@ ARCHWARNINGSXX = -Wall -Wshadow -Wundef
ARCHDEFINES = ARCHDEFINES =
ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 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) 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) CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES)
AFLAGS = $(CFLAGS) -D__ASSEMBLY__ AFLAGS = $(CFLAGS) -D__ASSEMBLY__

View File

@ -193,9 +193,12 @@ static void stm32_enable_irq(FAR const struct mrf24j40_lower_s *lower,
DEBUGASSERT(priv != NULL && (priv->handler != NULL || !state)); 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 */ /* Attach and enable, or detach and disable */
wlinfo("state:%d\n", (int)state);
if (state) if (state)
{ {
(void)stm32_gpiosetevent(priv->intcfg, true, true, true, (void)stm32_gpiosetevent(priv->intcfg, true, true, true,

View File

@ -11,10 +11,14 @@ config IEEE802154_MRF24J40
---help--- ---help---
This selection enables support for the Microchip MRF24J40 device. This selection enables support for the Microchip MRF24J40 device.
source drivers/wireless/ieee802154/mrf24j40/Kconfig
config IEEE802154_AT86RF233 config IEEE802154_AT86RF233
bool "ATMEL RF233 IEEE 802.15.4 transceiver" bool "ATMEL RF233 IEEE 802.15.4 transceiver"
default n default n
---help--- ---help---
This selection enables support for the Atmel RF233 device. This selection enables support for the Atmel RF233 device.
source drivers/wireless/ieee802154/at86rf23x/Kconfig
endif # DRIVERS_IEEE802154 endif # DRIVERS_IEEE802154

View File

@ -1,7 +1,7 @@
############################################################################ ############################################################################
# drivers/ieee802154/Make.defs # drivers/ieee802154/Make.defs
# #
# Copyright (C) 2016 Gregory Nutt. All rights reserved. # Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org> # Author: Gregory Nutt <gnutt@nuttx.org>
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -41,15 +41,10 @@ ifeq ($(CONFIG_DRIVERS_IEEE802154),y)
# Include IEEE 802.15.4 drivers into the build # Include IEEE 802.15.4 drivers into the build
ifeq ($(CONFIG_IEEE802154_MRF24J40),y) include wireless$(DELIM)ieee802154$(DELIM)mrf24j40$(DELIM)Make.defs
CSRCS += mrf24j40.c include wireless$(DELIM)ieee802154$(DELIM)at86rf23x$(DELIM)Make.defs
endif
ifeq ($(CONFIG_IEEE802154_AT86RF233),y) # Include common IEEE 802.15.4 build support
CSRCS += at86rf23x.c
endif
# Include IEEE 802.15.4 build support
DEPPATH += --dep-path wireless$(DELIM)ieee802154 DEPPATH += --dep-path wireless$(DELIM)ieee802154
VPATH += :wireless$(DELIM)ieee802154 VPATH += :wireless$(DELIM)ieee802154

View File

@ -0,0 +1,8 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
if IEEE802154_AT86RF233
endif # IEEE802154_AT86RF233

View File

@ -0,0 +1,48 @@
############################################################################
# drivers/ieee802154/at86rf23x/Make.defs
#
# Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# 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.
#
############################################################################
# Include AT86RF23x drivers into the build
ifeq ($(CONFIG_IEEE802154_AT86RF233),y)
CSRCS += at86rf23x.c
# Include AT86RF23x build support
DEPPATH += --dep-path wireless$(DELIM)ieee802154$(DELIM)at86rf23x
VPATH += :wireless$(DELIM)ieee802154$(DELIM)at86rf23x
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)wireless$(DELIM)ieee802154$(DELIM)at86rf23x}
endif # CONFIG_IEEE802154_AT86RF233

View File

@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* drivers/wireless/ieee802154/at86rf23x.c * drivers/wireless/ieee802154/at86rf23x/at86rf23x.c
* *
* Copyright (C) 2016 Matt Poppe. All rights reserved. * Copyright (C) 2016 Matt Poppe. All rights reserved.
* Author: Matt Poppe <matt@poppe.me> * Author: Matt Poppe <matt@poppe.me>
@ -996,19 +996,20 @@ static int at86rf23x_gettxpower(FAR struct ieee802154_radio_s *ieee,
reg = at86rf23x_getreg(dev->spi, RF23X_REG_TXPWR); reg = at86rf23x_getreg(dev->spi, RF23X_REG_TXPWR);
switch (reg) switch (reg)
{ {
case RF23X_TXPWR_POS_4: case RF23X_TXPWR_POS_4:
*txpwr = 0; *txpwr = 0;
break; break;
case RF23X_TXPWR_POS_3_7: case RF23X_TXPWR_POS_3_7:
*txpwr =0;
break;
case RF23X_TXPWR_POS_3_4:
*txpwr = 0; *txpwr = 0;
break; break;
case RF23X_TXPWR_POS_3_4: case RF23X_TXPWR_POS_3:
*txpwr = 0;
break;
case RF23X_TXPWR_POS_3:
*txpwr = 0; *txpwr = 0;
break; break;
@ -1016,23 +1017,23 @@ static int at86rf23x_gettxpower(FAR struct ieee802154_radio_s *ieee,
*txpwr = 0; *txpwr = 0;
break; break;
case RF23X_TXPWR_POS_2: case RF23X_TXPWR_POS_2:
*txpwr = 0; *txpwr = 0;
break; break;
case RF23X_TXPWR_POS_1: case RF23X_TXPWR_POS_1:
*txpwr = 0; *txpwr = 0;
break; break;
case RF23X_TXPWR_0: case RF23X_TXPWR_0:
*txpwr = 0; *txpwr =0;
break; break;
case RF23X_TXPWR_NEG_1: case RF23X_TXPWR_NEG_1:
*txpwr = 1000; *txpwr = 1000;
break; break;
case RF23X_TXPWR_NEG_2: case RF23X_TXPWR_NEG_2:
*txpwr = 2000; *txpwr = 2000;
break; break;
@ -1071,11 +1072,11 @@ static int at86rf23x_gettxpower(FAR struct ieee802154_radio_s *ieee,
* Configures if energy detection is used or carrier sense. The base * Configures if energy detection is used or carrier sense. The base
* measurement is configured here as well * measurement is configured here as well
* *
*
****************************************************************************/ ****************************************************************************/
static int at86rf23x_setcca(FAR struct ieee802154_radio_s *ieee, static
FAR struct ieee802154_cca_s *cca) int at86rf23x_setcca(FAR struct ieee802154_radio_s *ieee,
FAR struct ieee802154_cca_s *cca)
{ {
FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee;

View File

@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* drivers/wireless/ieee802154/at86rf23x.c * drivers/wireless/ieee802154/at86rf23x/at86rf23x.h
* *
* Copyright (C) 2016 Matt Poppe. All rights reserved. * Copyright (C) 2016 Matt Poppe. All rights reserved.
* Author: Matt Poppe <matt@poppe.me> * Author: Matt Poppe <matt@poppe.me>
@ -33,8 +33,8 @@
* *
****************************************************************************/ ****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE802154_AT86RF23X_H #ifndef __DRIVERS_WIRELESS_IEEE802154_AT86RF23X_AT86RF23X_H
#define __DRIVERS_WIRELESS_IEEE802154_AT86RF23X_H #define __DRIVERS_WIRELESS_IEEE802154_AT86RF23X_AT86RF23X_H
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@ -218,4 +218,4 @@
#define RF23X_IRQ_MASK_DEFAULT (RF23X_IRQ_MASK_TRX_END) #define RF23X_IRQ_MASK_DEFAULT (RF23X_IRQ_MASK_TRX_END)
#endif /* __DRIVERS_WIRELESS_IEEE802154_AT86RF23X_H */ #endif /* __DRIVERS_WIRELESS_IEEE802154_AT86RF23X_AT86RF23X_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
if IEEE802154_MRF24J40
endif # IEEE802154_MRF24J40

View File

@ -0,0 +1,49 @@
############################################################################
# drivers/ieee802154/mrf24j40/Make.defs
#
# Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# 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.
#
############################################################################
ifeq ($(CONFIG_IEEE802154_MRF24J40),y)
# Include MRF24J40 files into the build
CSRCS += mrf24j40_getset.c mrf24j40_interrupt.c mrf24j40_radif.c
CSRCS += mrf24j40_regops.c mrf24j40.c
# Include MRF24J40 build support
DEPPATH += --dep-path wireless$(DELIM)ieee802154$(DELIM)mrf24j40
VPATH += :wireless$(DELIM)ieee802154$(DELIM)mrf24j40
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)wireless$(DELIM)ieee802154$(DELIM)mrf24j40}
endif # CONFIG_IEEE802154_MRF24J40

View File

@ -0,0 +1,473 @@
/****************************************************************************
* drivers/wireless/ieee802154/mrf24j40/mrf24j40.c
*
* Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved.
* Copyright (C) 2017 Verge Inc. All rights reserved.
* Author: Sebastien Lorquet <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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 <nuttx/config.h>
#include <assert.h>
#include <debug.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <semaphore.h>
#include <sys/types.h>
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/semaphore.h>
#include <nuttx/mm/iob.h>
#include <nuttx/wireless/ieee802154/mrf24j40.h>
#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include "mrf24j40.h"
#include "mrf24j40_reg.h"
#include "mrf24j40_radif.h"
#include "mrf24j40_getset.h"
#include "mrf24j40_regops.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#if 0
static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev,
FAR uint8_t *energy);
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mrf24j40_energydetect
*
* Description:
* Measure the RSSI level for the current channel.
*
****************************************************************************/
#if 0
static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev,
FAR uint8_t *energy)
{
uint8_t reg;
/* Manually enable the LNA*/
mrf24j40_setpamode(dev, MRF24J40_PA_ED);
/* Set RSSI average duration to 8 symbols */
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1);
reg |= 0x30;
mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg);
/* 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_setpamode(dev, MRF24J40_PA_AUTO);
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: mrf24j40_dopoll_csma
*
* Description:
* This function is called in order to preform an out-of-sequence TX poll.
* This is done:
*
* 1. After completion of a transmission (mrf24j40_txdone_csma),
* 2. When new TX data is available (mrf24j40_txnotify), and
* 3. After a TX timeout to restart the sending process
* (mrf24j40_txtimeout_csma).
*
* Parameters:
* radio - Reference to the radio driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
void mrf24j40_dopoll_csma(FAR void *arg)
{
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg;
int len = 0;
/* Get exclusive access to the driver */
while (sem_wait(&dev->exclsem) != 0) { }
/* If this a CSMA transaction and we have room in the CSMA fifo */
if (!dev->csma_busy)
{
wlinfo("Polling for frame\n");
len = dev->radiocb->poll(dev->radiocb, false, &dev->csma_desc);
if (len > 0)
{
wlinfo("Frame received. Frame length: %d\n", len);
/* Now the txdesc is in use */
dev->csma_busy = 1;
/* Setup the transaction on the device in the CSMA FIFO */
mrf24j40_norm_setup(dev, dev->csma_desc->frame, true);
mrf24j40_norm_trigger(dev);
}
}
sem_post(&dev->exclsem);
}
/****************************************************************************
* Function: mrf24j40_dopoll_gts
*
* Description:
* This function is called in order to preform an out-of-sequence TX poll.
* This is done:
*
* 1. After completion of a transmission (mrf24j40_txdone_gts),
* 2. When new TX data is available (mrf24j40_txnotify), and
* 3. After a TX timeout to restart the sending process
* (mrf24j40_txtimeout_gts).
*
* Parameters:
* arg - Reference to the radio driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
void mrf24j40_dopoll_gts(FAR void *arg)
{
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg;
int gts = 0;
int len = 0;
/* Get exclusive access to the driver */
while (sem_wait(&dev->exclsem) != 0) { }
for (gts = 0; gts < MRF24J40_GTS_SLOTS; gts++)
{
if (!dev->gts_busy[gts])
{
len = dev->radiocb->poll(dev->radiocb, true, &dev->gts_desc[gts]);
if (len > 0)
{
/* Now the txdesc is in use */
dev->gts_busy[gts]= 1;
/* Setup the transaction on the device in the open GTS FIFO */
mrf24j40_gts_setup(dev, gts, dev->gts_desc[gts]->frame);
}
}
}
sem_post(&dev->exclsem);
}
/****************************************************************************
* Name: mrf24j40_norm_setup
*
* Description:
* Setup a transaction in the normal TX FIFO
*
****************************************************************************/
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
*
****************************************************************************/
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
*
****************************************************************************/
void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev)
{
uint8_t reg;
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON0);
reg |= MRF24J40_TXBCON0_TXBTRIG;
mrf24j40_setreg(dev->spi, MRF24J40_TXBCON0, reg);
}
/****************************************************************************
* Name: mrf24j40_gts_setup
*
* Description:
* Setup a GTS transaction in one of the GTS FIFOs
*
****************************************************************************/
void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo,
FAR struct iob_s *frame)
{
}
/****************************************************************************
* Name: mrf24j40_setup_fifo
*
* Description:
*
****************************************************************************/
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 */
int i;
uint16_t frame_ctrl;
/* Analyze frame control to compute header length */
frame_ctrl = buf[0];
frame_ctrl |= (buf[1] << 8);
if ((frame_ctrl & IEEE802154_FRAMECTRL_DADDR)== IEEE802154_ADDRMODE_SHORT)
{
hlen += 2 + 2; /* Destination PAN + shortaddr */
}
else if ((frame_ctrl & IEEE802154_FRAMECTRL_DADDR) == IEEE802154_ADDRMODE_EXTENDED)
{
hlen += 2 + 8; /* Destination PAN + extaddr */
}
if (!(frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP))
{
hlen += 2; /* No PAN compression, source PAN is different from dest PAN */
}
if ((frame_ctrl & IEEE802154_FRAMECTRL_SADDR)== IEEE802154_ADDRMODE_SHORT)
{
hlen += 2; /* Source saddr */
}
else if ((frame_ctrl & IEEE802154_FRAMECTRL_SADDR) == IEEE802154_ADDRMODE_EXTENDED)
{
hlen += 8; /* Ext saddr */
}
/* Header len, 0, TODO for security modes */
mrf24j40_setreg(dev->spi, fifo_addr++, hlen);
/* Frame length */
mrf24j40_setreg(dev->spi, fifo_addr++, length);
/* Frame data */
for (i = 0; i < length; i++)
{
mrf24j40_setreg(dev->spi, fifo_addr++, buf[i]);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mrf24j40_init
*
* Description:
* Return an mrf24j40 device for use by other drivers.
*
****************************************************************************/
FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi,
FAR const struct mrf24j40_lower_s *lower)
{
FAR struct mrf24j40_radio_s *dev;
dev = kmm_zalloc(sizeof(struct mrf24j40_radio_s));
if (dev == NULL)
{
return NULL;
}
/* Attach irq */
if (lower->attach(lower, mrf24j40_interrupt, dev) != OK)
{
#if 0
free(dev);
#endif
return NULL;
}
/* Allow exclusive access to the privmac struct */
sem_init(&dev->exclsem, 0, 1);
dev->radio.bind = mrf24j40_bind;
dev->radio.reset = mrf24j40_reset;
dev->radio.getattr = mrf24j40_getattr;
dev->radio.setattr = mrf24j40_setattr;
dev->radio.txnotify = mrf24j40_txnotify;
dev->radio.txdelayed = mrf24j40_txdelayed;
dev->radio.rxenable = mrf24j40_rxenable;
dev->radio.beaconstart = mrf24j40_beaconstart;
dev->radio.beaconupdate = mrf24j40_beaconupdate;
dev->radio.beaconstop = mrf24j40_beaconstop;
dev->radio.sfupdate = mrf24j40_sfupdate;
dev->lower = lower;
dev->spi = spi;
mrf24j40_reset(&dev->radio);
dev->lower->enable(dev->lower, true);
return &dev->radio;
}

View File

@ -0,0 +1,227 @@
/****************************************************************************
* drivers/wireless/ieee802154/mrf24j40/mrf24j40.h
*
* Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved.
* Author: Sebastien Lorquet <sebastien@lorquet.fr>
*
* 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_H
#define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <semaphore.h>
#include <nuttx/wqueue.h>
#include <nuttx/spi/spi.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MRF24J40_GTS_SLOTS 2
/* 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
/* 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
/* Clock configuration macros */
#define MRF24J40_BEACONINTERVAL_NSEC(beaconorder) \
(IEEE802154_BASE_SUPERFRAME_DURATION * (1 << beaconorder) * (16 * 1000))
#define MRF24J40_SUPERFRAMEDURATION_NSEC(sforder) \
(IEEE802154_BASE_SUPERFRAME_DURATION * (1 << sforder) * (16 * 1000))
/* Configuration *************************************************************/
#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
/****************************************************************************
* Public 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 */
uint32_t slpclkper; /* Sleep clock period (nanoseconds) */
/* 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];
};
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* 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);
}
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg);
void mrf24j40_irqworker(FAR void *arg);
void mrf24j40_dopoll_csma(FAR void *arg);
void mrf24j40_dopoll_gts(FAR void *arg);
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);
#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H */

View File

@ -0,0 +1,499 @@
/****************************************************************************
* 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 <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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 <nuttx/config.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/arch.h>
#include "mrf24j40.h"
#include "mrf24j40_reg.h"
#include "mrf24j40_regops.h"
#include "mrf24j40_getset.h"
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mrf24j40_resetrfsm
*
* Description:
* Reset the RF state machine. Required at boot, after channel change,
* and probably after PA settings.
*
****************************************************************************/
static void 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);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
uint8_t reg;
/* 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 OK;
}
/****************************************************************************
* 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;
}
/****************************************************************************
* Name: mrf24j40_setpamode
*
* Description:
* Control the external LNA/PA on the MRF24J40MB/MC/MD/ME modules
* GPIO 1: PA enable
* GPIO 2: LNA enable
* GPIO 3: PA power enable (not required on MB)
****************************************************************************/
int mrf24j40_setpamode(FAR struct mrf24j40_radio_s *dev, int mode)
{
if (!dev->paenabled)
{
return OK;
}
if (mode == MRF24J40_PA_AUTO)
{
mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x08);
mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x08);
mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x0F);
}
else if (mode == MRF24J40_PA_ED)
{
mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x08);
mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x0F);
mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x0C);
}
else if (mode == MRF24J40_PA_SLEEP)
{
mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x08);
mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x0F);
mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x00);
}
else
{
return -EINVAL;
}
mrf24j40_resetrfsm(dev);
return OK;
}

View File

@ -0,0 +1,66 @@
/****************************************************************************
* 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 <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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);
int mrf24j40_setpamode(FAR struct mrf24j40_radio_s *dev, int mode);
#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_GETSET_H */

View File

@ -0,0 +1,443 @@
/****************************************************************************
* 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 <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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 <nuttx/config.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/mm/iob.h>
#include <nuttx/wireless/ieee802154/mrf24j40.h>
#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
if (dev->devmode != IEEE802154_DEVMODE_ENDPOINT)
{
/* 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);
wlinfo("Beacon triggered. BSN: 0x%02X\n", dev->bsn-1);
}
}
/* 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);
}

View File

@ -0,0 +1,749 @@
/****************************************************************************
* 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 <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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 <nuttx/config.h>
#include <assert.h>
#include <debug.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <semaphore.h>
#include <nuttx/arch.h>
#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include "mrf24j40.h"
#include "mrf24j40_reg.h"
#include "mrf24j40_getset.h"
#include "mrf24j40_regops.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols);
static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo,
uint8_t so);
static void mrf24j40_slpclkcal(FAR struct mrf24j40_radio_s *dev);
/****************************************************************************
* Private Data
****************************************************************************/
static const uint8_t g_allones[8] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols)
{
uint16_t nhalfsym;
uint8_t reg;
nhalfsym = (numsymbols << 1);
/* Disable the interrupt, clear the timer count */
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
reg |= MRF24J40_INTCON_HSYMTMRIE;
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, 0x00);
mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, 0x00);
reg &= ~MRF24J40_INTCON_HSYMTMRIE;
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
/* Set the timer count and enable interrupts */
reg = (nhalfsym & 0xFF);
mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, reg);
reg = (nhalfsym >> 8) & 0xFF;
mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, reg);
}
/****************************************************************************
* Name: mrf24j40_setorder
*
* Description:
* Configures the timers and sets the ORDER register
****************************************************************************/
static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo,
uint8_t so)
{
uint32_t bi = MRF24J40_BEACONINTERVAL_NSEC(bo);
uint32_t sfduration = MRF24J40_SUPERFRAMEDURATION_NSEC(so);
uint32_t maincnt;
uint32_t remcnt;
wlinfo("bo: %d, so: %d\n", bo, so);
if (bo < 15)
{
if (dev->devmode == IEEE802154_DEVMODE_ENDPOINT)
{
wlinfo("Configuring sleep for inactive period\n");
maincnt = (bi - sfduration) / dev->slpclkper;
remcnt = ((bi - sfduration) - (maincnt * dev->slpclkper)) / 50;
}
else
{
wlinfo("Configuring sleep for beacon interval\n");
maincnt = bi / dev->slpclkper;
remcnt = (bi - (maincnt * dev->slpclkper)) / 50;
}
wlinfo("MAINCNT: %lu, REMCNT: %lu\n", maincnt, remcnt);
/* Program 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, (remcnt & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_REMCNTH, ((remcnt >> 8) & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT0, (maincnt & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT1, ((maincnt >> 8) & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT2, ((maincnt >> 16) & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT3, ((maincnt >> 24) & 0x03));
}
/* Configure the BO (ORDER 0x10<7:4>) and SO (ORDER 0x10<3:0>) values.
* After configuring BO and SO, the beacon frame will be sent immediately.
*/
mrf24j40_setreg(dev->spi, MRF24J40_ORDER, ((bo << 4) & 0xF0) | (so & 0x0F));
}
static void mrf24j40_slpclkcal(FAR struct mrf24j40_radio_s *dev)
{
uint8_t reg;
/* Select the source of SLPCLK (internal 100kHz) */
mrf24j40_setreg(dev->spi, MRF24J40_RFCON7, MRF24J40_RFCON7_SEL_100KHZ);
/* If the Sleep Clock Selection, SLPCLKSEL (0x207<7:6), is the internal
* oscillator (100 kHz), set SLPCLKDIV to a minimum value of 0x01.
*/
mrf24j40_setreg(dev->spi, MRF24J40_SLPCON1,
0x01 | MRF24J40_SLPCON1_CLKOUT_DISABLED);
/* Begin calibration by setting the SLPCALEN bit (SLPCAL2 0x20B<4>) to
* 1. Sixteen samples of the SLPCLK are counted and stored in the
* SLPCAL register. No need to mask, this is the only writable bit
*/
mrf24j40_setreg(dev->spi, MRF24J40_SLPCAL2, MRF24J40_SLPCAL2_SLPCALEN);
/* Calibration is complete when the SLPCALRDY bit (SLPCAL2 0x20B<7>) is
* set to 1.
*/
while (!(mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) &
MRF24J40_SLPCAL2_SLPCALRDY))
{
up_udelay(1);
}
reg = mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL0);
dev->slpclkper = reg;
reg = mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL1);
dev->slpclkper |= (reg << 8);
reg = mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) & 0x0F;
dev->slpclkper |= (reg << 16);
dev->slpclkper = (dev->slpclkper * 50 / 16);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/* 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;
}
/****************************************************************************
* Name: mrf24j40_rxenable
*
* Description:
* Enable/Disable receiver.
*
****************************************************************************/
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;
dev->rxenabled = enable;
if (enable)
{
/* Disable packet reception. See pg. 109 of datasheet */
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, MRF24J40_BBREG1_RXDECINV);
/* Enable rx int */
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
reg &= ~MRF24J40_INTCON_RXIE;
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
/* Purge the RX buffer */
reg = mrf24j40_getreg(dev->spi, MRF24J40_RXFLUSH);
reg |= MRF24J40_RXFLUSH_RXFLUSH;
mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, reg);
/* Re-enable packet reception. See pg. 109 of datasheet */
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0);
}
else
{
/* Disable rx int */
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
reg |= MRF24J40_INTCON_RXIE;
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
}
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_BBREG6 , 0x40); /* 01000000 Append RSSI to rx packets */
/* Calibrate the Sleep Clock (SLPCLK) frequency. Refer to Section 3.15.1.2
* Sleep Clock Calibration.
*/
mrf24j40_slpclkcal(dev);
/* 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 WAKETIME to recommended value for 100kHz SLPCLK Source.
*
* NOTE!!!: The datasheet specifies that WAKETIME > WAKECNT. It appears that
* it is even sensitive to the order in which you set WAKECNT and WAKETIME.
* Meaning, if you set WAKECNT first and it goes higher than WAKETIME, and
* then raise WAKETIME above WAKECNT, the device will not function correctly.
* Therefore, be careful when changing these registers
*/
mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2);
mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00);
/* Set WAKECNT (SLPACK 0x35<6:0>) value = 0x5F to set the main oscillator
* (20 MHz) start-up timer value.
*/
mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, (0x0C8 & MRF24J40_SLPACK_WAKECNT0_6));
reg = mrf24j40_getreg(dev->spi, MRF24J40_RFCTL);
reg &= ~MRF24J40_RFCTRL_WAKECNT7_8;
reg |= ((0x0C8 >> 7) & 0x03) << 3;
mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg);
/* 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);
mrf24j40_setorder(dev, 15, 15);
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_setpamode(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 = IEEE802154_STATUS_SUCCESS;;
switch (attr)
{
case IEEE802154_ATTR_MAC_PANID:
{
mrf24j40_setpanid(dev, attrval->mac.panid);
}
break;
case IEEE802154_ATTR_MAC_SADDR:
{
mrf24j40_setsaddr(dev, attrval->mac.saddr);
}
break;
case IEEE802154_ATTR_MAC_EADDR:
{
mrf24j40_seteaddr(dev, attrval->mac.eaddr);
}
break;
case IEEE802154_ATTR_MAC_COORD_SADDR:
{
mrf24j40_setcoordsaddr(dev, attrval->mac.coordsaddr);
}
break;
case IEEE802154_ATTR_MAC_COORD_EADDR:
{
mrf24j40_setcoordeaddr(dev, attrval->mac.coordeaddr);
}
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);
}
}
break;
case IEEE802154_ATTR_PHY_CHAN:
{
mrf24j40_setchannel(dev, attrval->phy.chan);
}
break;
case IEEE802154_ATTR_MAC_DEVMODE:
{
mrf24j40_setdevmode(dev, attrval->mac.devmode);
}
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;
if (dev->devmode == IEEE802154_DEVMODE_ENDPOINT)
{
mrf24j40_setreg(dev->spi, MRF24J40_FRMOFFSET, 0x15);
}
else
{
mrf24j40_setreg(dev->spi, MRF24J40_FRMOFFSET, 0x00);
}
}
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;
}

View File

@ -0,0 +1,72 @@
/****************************************************************************
* drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h
*
* Copyright (C) 2017 Verge Inc. All rights reserved.
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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_rxenable(FAR struct ieee802154_radio_s *radio, bool enable);
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 */

View File

@ -1,8 +1,10 @@
/**************************************************************************** /****************************************************************************
* drivers/wireless/ieee802154/mrf24j40.h * drivers/wireless/ieee802154/mrf24j40/mrf24j40_reg.h
* *
* Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved.
* Copyright (C) 2017 Verge Inc. All rights reserved.
* Author: Sebastien Lorquet <sebastien@lorquet.fr> * Author: Sebastien Lorquet <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -33,8 +35,8 @@
* *
****************************************************************************/ ****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H #ifndef __DRIVERS_WIRELESS_IEEE802154_MRF24J40_REG_H
#define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H #define __DRIVERS_WIRELESS_IEEE802154_MRF24J40_REG_H
/* MRF24J40 Registers *******************************************************/ /* MRF24J40 Registers *******************************************************/
@ -226,6 +228,11 @@
#define MRF24J40_TXSTAT_X_SHIFT 6 #define MRF24J40_TXSTAT_X_SHIFT 6
#define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT) #define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT)
/* TXBCON0 bits */
#define MRF24J40_TXBCON0_TXBTRIG 0x01
#define MRF24J40_TXBCON0_TXBSECEN 0x02
/* TXBCON1 bits */ /* TXBCON1 bits */
#define MRF24J40_TXBCON1_RSSINUM 0x30 #define MRF24J40_TXBCON1_RSSINUM 0x30
@ -265,6 +272,13 @@
#define MRF24J40_SLPACK_WAKECNT0_6 0x7F #define MRF24J40_SLPACK_WAKECNT0_6 0x7F
#define MRF24J40_SLPACK_SLPACK 0x80 #define MRF24J40_SLPACK_SLPACK 0x80
/* RFCTL bits */
#define MRF24J40_RFCTRL_RFRXMODE 0x01
#define MRF24J40_RFCTRL_RFTXMODE 0x02
#define MRF24J40_RFCTRL_RFRST 0x03
#define MRF24J40_RFCTRL_WAKECNT7_8 0x18
/* RXFLUSH bits */ /* RXFLUSH bits */
#define MRF24J40_RXFLUSH_RXFLUSH 0x01 #define MRF24J40_RXFLUSH_RXFLUSH 0x01
@ -281,4 +295,8 @@
#define MRF24J40_RXFLUSH_SHIFT_WAKEPAD 5 #define MRF24J40_RXFLUSH_SHIFT_WAKEPAD 5
#define MRF24J40_RXFLUSH_SHIFT_WAKEPOL 6 #define MRF24J40_RXFLUSH_SHIFT_WAKEPOL 6
#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H */ /* SLPCON1 bits */
#define MRF24J40_SLPCON1_CLKOUT_DISABLED 0x20
#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_REG_H */

View File

@ -0,0 +1,191 @@
/****************************************************************************
* 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 <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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 <nuttx/config.h>
#include <assert.h>
#include <debug.h>
#include <stdio.h>
#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;
}

View File

@ -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 <sebastien@lorquet.fr>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* 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 */

View File

@ -423,26 +423,30 @@ enum ieee802154_attr_e
IEEE802154_ATTR_MAC_SADDR, IEEE802154_ATTR_MAC_SADDR,
IEEE802154_ATTR_MAC_SUPERFRAME_ORDER, IEEE802154_ATTR_MAC_SUPERFRAME_ORDER,
IEEE802154_ATTR_MAC_SYNC_SYMBOL_OFFSET, IEEE802154_ATTR_MAC_SYNC_SYMBOL_OFFSET,
IEEE802154_PIB_MAC_TIMESTAMP_SUPPORT, IEEE802154_ATTR_MAC_TIMESTAMP_SUPPORT,
IEEE802154_PIB_MAC_TRANSACTION_PERSIST_TIME, IEEE802154_ATTR_MAC_TRANSACTION_PERSIST_TIME,
IEEE802154_PIB_MAC_TX_CTRL_ACTIVE_DUR, IEEE802154_ATTR_MAC_TX_CTRL_ACTIVE_DUR,
IEEE802154_PIB_MAC_TX_CTRL_PAUSE_DUR, IEEE802154_ATTR_MAC_TX_CTRL_PAUSE_DUR,
IEEE802154_PIB_MAC_TX_TOTAL_DUR, IEEE802154_ATTR_MAC_TX_TOTAL_DUR,
IEEE802154_ATTR_MAC_DEVMODE, /* Non-standard */ IEEE802154_ATTR_MAC_DEVMODE, /* Non-standard */
/* MAC Security Attributes */ /* MAC Security Attributes */
IEEE802154_PIB_MAC_KEY_TABLE = 0x70, IEEE802154_ATTR_MAC_KEY_TABLE = 0x70,
IEEE802154_PIB_MAC_DEV_TABLE, IEEE802154_ATTR_MAC_DEV_TABLE,
IEEE802154_PIB_MAC_SEC_LVL_TABLE, IEEE802154_ATTR_MAC_SEC_LVL_TABLE,
IEEE802154_PIB_MAC_FRAME_COUNTER, IEEE802154_ATTR_MAC_FRAME_COUNTER,
IEEE802154_PIB_MAC_AUTOREQ_SEC_LVL, IEEE802154_ATTR_MAC_AUTOREQ_SEC_LVL,
IEEE802154_PIB_MAC_AUTOREQ_KEY_ID_MODE, IEEE802154_ATTR_MAC_AUTOREQ_KEY_ID_MODE,
IEEE802154_PIB_MAC_AUTOREQ_KEY_SOURCE, IEEE802154_ATTR_MAC_AUTOREQ_KEY_SOURCE,
IEEE802154_PIB_MAC_AUTOREQ_KEY_INDEX, IEEE802154_ATTR_MAC_AUTOREQ_KEY_INDEX,
IEEE802154_PIB_MAC_DEFAULT_KEY_SRC, IEEE802154_ATTR_MAC_DEFAULT_KEY_SRC,
IEEE802154_PIB_MAC_PANCOORD_EXT_ADDR, IEEE802154_ATTR_MAC_PANCOORD_EXT_ADDR,
IEEE802154_PIB_MAC_PANCOORD_SHORT_ADDR, IEEE802154_ATTR_MAC_PANCOORD_SHORT_ADDR,
/* Special Attributes */
IEEE802154_ATTR_RADIO_REGDUMP = 0xF0,
}; };
/* Frame Type */ /* Frame Type */
@ -564,11 +568,10 @@ struct ieee802154_capability_info_s
struct ieee802154_superframespec_s struct ieee802154_superframespec_s
{ {
uint16_t beaconorder : 4; /* Transmission interval of beacon */ uint16_t beaconorder : 4; /* Transmission interval of beacon */
uint16_t sforder : 4; /* Length of active portion of superframe */ uint16_t sforder : 4; /* Length of active portion of superframe */
uint16_t final_capslot : 4; /* Last slot utilized by CAP */ uint16_t final_capslot : 4; /* Last slot utilized by CAP */
uint16_t ble : 1; /* Battery Life Extension (BLE) */ uint16_t ble : 1; /* Battery Life Extension (BLE) */
uint16_t reserved : 1; /* Reserved bit */
uint16_t pancoord : 1; /* 1 if beacon sent by pan coordinator */ uint16_t pancoord : 1; /* 1 if beacon sent by pan coordinator */
uint16_t assocpermit : 1; /* 1 if coordinator is accepting associaton */ uint16_t assocpermit : 1; /* 1 if coordinator is accepting associaton */
}; };
@ -593,19 +596,10 @@ struct ieee802154_pandesc_s
* in symbols */ * in symbols */
}; };
struct ieee802154_pend_addr_s struct ieee802154_pendaddr_s
{ {
union uint8_t nsaddr : 3; /* Number of short addresses pending */
{ uint8_t neaddr : 3; /* Number of extended addresses pending */
uint8_t pa_spec;
struct
{
uint8_t num_short_addr : 3; /* Number of short addresses pending */
uint8_t reserved_3 : 1; /* Reserved bit */
uint8_t num_ext_addr : 3; /* Number of extended addresses pending */
uint8_t reserved_7 : 1; /* Reserved bit */
} pa_addr;
} u;
struct ieee802154_addr_s addr[7]; /* Array of at most 7 addresses */ struct ieee802154_addr_s addr[7]; /* Array of at most 7 addresses */
}; };
@ -632,17 +626,16 @@ union ieee802154_macattr_u
bool is_assoc; bool is_assoc;
bool assocpermit; bool assocpermit;
bool auto_req; bool autoreq;
bool batt_life_ext; bool batt_life_ext;
bool gts_permit; bool gts_permit;
bool promisc_mode; bool promisc_mode;
bool rng_support; bool rng_support;
bool resp_waittime;
bool rxonidle; bool rxonidle;
bool sec_enabled; bool sec_enabled;
bool timestamp_support; bool timestamp_support;
uint32_t ack_wait_dur; uint32_t ack_waitdur;
uint8_t batt_life_ext_periods; uint8_t batt_life_ext_periods;
uint8_t max_csma_backoffs : 3; uint8_t max_csma_backoffs : 3;
uint8_t max_be : 4; uint8_t max_be : 4;
@ -656,6 +649,7 @@ union ieee802154_macattr_u
uint32_t tx_ctrl_active_dur; uint32_t tx_ctrl_active_dur;
uint32_t tx_ctrl_pause_dur; uint32_t tx_ctrl_pause_dur;
uint32_t tx_total_dur; uint32_t tx_total_dur;
uint8_t resp_waittime;
uint8_t beacon_payload[IEEE802154_ATTR_MAC_BEACON_PAYLOAD_LEN]; uint8_t beacon_payload[IEEE802154_ATTR_MAC_BEACON_PAYLOAD_LEN];
uint8_t beacon_payload_len; uint8_t beacon_payload_len;
@ -706,17 +700,17 @@ enum ieee802154_scantype_e
struct ieee802154_frame_meta_s struct ieee802154_frame_meta_s
{ {
enum ieee802154_addrmode_e srcaddr_mode; /* Source Address Mode */ enum ieee802154_addrmode_e srcmode; /* Source Address Mode */
struct ieee802154_addr_s destaddr; /* Destination Address */ struct ieee802154_addr_s destaddr; /* Destination Address */
uint8_t msdu_handle; /* Handle assoc. with MSDU */ uint8_t handle; /* User-specified handle identifier */
struct struct
{ {
uint8_t ack_tx : 1; /* Acknowledge TX? */ uint8_t ackreq : 1;
uint8_t gts_tx : 1; /* 1=GTS used for TX, 0=CAP used for TX */ uint8_t usegts : 1;
uint8_t indirect_tx : 1; /* Should indirect transmission be used? */ uint8_t indirect : 1;
} msdu_flags; } flags;
#ifdef CONFIG_IEEE802154_SECURITY #ifdef CONFIG_IEEE802154_SECURITY
/* Security information if enabled */ /* Security information if enabled */
@ -727,7 +721,7 @@ struct ieee802154_frame_meta_s
#ifdef CONFIG_IEEE802154_UWB #ifdef CONFIG_IEEE802154_UWB
/* The UWB Pulse Repetition Frequency to be used for the transmission */ /* The UWB Pulse Repetition Frequency to be used for the transmission */
enum ieee802154_uwbprf_e uwb_prf; enum ieee802154_uwbprf_e uwbprf;
/* The UWB preamble symbol repititions /* The UWB preamble symbol repititions
* Should be one of: * Should be one of:
@ -738,7 +732,7 @@ struct ieee802154_frame_meta_s
/* The UWB Data Rate to be used for the transmission */ /* The UWB Data Rate to be used for the transmission */
enum ieee802154_uwb_datarate_e data_rate; enum ieee802154_uwb_datarate_e datarate;
#endif #endif
enum ieee802154_ranging_e ranging; enum ieee802154_ranging_e ranging;
@ -1112,7 +1106,7 @@ struct ieee802154_disassoc_conf_s
* *
*****************************************************************************/ *****************************************************************************/
struct ieee802154_beaconnotify_ind_s struct ieee802154_beacon_ind_s
{ {
uint8_t bsn; /* Beacon sequence number */ uint8_t bsn; /* Beacon sequence number */
@ -1122,20 +1116,11 @@ struct ieee802154_beaconnotify_ind_s
/* Beacon pending addresses */ /* Beacon pending addresses */
struct ieee802154_pend_addr_s pend_addr; struct ieee802154_pendaddr_s pendaddr;
uint8_t payloadlength; /* # of octets contained in the beacon payload */
uint8_t sdu_length; /* Number of octets contained in the beacon uint8_t payload[IEEE802154_MAX_BEACON_PAYLOAD_LEN];
* payload of the received beacond frame */
/* Beacon payload */
uint8_t sdu[IEEE802154_MAX_BEACON_PAYLOAD_LEN];
}; };
#define SIZEOF_IEEE802154_BEACONNOTIFY_IND_S(n) \
(sizeof(struct ieee802154_beaconnotify_ind_s) \
- IEEE802154_MAX_BEACON_PAYLOAD_LEN + (n))
/***************************************************************************** /*****************************************************************************
* Primitive: MLME-COMM-STATUS.indication * Primitive: MLME-COMM-STATUS.indication
* *
@ -1265,7 +1250,7 @@ struct ieee802154_orphan_resp_s
struct ieee802154_reset_req_s struct ieee802154_reset_req_s
{ {
bool rst_pibattr; bool resetattr;
}; };
/***************************************************************************** /*****************************************************************************
@ -1538,21 +1523,21 @@ union ieee802154_notif_u
/* MLME Notifications */ /* MLME Notifications */
struct ieee802154_assoc_conf_s assocconf; struct ieee802154_assoc_conf_s assocconf;
struct ieee802154_disassoc_conf_s disassocconf; struct ieee802154_disassoc_conf_s disassocconf;
struct ieee802154_gts_conf_s gtsconf; struct ieee802154_gts_conf_s gtsconf;
struct ieee802154_rxenable_conf_s rxenableconf; struct ieee802154_rxenable_conf_s rxenableconf;
struct ieee802154_scan_conf_s scanconf; struct ieee802154_scan_conf_s scanconf;
struct ieee802154_start_conf_s startconf; struct ieee802154_start_conf_s startconf;
struct ieee802154_poll_conf_s pollconf; struct ieee802154_poll_conf_s pollconf;
struct ieee802154_assoc_ind_s assocind; struct ieee802154_assoc_ind_s assocind;
struct ieee802154_disassoc_ind_s disassocind; struct ieee802154_disassoc_ind_s disassocind;
struct ieee802154_beaconnotify_ind_s beaconnotifyind; struct ieee802154_beacon_ind_s beaconind;
struct ieee802154_gts_ind_s gtsind; struct ieee802154_gts_ind_s gtsind;
struct ieee802154_orphan_ind_s orphanind; struct ieee802154_orphan_ind_s orphanind;
struct ieee802154_commstatus_ind_s commstatusind; struct ieee802154_commstatus_ind_s commstatusind;
struct ieee802154_syncloss_ind_s synclossind; struct ieee802154_syncloss_ind_s synclossind;
}; };
struct ieee802154_notif_s struct ieee802154_notif_s

View File

@ -80,11 +80,15 @@ struct ieee802154_txdesc_s
FAR struct ieee802154_data_conf_s *conf; FAR struct ieee802154_data_conf_s *conf;
enum ieee802154_frametype_e frametype; /* Frame type. Used by MAC layer to /* Frame type. Used by MAC layer to control how tx done is handled */
* control how tx done is handled */
bool framepending; /* Did the ACK have the frame pending bit enum ieee802154_frametype_e frametype;
* bit set */
uint32_t purge_time; /* Time to purge transaction */ bool framepending; /* Did the ACK have the frame pending bit set */
uint32_t purgetime; /* Time to purge transaction */
uint8_t retrycount; /* Number of remaining retries. Set to macMaxFrameRetries
* when txdescriptor is allocated
*/
/* TODO: Add slotting information for GTS transactions */ /* TODO: Add slotting information for GTS transactions */
}; };
@ -119,20 +123,18 @@ struct ieee802154_radio_s
{ {
CODE int (*bind) (FAR struct ieee802154_radio_s *radio, CODE int (*bind) (FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_radiocb_s *radiocb); FAR struct ieee802154_radiocb_s *radiocb);
CODE int (*reset) (FAR struct ieee802154_radio_s *radio);
CODE int (*getattr) (FAR struct ieee802154_radio_s *radio,
enum ieee802154_attr_e ,
FAR union ieee802154_attr_u *attrval);
CODE int (*setattr) (FAR struct ieee802154_radio_s *radio,
enum ieee802154_attr_e ,
FAR const union ieee802154_attr_u *attrval);
CODE int (*txnotify)(FAR struct ieee802154_radio_s *radio, bool gts); CODE int (*txnotify)(FAR struct ieee802154_radio_s *radio, bool gts);
CODE int (*txdelayed)(FAR struct ieee802154_radio_s *radio, CODE int (*txdelayed)(FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_txdesc_s *txdesc, FAR struct ieee802154_txdesc_s *txdesc,
uint32_t symboldelay); uint32_t symboldelay);
CODE int (*reset_attrs) (FAR struct ieee802154_radio_s *radio);
CODE int (*get_attr) (FAR struct ieee802154_radio_s *radio,
enum ieee802154_attr_e ,
FAR union ieee802154_attr_u *attrval);
CODE int (*set_attr) (FAR struct ieee802154_radio_s *radio,
enum ieee802154_attr_e ,
FAR const union ieee802154_attr_u *attrval);
CODE int (*rxenable) (FAR struct ieee802154_radio_s *radio, bool enable); CODE int (*rxenable) (FAR struct ieee802154_radio_s *radio, bool enable);
CODE int (*req_rxenable)(FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_rxenable_req_s *req);
CODE int (*beaconstart)(FAR struct ieee802154_radio_s *radio, CODE int (*beaconstart)(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec, FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon); FAR struct ieee802154_beaconframe_s *beacon);

View File

@ -163,9 +163,9 @@ int sixlowpan_meta_data(FAR struct ieee802154_driver_s *ieee,
/* Source address mode */ /* Source address mode */
meta->srcaddr_mode = pktmeta->sextended != 0? meta->srcmode = pktmeta->sextended != 0?
IEEE802154_ADDRMODE_EXTENDED : IEEE802154_ADDRMODE_EXTENDED :
IEEE802154_ADDRMODE_SHORT; IEEE802154_ADDRMODE_SHORT;
/* Check for a broadcast destination address (all zero) */ /* Check for a broadcast destination address (all zero) */
@ -184,7 +184,7 @@ int sixlowpan_meta_data(FAR struct ieee802154_driver_s *ieee,
if (rcvrnull) if (rcvrnull)
{ {
meta->msdu_flags.ack_tx = TRUE; meta->flags.ackreq = TRUE;
} }
/* Destination address */ /* Destination address */
@ -223,7 +223,7 @@ int sixlowpan_meta_data(FAR struct ieee802154_driver_s *ieee,
* fragment of a disassembled packet. * fragment of a disassembled packet.
*/ */
meta->msdu_handle = ieee->i_msdu_handle++; meta->handle = ieee->i_msdu_handle++;
#ifdef CONFIG_IEEE802154_SECURITY #ifdef CONFIG_IEEE802154_SECURITY
# warning CONFIG_IEEE802154_SECURITY not yet supported # warning CONFIG_IEEE802154_SECURITY not yet supported

View File

@ -83,6 +83,20 @@ config MAC802154_NPANDESC
information for all unique beacons received. This is the number of unique information for all unique beacons received. This is the number of unique
descriptors that can be held before the scan cancels with LIMIT_REACHED. 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 config IEEE802154_IND_PREALLOC
int "Number of pre-allocated meta-data structures" int "Number of pre-allocated meta-data structures"
default 20 default 20

View File

@ -37,7 +37,7 @@ ifeq ($(CONFIG_WIRELESS_IEEE802154),y)
# Include IEEE 802.15.4 support # Include IEEE 802.15.4 support
CSRCS += mac802154.c mac802154_indalloc.c mac802154_assoc.c mac802154_disassoc.c CSRCS += ieee802154_indalloc.c mac802154.c mac802154_assoc.c mac802154_disassoc.c
CSRCS += mac802154_bind.c mac802154_data.c mac802154_get_mhrlen.c CSRCS += mac802154_bind.c mac802154_data.c mac802154_get_mhrlen.c
CSRCS += mac802154_getset.c mac802154_gts.c mac802154_ioctl.c CSRCS += mac802154_getset.c mac802154_gts.c mac802154_ioctl.c
CSRCS += mac802154_notif.c mac802154_orphan.c mac802154_poll.c mac802154_purge.c CSRCS += mac802154_notif.c mac802154_orphan.c mac802154_poll.c mac802154_purge.c

View File

@ -92,13 +92,6 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
static void mac802154_purge_worker(FAR void *arg); 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, static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind); FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv, static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
@ -184,7 +177,7 @@ int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
{ {
/* Unlock MAC so that other work can be done to free a notification */ /* Unlock MAC so that other work can be done to free a notification */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Take a count from the tx desc semaphore, waiting if necessary. We /* Take a count from the tx desc semaphore, waiting if necessary. We
* only return from here with an error if we are allowing interruptions * only return from here with an error if we are allowing interruptions
@ -204,7 +197,7 @@ int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
* MAC in order to ensure this happens correctly. * MAC in order to ensure this happens correctly.
*/ */
ret = mac802154_takesem(&priv->exclsem, allow_interrupt); ret = mac802154_lock(priv, allow_interrupt);
if (ret < 0) if (ret < 0)
{ {
wlwarn("WARNING: mac802154_takesem failed: %d\n", ret); wlwarn("WARNING: mac802154_takesem failed: %d\n", ret);
@ -236,6 +229,9 @@ int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
return -EINTR; return -EINTR;
} }
(*txdesc)->purgetime = 0;
(*txdesc)->retrycount = priv->maxretries;
(*txdesc)->conf = &notif->u.dataconf; (*txdesc)->conf = &notif->u.dataconf;
return OK; return OK;
} }
@ -354,9 +350,9 @@ void mac802154_createdatareq(FAR struct ieee802154_privmac_s *priv,
memcpy(&txdesc->destaddr, &coordaddr, sizeof(struct ieee802154_addr_s)); memcpy(&txdesc->destaddr, &coordaddr, sizeof(struct ieee802154_addr_s));
/* Copy the IOB reference to the descriptor */ /* Save a reference of the tx descriptor */
txdesc->frame = iob; priv->cmd_desc = txdesc;
} }
/**************************************************************************** /****************************************************************************
@ -417,9 +413,11 @@ void mac802154_updatebeacon(FAR struct ieee802154_privmac_s *priv)
IEEE802154_SETSADDRMODE(beacon->bf_data, 0, priv->addr.mode); IEEE802154_SETSADDRMODE(beacon->bf_data, 0, priv->addr.mode);
IEEE802154_SETVERSION(beacon->bf_data, 0, 1); IEEE802154_SETVERSION(beacon->bf_data, 0, 1);
/* Copy in and increment the beacon sequence number */ /* The beacon sequence number has to be taken care of by the radio layer, since
* we only want to update the whole frame when more changes than just the bsn.
*/
beacon->bf_data[beacon->bf_len++] = priv->bsn++; beacon->bf_len++;
IEEE802154_PANIDCOPY(&beacon->bf_data[beacon->bf_len], priv->addr.panid); IEEE802154_PANIDCOPY(&beacon->bf_data[beacon->bf_len], priv->addr.panid);
beacon->bf_len += IEEE802154_PANIDSIZE; beacon->bf_len += IEEE802154_PANIDSIZE;
@ -561,7 +559,7 @@ void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv,
ticks = mac802154_symtoticks(priv, symbols); ticks = mac802154_symtoticks(priv, symbols);
txdesc->purge_time = clock_systimer() + ticks; txdesc->purgetime = clock_systimer() + ticks;
/* Make sure the beacon gets updated */ /* Make sure the beacon gets updated */
@ -580,8 +578,8 @@ void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv,
if (work_available(&priv->purge_work)) if (work_available(&priv->purge_work))
{ {
//work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker, work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker,
// (FAR void *)priv, ticks); (FAR void *)priv, ticks);
} }
} }
@ -607,7 +605,7 @@ static void mac802154_purge_worker(FAR void *arg)
* signals so don't allow interruptions * signals so don't allow interruptions
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
while (1) while (1)
{ {
@ -622,12 +620,12 @@ static void mac802154_purge_worker(FAR void *arg)
break; break;
} }
/* Should probably check a little ahead and remove the transaction if it is within /* Should probably check a little ahead and remove the transaction if it is within
* a certain number of clock ticks away. There is no since in scheduling the * a certain number of clock ticks away. There is no since in scheduling the
* timer to expire in only a few ticks. * timer to expire in only a few ticks.
*/ */
if (clock_systimer() >= txdesc->purge_time) if (clock_systimer() >= txdesc->purgetime)
{ {
/* Unlink the transaction */ /* Unlink the transaction */
@ -636,8 +634,8 @@ static void mac802154_purge_worker(FAR void *arg)
/* Free the IOB, the notification, and the tx descriptor */ /* Free the IOB, the notification, and the tx descriptor */
iob_free(txdesc->frame); iob_free(txdesc->frame);
((FAR struct mac802154_notif_s *)txdesc->conf)->flink = priv->notif_free; mac802154_notif_free_locked(priv,
priv->notif_free = ((FAR struct mac802154_notif_s *)txdesc->conf); (FAR struct ieee802154_notif_s *)txdesc->conf);
mac802154_txdesc_free(priv, txdesc); mac802154_txdesc_free(priv, txdesc);
priv->beaconupdate = true; priv->beaconupdate = true;
@ -648,10 +646,12 @@ static void mac802154_purge_worker(FAR void *arg)
/* Reschedule the transaction for the next timeout */ /* Reschedule the transaction for the next timeout */
work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker, work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker,
(FAR void *)priv, txdesc->purge_time - clock_systimer()); (FAR void *)priv, txdesc->purgetime - clock_systimer());
break; break;
} }
} }
mac802154_unlock(priv);
} }
/**************************************************************************** /****************************************************************************
@ -677,7 +677,7 @@ static int mac802154_radiopoll(FAR const struct ieee802154_radiocb_s *radiocb,
/* Get exclusive access to the driver structure. Ignore any EINTR signals */ /* Get exclusive access to the driver structure. Ignore any EINTR signals */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
if (gts) if (gts)
{ {
@ -692,7 +692,7 @@ static int mac802154_radiopoll(FAR const struct ieee802154_radiocb_s *radiocb,
*txdesc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->csma_queue); *txdesc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->csma_queue);
} }
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
if (*txdesc != NULL) if (*txdesc != NULL)
{ {
@ -729,11 +729,11 @@ static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb,
* signals so don't allow interruptions * signals so don't allow interruptions
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
sq_addlast((FAR sq_entry_t *)txdesc, &priv->txdone_queue); sq_addlast((FAR sq_entry_t *)txdesc, &priv->txdone_queue);
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Schedule work with the work queue to process the completion further */ /* Schedule work with the work queue to process the completion further */
@ -760,13 +760,12 @@ static void mac802154_txdone_worker(FAR void *arg)
(FAR struct ieee802154_privmac_s *)arg; (FAR struct ieee802154_privmac_s *)arg;
FAR struct ieee802154_txdesc_s *txdesc; FAR struct ieee802154_txdesc_s *txdesc;
FAR struct ieee802154_notif_s *notif; FAR struct ieee802154_notif_s *notif;
FAR struct mac802154_notif_s *privnotif;
/* Get exclusive access to the driver structure. We don't care about any /* Get exclusive access to the driver structure. We don't care about any
* signals so don't allow interruptions * signals so don't allow interruptions
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
while (1) while (1)
{ {
@ -781,8 +780,9 @@ static void mac802154_txdone_worker(FAR void *arg)
* notification structure to make it easier to use. * notification structure to make it easier to use.
*/ */
privnotif = (FAR struct mac802154_notif_s *)txdesc->conf; notif =(FAR struct ieee802154_notif_s *)txdesc->conf;
notif = &privnotif->pub;
wlinfo("Tx status: %s\n", IEEE802154_STATUS_STRING[txdesc->conf->status]);
switch(txdesc->frametype) switch(txdesc->frametype)
{ {
@ -792,9 +792,9 @@ static void mac802154_txdone_worker(FAR void *arg)
/* Release the MAC, call the callback, get exclusive access again */ /* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_notify(priv, notif); mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
} }
break; break;
@ -857,14 +857,7 @@ static void mac802154_txdone_worker(FAR void *arg)
break; break;
default: default:
/* We can deallocate the data conf notification as it is no mac802154_notif_free_locked(priv, notif);
* longer needed. We can't use the public function here
* since we already have the MAC locked.
*/
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
priv->nnotif = 0;
break; break;
} }
} }
@ -872,13 +865,7 @@ static void mac802154_txdone_worker(FAR void *arg)
default: default:
{ {
/* We can deallocate the data conf notification as it is no longer mac802154_notif_free_locked(priv, notif);
* needed. We can't use the public function here since we already
* have the MAC locked.
*/
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
} }
break; break;
} }
@ -889,7 +876,7 @@ static void mac802154_txdone_worker(FAR void *arg)
mac802154_txdesc_free(priv, txdesc); mac802154_txdesc_free(priv, txdesc);
} }
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
} }
/**************************************************************************** /****************************************************************************
@ -920,15 +907,15 @@ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb,
* signals so if we see one, just go back to trying to get access again. * signals so if we see one, just go back to trying to get access again.
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* Push the iob onto the tail of the frame list for processing */ /* Push the iob onto the tail of the frame list for processing */
sq_addlast((FAR sq_entry_t *)ind, &priv->dataind_queue); sq_addlast((FAR sq_entry_t *)ind, &priv->dataind_queue);
wlinfo("frame received\n"); wlinfo("Frame received\n");
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Schedule work with the work queue to process the completion further */ /* Schedule work with the work queue to process the completion further */
@ -966,7 +953,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
* signals so if we see one, just go back to trying to get access again. * signals so if we see one, just go back to trying to get access again.
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* Pop the iob from the head of the frame list for processing */ /* Pop the iob from the head of the frame list for processing */
@ -974,7 +961,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
/* Once we pop off the indication, we don't need to keep the mac locked */ /* Once we pop off the indication, we don't need to keep the mac locked */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
if (ind == NULL) if (ind == NULL)
{ {
@ -1100,7 +1087,6 @@ static void mac802154_rxframe_worker(FAR void *arg)
case IEEE802154_CMD_ORPHAN_NOT: case IEEE802154_CMD_ORPHAN_NOT:
wlinfo("Orphan notif received\n"); wlinfo("Orphan notif received\n");
break; break;
break;
case IEEE802154_CMD_BEACON_REQ: case IEEE802154_CMD_BEACON_REQ:
wlinfo("Beacon request received\n"); wlinfo("Beacon request received\n");
@ -1123,7 +1109,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
case IEEE802154_FRAME_BEACON: case IEEE802154_FRAME_BEACON:
{ {
wlinfo("Beacon frame received\n"); wlinfo("Beacon frame received. BSN: 0x%02X\n", ind->dsn);
mac802154_rxbeaconframe(priv, ind); mac802154_rxbeaconframe(priv, ind);
ieee802154_ind_free(ind); ieee802154_ind_free(ind);
} }
@ -1159,7 +1145,7 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* If we are currently performing a POLL operation and we've /* If we are currently performing a POLL operation and we've
* received a data response, use the addressing information * received a data response, use the addressing information
@ -1178,7 +1164,9 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
* FIXME: Fix documentation * FIXME: Fix documentation
*/ */
if (priv->curr_op == MAC802154_OP_POLL || priv->curr_op == MAC802154_OP_ASSOC) if (priv->curr_op == MAC802154_OP_POLL ||
priv->curr_op == MAC802154_OP_ASSOC ||
priv->curr_op == MAC802154_OP_AUTOEXTRACT)
{ {
/* If we are in promiscuous mode, we need to check if the /* If we are in promiscuous mode, we need to check if the
* frame is even for us first. If the address is not ours, * frame is even for us first. If the address is not ours,
@ -1232,7 +1220,8 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
} }
/* If we've gotten this far, the frame is our extracted data. Cancel the /* If we've gotten this far, the frame is our extracted data. Cancel the
* timeout */ * timeout
*/
mac802154_timercancel(priv); mac802154_timercancel(priv);
@ -1275,7 +1264,7 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC */ /* Release the MAC */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_notify(priv, notif); mac802154_notify(priv, notif);
/* If there was data, pass it along */ /* If there was data, pass it along */
@ -1291,7 +1280,7 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
notify_with_lock: notify_with_lock:
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
notify_without_lock: notify_without_lock:
@ -1350,7 +1339,7 @@ static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* Search the list of indirect transactions to see if there are any waiting /* Search the list of indirect transactions to see if there are any waiting
* for the requesting device. * for the requesting device.
@ -1376,11 +1365,20 @@ static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
sq_rem((FAR sq_entry_t *)txdesc, &priv->indirect_queue); sq_rem((FAR sq_entry_t *)txdesc, &priv->indirect_queue);
/* NOTE: We don't do anything with the purge timeout, because
* we really don't need to. As of now, I see no disadvantage
* to just letting the timeout expire, which won't purge the
* transaction since it is no longer on the list, and then it
* will reschedule the next timeout appropriately. The logic
* otherwise may get complicated even though it may save a few
* clock cycles.
*/
/* The addresses match, send the transaction immediately */ /* The addresses match, send the transaction immediately */
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
priv->beaconupdate = true; priv->beaconupdate = true;
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return; return;
} }
} }
@ -1397,7 +1395,7 @@ static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
priv->beaconupdate = true; priv->beaconupdate = true;
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return; return;
} }
} }
@ -1503,7 +1501,7 @@ static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
txdesc->frame = iob; txdesc->frame = iob;
txdesc->frametype = IEEE802154_FRAME_DATA; txdesc->frametype = IEEE802154_FRAME_DATA;
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
} }
@ -1522,18 +1520,31 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
* signals so if we see one, just go back to trying to get access again. * signals so if we see one, just go back to trying to get access again.
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* Check if there is any reason to update the beacon */ switch (sfevent)
if (priv->beaconupdate)
{ {
mac802154_updatebeacon(priv); case IEEE802154_SFEVENT_ENDOFACTIVE:
{
#ifdef CONFIG_MAC802154_SFEVENT_VERBOSE
wlinfo("End of superframe\n");
#endif
priv->radio->beaconupdate(priv->radio, &priv->beaconframe[priv->bf_ind]); /* Check if there is any reason to update the beacon */
if (priv->beaconupdate)
{
mac802154_updatebeacon(priv);
priv->radio->beaconupdate(priv->radio, &priv->beaconframe[priv->bf_ind]);
}
}
break;
default:
break;
} }
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
} }
/**************************************************************************** /****************************************************************************
@ -1543,51 +1554,182 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
* Function called from the generic RX Frame worker to parse and handle the * Function called from the generic RX Frame worker to parse and handle the
* reception of a beacon frame. * reception of a beacon frame.
* *
* Assumptions: MAC is locked
*
****************************************************************************/ ****************************************************************************/
static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv, static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind) FAR struct ieee802154_data_ind_s *ind)
{ {
FAR struct iob_s *iob = ind->frame;
struct ieee802154_pandesc_s pandesc;
FAR struct ieee802154_txdesc_s *respdesc; FAR struct ieee802154_txdesc_s *respdesc;
uint8_t numgtsdesc; FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_beacon_ind_s *beacon;
FAR struct iob_s *iob = ind->frame;
uint8_t ngtsdesc;
uint8_t gtsdirmask; uint8_t gtsdirmask;
uint8_t npendsaddr; bool pending_saddr = false;
uint8_t npendeaddr; bool pending_eaddr = false;
int i; int i;
/* Even though we may not use the notification, we use a notification to
* hold all the parsed beacon information. Freeing the notification is quick,
* so it's worth saving a copy (If you were to parse all the info in locally,
* you would have to copy the data over in the case that you actually need
* to notify the next highest layer)
*/
mac802154_notif_alloc(priv, &notif, false);
beacon = &notif->u.beaconind;
/* Make sure there is another 2 bytes to process */
if (iob->io_len < iob->io_offset + 2)
{
goto errout;
}
/* Copy the coordinator address and channel info into the pan descriptor */ /* Copy the coordinator address and channel info into the pan descriptor */
memcpy(&pandesc.coordaddr, &ind->src, sizeof(struct ieee802154_addr_s)); memcpy(&beacon->pandesc.coordaddr, &ind->src, sizeof(struct ieee802154_addr_s));
pandesc.chan = priv->currscan.channels[priv->scanindex]; beacon->pandesc.chan = priv->currscan.channels[priv->scanindex];
pandesc.chpage = priv->currscan.chpage; beacon->pandesc.chpage = priv->currscan.chpage;
pandesc.lqi = ind->lqi; beacon->pandesc.lqi = ind->lqi;
pandesc.timestamp = ind->timestamp; beacon->pandesc.timestamp = ind->timestamp;
/* Parse the superframe specification field */ /* Parse the superframe specification field */
pandesc.sfspec.beaconorder = IEEE802154_GETBEACONORDER(iob->io_data, beacon->pandesc.sfspec.beaconorder = IEEE802154_GETBEACONORDER(iob->io_data,
iob->io_offset); iob->io_offset);
beacon->pandesc.sfspec.sforder =
IEEE802154_GETSFORDER(iob->io_data, iob->io_offset);
beacon->pandesc.sfspec.final_capslot =
IEEE802154_GETFINCAPSLOT(iob->io_data, iob->io_offset);
beacon->pandesc.sfspec.ble =
IEEE802154_GETBLE(iob->io_data, iob->io_offset);
beacon->pandesc.sfspec.pancoord =
IEEE802154_GETPANCOORD(iob->io_data, iob->io_offset);
beacon->pandesc.sfspec.assocpermit =
IEEE802154_GETASSOCPERMIT(iob->io_data, iob->io_offset);
pandesc.sfspec.sforder = IEEE802154_GETSFORDER(iob->io_data, iob->io_offset);
pandesc.sfspec.final_capslot = IEEE802154_GETFINCAPSLOT(iob->io_data,
iob->io_offset);
pandesc.sfspec.ble = IEEE802154_GETBLE(iob->io_data, iob->io_offset);
pandesc.sfspec.pancoord = IEEE802154_GETPANCOORD(iob->io_data, iob->io_offset);
pandesc.sfspec.assocpermit = IEEE802154_GETASSOCPERMIT(iob->io_data,
iob->io_offset);
iob->io_offset += 2; iob->io_offset += 2;
/* Make sure there is another byte to process (GTS Spec) */
if (iob->io_len < iob->io_offset + 1)
{
goto errout;
}
/* Parse the GTS Specification field */ /* Parse the GTS Specification field */
numgtsdesc = IEEE802154_GETGTSDESCCOUNT(iob->io_data, iob->io_offset); ngtsdesc = IEEE802154_GETGTSDESCCOUNT(iob->io_data, iob->io_offset);
pandesc.gtspermit = IEEE802154_GETGTSPERMIT(iob->io_data, iob->io_offset); beacon->pandesc.gtspermit = IEEE802154_GETGTSPERMIT(iob->io_data, iob->io_offset);
iob->io_offset++; iob->io_offset++;
/* We only need to parse the rest of the frame if we are not performing a /* If there are any GTS descriptors, handle the GTS Dir and GTS List fields */
* scan
*/ if (ngtsdesc > 0)
{
/* Make sure there is another bytes to process (GTS Direction) */
if (iob->io_len < iob->io_offset + 1)
{
goto errout;
}
gtsdirmask = IEEE802154_GETGTSDIRMASK(iob->io_data, iob->io_offset);
UNUSED(gtsdirmask);
iob->io_offset++;
/* Make sure there are enough bytes left to represent the GTS List */
if (iob->io_len < iob->io_offset + (3 * ngtsdesc))
{
goto errout;
}
for (i = 0; i < ngtsdesc; i++)
{
/* For now we just discard the data by skipping over it */
iob->io_offset += 3;
}
}
/* Pending address fields. Min 1 byte, the Pending Address Specification */
if (iob->io_len < iob->io_offset + 1)
{
goto errout;
}
beacon->pendaddr.nsaddr = IEEE802154_GETNPENDSADDR(iob->io_data, iob->io_offset);
beacon->pendaddr.neaddr = IEEE802154_GETNPENDEADDR(iob->io_data, iob->io_offset);
iob->io_offset++;
/* Make sure there are enough bytes left to represent the address list */
if (iob->io_len < (iob->io_offset +
(IEEE802154_SADDRSIZE * beacon->pendaddr.nsaddr) +
(IEEE802154_EADDRSIZE * beacon->pendaddr.neaddr)))
{
goto errout;
}
/* Copy in the pending addresses */
for (i = 0; i < beacon->pendaddr.nsaddr; i++)
{
beacon->pendaddr.addr[i].mode = IEEE802154_ADDRMODE_SHORT;
mac802154_takesaddr(iob, beacon->pendaddr.addr[i].saddr);
/* Check if the short address matches our short address */
if (IEEE802154_SADDRCMP(beacon->pendaddr.addr[i].saddr, priv->addr.saddr))
{
/* Wait to actually decide how to handle this until we parse
* the rest of the frame
*/
wlinfo("Data pending for us in coord\n");
pending_saddr = true;
}
}
for (i = beacon->pendaddr.nsaddr;
i < (beacon->pendaddr.nsaddr + beacon->pendaddr.neaddr);
i++)
{
beacon->pendaddr.addr[i].mode = IEEE802154_ADDRMODE_EXTENDED;
mac802154_takeeaddr(iob, beacon->pendaddr.addr[i].eaddr);
/* If the extended address matches our extended address */
if (IEEE802154_EADDRCMP(beacon->pendaddr.addr[i].eaddr, priv->addr.eaddr))
{
/* Wait to actually decide how to handle this until we parse
* the rest of the frame
*/
wlinfo("Data pending for us in coord\n");
pending_eaddr = true;
}
}
/* If there is anything left in the frame, process it as the beacon payload */
beacon->payloadlength = iob->io_len - iob->io_offset;
if (beacon->payloadlength > 0)
{
memcpy(beacon->payload, &iob->io_data[iob->io_offset], beacon->payloadlength);
}
/* At this point, we have extracted all relevant info from the incoming frame */
if (priv->curr_op == MAC802154_OP_SCAN) if (priv->curr_op == MAC802154_OP_SCAN)
{ {
@ -1601,19 +1743,31 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
} }
if (memcmp(&ind->src, &priv->pandescs[i].coordaddr, if (memcmp(&ind->src, &priv->pandescs[i].coordaddr,
sizeof(struct ieee802154_addr_s))) sizeof(struct ieee802154_addr_s)) != 0)
{ {
continue; continue;
} }
/* The beacon is the same as another, so discard it */ /* The beacon is the same as another, so discard it */
mac802154_notif_free_locked(priv, notif);
return; return;
} }
/* TODO: There is supposed to be different logic for the scanning procedure
* based on the macAutoRequest attribute. Currently, we perform scan
* operations as if macAutoRequest is set to TRUE, without actually checking
* the value. Basically, if macAutoRequest is TRUE, we are supposed to
* round up all of the pandesc results and pass them all up via the
* SCAN.confirm primitive. If macAutoRequest is FALSE, we are supposed
* to notify the next highest layer each time a unique beacon is received
* via the BEACON.notify primitive, and pass a NULLed out list of pandesc
* when SCAN.confirm is sent.
*/
/* Copy the pan desc to the list of pan desc */ /* Copy the pan desc to the list of pan desc */
memcpy(&priv->pandescs[priv->npandesc], &pandesc, memcpy(&priv->pandescs[priv->npandesc], &beacon->pandesc,
sizeof(struct ieee802154_pandesc_s)); sizeof(struct ieee802154_pandesc_s));
priv->npandesc++; priv->npandesc++;
@ -1622,69 +1776,101 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
mac802154_scanfinish(priv, IEEE802154_STATUS_LIMITREACHED); mac802154_scanfinish(priv, IEEE802154_STATUS_LIMITREACHED);
} }
} }
/* If we are not performing a SCAN operation */
else else
{ {
/* If there are any GTS descriptors, handle the GTS Directions and /* Check the superframe structure and update the appropriate attributes. */
* GTS List fields
*/
if (numgtsdesc > 0) if (memcmp(&priv->sfspec, &beacon->pandesc.sfspec,
sizeof(struct ieee802154_superframespec_s)) != 0)
{ {
gtsdirmask = IEEE802154_GETGTSDIRMASK(iob->io_data, iob->io_offset); /* Copy in the new superframe spec */
iob->io_offset++;
for (i = 0; i < numgtsdesc; i++) memcpy(&priv->sfspec, &beacon->pandesc.sfspec,
{ sizeof(struct ieee802154_superframespec_s));
/* For now we just discard the data by skipping over it */
iob->io_offset += 3; /* Tell the radio layer about the superframe spec update */
}
priv->radio->sfupdate(priv->radio, &priv->sfspec);
} }
/* Pending address fields. Min 1 byte, the Pending Address Specification */ /* If we are performing an association and there is data pending for us
* we ignore the autoRequest logic and just extract it. We also don't
npendsaddr = IEEE802154_GETNPENDSADDR(iob->io_data, iob->io_offset); * send a BEACON-NOTFIY.indication in this case, not sure if that
npendeaddr = IEEE802154_GETNPENDEADDR(iob->io_data, iob->io_offset); * is the right thing to do, can't find anything definitive in standard.
iob->io_offset++;
/* The pending address field tells us whether or not there is any data
* pending for us.
*/ */
for (i = 0; i < npendsaddr; i++) if (priv->curr_op == MAC802154_OP_ASSOC && pending_eaddr)
{ {
/* If the short address matches our short address */ priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
mac802154_txdesc_alloc(priv, &respdesc, false);
mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
IEEE802154_ADDRMODE_EXTENDED, respdesc);
if (IEEE802154_SADDRCMP(&iob->io_data[iob->io_offset], priv->addr.saddr)) /* Link the transaction into the CSMA transaction list */
{
/* TODO: Handle data pending in coordinator for us */ sq_addlast((FAR sq_entry_t *)respdesc, &priv->csma_queue);
}
iob->io_offset += IEEE802154_SADDRSIZE; /* Notify the radio driver that there is data available */
priv->radio->txnotify(priv->radio, false);
} }
else
for (i = 0; i < npendeaddr; i++)
{ {
/* If the extended address matches our extended address */ if (priv->autoreq || priv->curr_op == MAC802154_OP_POLL)
if (IEEE802154_EADDRCMP(&iob->io_data[iob->io_offset], priv->addr.eaddr))
{ {
/* If we are associating, polling, or if macAutoRequest is TRUE, /* If a beacon frame is received and macAutoRequest is set to
* extract the data. * TRUE, the MLME shall first issue the MLME-
* BEACON-NOTIFY.indication primitive if the beacon contains any
* payload.
*/ */
if ((priv->autoreq) || (priv->curr_op == MAC802154_OP_ASSOC) || if (beacon->payloadlength > 0)
(priv->curr_op == MAC802154_OP_POLL)) {
/* Unlock the MAC, notify, then lock again */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_lock(priv, false);
}
/* If we have data pending for us, attempt to extract it. If for some
* reason we have data pending under our short address and our
* extended address, let the short address arbitrarily take precedence
*/
if (pending_saddr | pending_eaddr)
{ {
mac802154_txdesc_alloc(priv, &respdesc, false); mac802154_txdesc_alloc(priv, &respdesc, false);
mac802154_createdatareq(priv, &priv->pandesc.coordaddr, if (priv->curr_op == MAC802154_OP_POLL)
IEEE802154_ADDRMODE_EXTENDED, respdesc);
if (priv->curr_op == MAC802154_OP_ASSOC ||
priv->curr_op == MAC802154_OP_POLL)
{ {
priv->curr_cmd = IEEE802154_CMD_DATA_REQ; priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
} }
else if (priv->curr_op == MAC802154_OP_ASSOC)
{
priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
}
else if (priv->curr_op == MAC802154_OP_NONE)
{
DEBUGASSERT(priv->opsem.semcount == 1);
mac802154_takesem(&priv->opsem, false);
priv->curr_op = MAC802154_OP_AUTOEXTRACT;
priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
}
if (pending_saddr)
{
mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
IEEE802154_ADDRMODE_SHORT, respdesc);
}
else
{
mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
IEEE802154_ADDRMODE_EXTENDED, respdesc);
}
/* Link the transaction into the CSMA transaction list */ /* Link the transaction into the CSMA transaction list */
@ -1694,146 +1880,39 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
priv->radio->txnotify(priv->radio, false); priv->radio->txnotify(priv->radio, false);
} }
/* If there was a beacon payload, we used the notification, so
* return here to make sure we don't free the notification.
*/
if (beacon->payloadlength > 0)
{
return;
}
} }
iob->io_offset += IEEE802154_EADDRSIZE; else
} {
/* If a valid beacon frame is received and macAutoRequest is set to FALSE,
* the MLME shall indicate the beacon parameters to the next higher layer
* by issuing the MLME-BEACON-NOTIFY.indication primitive. [1] pg. 38
*/
/* TODO: Process incoming beacon payload /* Unlock the MAC, notify, then lock again */
* If there is anything left in the frame, process it as the beacon payload
*/
/* Check the superframe structure and update the appropriate attributes. */ mac802154_unlock(priv)
mac802154_notify(priv, notif);
if (memcmp(&priv->sfspec, &pandesc.sfspec, mac802154_lock(priv, false);
sizeof(struct ieee802154_superframespec_s)) != 0) return; /* Return so that we don't free the notificaiton */
{ }
/* Copy in the new superframe spec */
memcpy(&priv->sfspec, &pandesc.sfspec,
sizeof(struct ieee802154_superframespec_s));
/* Tell the radio layer about the superframe spec update */
priv->radio->sfupdate(priv->radio, &pandesc.sfspec);
} }
} }
}
/**************************************************************************** mac802154_notif_free_locked(priv, notif);
* Name: mac802154_symtoticks return;
*
* 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, errout:
uint32_t symbols) wlwarn("Received beacon with bad format\n");
{ mac802154_notif_free_locked(priv, notif);
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->get_attr(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);
work_queue(MAC802154_WORK, &priv->timeout_work, (worker_t)priv->timeout_worker,
priv, 0);
} }
/**************************************************************************** /****************************************************************************
@ -1879,6 +1958,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
if (mac == NULL) if (mac == NULL)
{ {
wlinfo("Failed allocation privmac structure\n");
return NULL; return NULL;
} }
@ -1890,16 +1970,10 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
sem_init(&mac->opsem, 0, 1); sem_init(&mac->opsem, 0, 1);
/* Setup watchdog for extraction timeout */
mac->timeout = wd_create();
/* Initialize fields */ /* Initialize fields */
mac->radio = radiodev; mac->radio = radiodev;
mac802154_req_reset((MACHANDLE)mac, true);
/* Initialize the Radio callbacks */ /* Initialize the Radio callbacks */
mac->radiocb.priv = mac; mac->radiocb.priv = mac;
@ -1919,6 +1993,8 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
ieee802154_indpool_initialize(); ieee802154_indpool_initialize();
mac802154_resetqueues(mac); mac802154_resetqueues(mac);
mac802154_req_reset((MACHANDLE)mac, true);
/* Set the default extended address */ /* Set the default extended address */
for (i = 0; i < IEEE802154_EADDRSIZE; i++) for (i = 0; i < IEEE802154_EADDRSIZE; i++)
@ -1926,9 +2002,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
eaddr[i] = (CONFIG_IEEE802154_DEFAULT_EADDR >> (8 * i)) & 0xFF; eaddr[i] = (CONFIG_IEEE802154_DEFAULT_EADDR >> (8 * i)) & 0xFF;
} }
IEEE802154_EADDRCOPY(mac->addr.eaddr, eaddr); mac802154_seteaddr(mac, eaddr);
mac->radio->set_attr(mac->radio, IEEE802154_ATTR_MAC_EADDR,
(union ieee802154_attr_u *)&eaddr[0]);
return (MACHANDLE)mac; return (MACHANDLE)mac;
} }

View File

@ -223,11 +223,11 @@ int mac802154_req_gts(MACHANDLE mac, FAR struct ieee802154_gts_req_s *req);
* *
* Input Parameters: * Input Parameters:
* mac - Handle to the MAC layer instance * mac - Handle to the MAC layer instance
* rst_pibattr - Whether or not to reset the MAC PIB attributes to defaults * reset_attr - Whether or not to reset the MAC PIB attributes to defaults
* *
****************************************************************************/ ****************************************************************************/
int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr); int mac802154_req_reset(MACHANDLE mac, bool restattr);
/**************************************************************************** /****************************************************************************
* Name: mac802154_req_rxenable * Name: mac802154_req_rxenable
@ -368,7 +368,7 @@ int mac802154_resp_orphan(MACHANDLE mac,
* *
****************************************************************************/ ****************************************************************************/
int mac802154_notif_free(MACHANDLE mac, void mac802154_notif_free(MACHANDLE mac,
FAR struct ieee802154_notif_s *notif); FAR struct ieee802154_notif_s *notif);
#undef EXTERN #undef EXTERN

View File

@ -58,7 +58,7 @@
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv); static void mac802154_assoctimeout(FAR void *arg);
/**************************************************************************** /****************************************************************************
* Public MAC Functions * Public MAC Functions
@ -86,8 +86,8 @@ int mac802154_req_associate(MACHANDLE mac,
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
FAR struct ieee802154_txdesc_s *txdesc; FAR struct ieee802154_txdesc_s *txdesc;
FAR struct iob_s *iob; FAR struct iob_s *iob;
bool rxonidle;
int ret; int ret;
int i;
if (req->coordaddr.mode == IEEE802154_ADDRMODE_NONE) if (req->coordaddr.mode == IEEE802154_ADDRMODE_NONE)
{ {
@ -111,7 +111,7 @@ int mac802154_req_associate(MACHANDLE mac,
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
ret = mac802154_takesem(&priv->exclsem, true); ret = mac802154_lock(priv, true);
if (ret < 0) if (ret < 0)
{ {
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
@ -127,27 +127,22 @@ int mac802154_req_associate(MACHANDLE mac,
mac802154_setcoordaddr(priv, &req->coordaddr); mac802154_setcoordaddr(priv, &req->coordaddr);
/* TODO: Need to send coordinator address to radio layer */
/* Copy the coordinator PAN ID to our PAN ID */ /* Copy the coordinator PAN ID to our PAN ID */
mac802154_setpanid(priv, req->coordaddr.panid); mac802154_setpanid(priv, req->coordaddr.panid);
/* Copy in the capabilities information bitfield */ /* Copy in the capabilities information bitfield */
priv->devmode = (req->capabilities.devtype) ? if (req->capabilities.devtype)
IEEE802154_DEVMODE_COORD : IEEE802154_DEVMODE_ENDPOINT; {
mac802154_setdevmode(priv, IEEE802154_DEVMODE_COORD);
}
else
{
mac802154_setdevmode(priv, IEEE802154_DEVMODE_ENDPOINT);
}
/* Unlike other attributes, we can't simply cast this one since it is a bit mac802154_setrxonidle(priv, req->capabilities.rxonidle);
* in a bitfield. Casting it will give us unpredicatble results. Instead
* of creating a ieee802154_attr_u, we use a local bool. Allocating the
* ieee802154_attr_u value would take up more room on the stack since it is
* as large as the largest attribute type.
*/
rxonidle = req->capabilities.rxonidle;
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE,
(FAR const union ieee802154_attr_u *)&rxonidle);
/* Allocate an IOB to put the frame in */ /* Allocate an IOB to put the frame in */
@ -165,7 +160,7 @@ int mac802154_req_associate(MACHANDLE mac,
if (ret < 0) if (ret < 0)
{ {
iob_free(iob); iob_free(iob);
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
return ret; return ret;
} }
@ -250,13 +245,67 @@ int mac802154_req_associate(MACHANDLE mac,
priv->cmd_desc = txdesc; priv->cmd_desc = txdesc;
/* Search the list of PAN descriptors, that would have been populated by the
* latest scan procedure. If we have seen a beacon from the coordinator that
* we are about to associate with, we can check the beacon order to determine
* whether we can send the command during the CAP. If we haven't received
* a beacon frame from the desired coordinator address, we have to just
* send the frame out immediately.
*/
for (i = 0; i < priv->npandesc; i++)
{
/* Check to make sure the beacon is from the same channel as the request */
if (req->chan != priv->pandescs[i].chan)
{
continue;
}
if (memcmp(&req->coordaddr, &priv->pandescs[i].coordaddr,
sizeof(struct ieee802154_addr_s)) == 0)
{
wlinfo("Found matching beacon to use for settings\n");
/* We have a beacon frame from this coordinator, we can set the
* sfspec and send accordingly.
*/
/* Copy in the new superframe spec */
memcpy(&priv->sfspec, &priv->pandescs[i].sfspec,
sizeof(struct ieee802154_superframespec_s));
/* Tell the radio layer about the superframe spec update */
priv->radio->sfupdate(priv->radio, &priv->pandescs[i].sfspec);
}
}
if (priv->sfspec.beaconorder == 15)
{
wlinfo("Transmitting assoc request\n");
/* Association Request command gets sent out immediately */
priv->radio->txdelayed(priv->radio, txdesc, 0);
}
else
{
wlinfo("Queuing assoc request for CAP\n");
/* Link the transaction into the CSMA transaction list */
sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue);
/* Notify the radio driver that there is data available */
priv->radio->txnotify(priv->radio, false);
}
/* We no longer need to have the MAC layer locked. */ /* We no longer need to have the MAC layer locked. */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Association Request command gets sent out immediately */
priv->radio->txdelayed(priv->radio, txdesc, 0);
return OK; return OK;
} }
@ -351,7 +400,7 @@ int mac802154_resp_associate(MACHANDLE mac,
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
ret = mac802154_takesem(&priv->exclsem, true); ret = mac802154_lock(priv, true);
if (ret < 0) if (ret < 0)
{ {
iob_free(iob); iob_free(iob);
@ -364,7 +413,7 @@ int mac802154_resp_associate(MACHANDLE mac,
if (ret < 0) if (ret < 0)
{ {
iob_free(iob); iob_free(iob);
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return ret; return ret;
} }
@ -377,7 +426,7 @@ int mac802154_resp_associate(MACHANDLE mac,
mac802154_setupindirect(priv, txdesc); mac802154_setupindirect(priv, txdesc);
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return OK; return OK;
} }
@ -402,10 +451,9 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s *txdesc) FAR struct ieee802154_txdesc_s *txdesc)
{ {
enum ieee802154_status_e status; enum ieee802154_status_e status;
FAR struct mac802154_notif_s *privnotif =
(FAR struct mac802154_notif_s *)txdesc->conf;
FAR struct ieee802154_notif_s *notif = &privnotif->pub;
FAR struct ieee802154_txdesc_s *respdesc; FAR struct ieee802154_txdesc_s *respdesc;
FAR struct ieee802154_notif_s *notif =
(FAR struct ieee802154_notif_s *)txdesc->conf;
if(txdesc->conf->status != IEEE802154_STATUS_SUCCESS) if(txdesc->conf->status != IEEE802154_STATUS_SUCCESS)
{ {
@ -433,6 +481,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC); IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
/* We are now done the operation, unlock the semaphore */ /* We are now done the operation, unlock the semaphore */
priv->curr_op = MAC802154_OP_NONE; priv->curr_op = MAC802154_OP_NONE;
@ -441,9 +490,9 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC, call the callback, get exclusive access again */ /* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_notify(priv, notif); mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
} }
else else
{ {
@ -467,17 +516,33 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
* to respond. Setup a timeout for macResponseWaitTime so that we * to respond. Setup a timeout for macResponseWaitTime so that we
* can inform the next highest layer if the association attempt fails * can inform the next highest layer if the association attempt fails
* due to NO_DATA. * due to NO_DATA.
*
* TODO: The standard defines macResponseWaitTime as:
* The maximum time, in multiples of aBaseSuperframeDuration, a device
* shall wait for a response command frame to be available following a
* request command frame.
*
* However, on beacon-enabled networks, it seems the maximum value
* isn't really that large of a value, AKA: assoc always fails from
* timeout even though everything is working as expected. The definition
* does say after we've sent a data request, which we, haven't sent
* yet, but we do need a timeout for association in general. Not sure
* what the correct answer is. For now, I am going to change the
* way macResponseWaitTime is used with beacon-enabled networks and
* make the timeout (BI * macResponseWaitTime) where BI is Beacon
* Interval = aBaseSuperframeDuration * 2^macBeaconOrder
*/ */
wlinfo("Starting timeout timer\n");
mac802154_timerstart(priv, (priv->resp_waittime * mac802154_timerstart(priv, (priv->resp_waittime *
IEEE802154_BASE_SUPERFRAME_DURATION), (IEEE802154_BASE_SUPERFRAME_DURATION * (1 << priv->sfspec.beaconorder))),
mac802154_assoctimeout); mac802154_assoctimeout);
} }
else else
{ {
/* Make sure the coordinator address mode is not set to none. This shouldn't /* Make sure the coordinator address mode is not set to none. This
* happen since the association request should have set the mode to short or * shouldn't happen since the association request should have set
* extended * the mode to short or extended
*/ */
DEBUGASSERT(priv->pandesc.coordaddr.mode != IEEE802154_ADDRMODE_NONE); DEBUGASSERT(priv->pandesc.coordaddr.mode != IEEE802154_ADDRMODE_NONE);
@ -497,13 +562,9 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
(priv->resp_waittime*IEEE802154_BASE_SUPERFRAME_DURATION)); (priv->resp_waittime*IEEE802154_BASE_SUPERFRAME_DURATION));
} }
/* We can deallocate the data conf notification as it is no longer /* Deallocate the data conf notification as it is no longer needed. */
* needed. We can't use the public function here since we already
* have the MAC locked.
*/
privnotif->flink = priv->notif_free; mac802154_notif_free_locked(priv, notif);
priv->notif_free = privnotif;
} }
} }
@ -524,9 +585,8 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s *txdesc) FAR struct ieee802154_txdesc_s *txdesc)
{ {
enum ieee802154_status_e status; enum ieee802154_status_e status;
FAR struct mac802154_notif_s *privnotif = FAR struct ieee802154_notif_s *notif =
(FAR struct mac802154_notif_s *)txdesc->conf; (FAR struct ieee802154_notif_s *)txdesc->conf;
FAR struct ieee802154_notif_s *notif = &privnotif->pub;
/* If the data request failed to be sent, notify the next layer /* If the data request failed to be sent, notify the next layer
* that the association has failed. * that the association has failed.
@ -573,9 +633,9 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC, call the callback, get exclusive access again */ /* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_notify(priv, notif); mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
} }
else else
{ {
@ -587,22 +647,33 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
mac802154_rxenable(priv); mac802154_rxenable(priv);
/* Start a timer, if we receive the data frame, we will cancel /* If we are on a beacon-enabled network, we already have the association
* the timer, otherwise it will expire and we will notify the * timeout timer scheduled. So we only need to start the timeout timer
* next highest layer of the failure. * if we are operating on a non-beacon enabled network.
*
* NOTE: This may create a bad side-effect where the receiver is on
* for longer than it needs to be during association. Revisit if power
* is ever an issue.
*/ */
mac802154_timerstart(priv, priv->max_frame_waittime, if (priv->sfspec.beaconorder == 15)
mac802154_assoctimeout); {
/* We can deallocate the data conf notification as it is no longer /* Start a timer, if we receive the data frame, we will cancel
* needed. We can't use the public function here since we already * the timer, otherwise it will expire and we will notify the
* have the MAC locked. * next highest layer of the failure.
*/ */
wlinfo("Starting timeout timer\n");
mac802154_timerstart(priv, priv->max_frame_waittime,
mac802154_assoctimeout);
}
/* Deallocate the data conf notification as it is no longer needed. */
mac802154_notif_free_locked(priv, notif);
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
mac802154_givesem(&priv->notif_sem);
} }
} }
@ -624,7 +695,7 @@ void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv,
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* Allocate a notification to pass to the next highest layer */ /* Allocate a notification to pass to the next highest layer */
@ -665,7 +736,7 @@ void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv,
/* Unlock the MAC */ /* Unlock the MAC */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Notify the next highest layer of the association status */ /* Notify the next highest layer of the association status */
@ -673,7 +744,7 @@ void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv,
return; return;
errout_with_sem: errout_with_sem:
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return; return;
} }
@ -698,6 +769,19 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
if (priv->curr_op != MAC802154_OP_ASSOC) if (priv->curr_op != MAC802154_OP_ASSOC)
{ {
/* This situation can occur in a beacon-enabled network if the association
* request has timed out, but the Coordinator has already queued the
* response. Which means the beacon would contain our address, causing us
* to extract the response.
*
* TODO: What is supposed to happen in this situation. Are we supposed to
* accept the request? Are we supposed to Disassociate with the network
* as a convienience to the PAN Coordinator. So that it does not need
* to waste space holding our information?
*/
wlinfo("Ignoring association response frame\n");
return; return;
} }
@ -707,7 +791,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* Allocate a notification to pass to the next highest layer */ /* Allocate a notification to pass to the next highest layer */
@ -720,7 +804,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
/* Inform the radio of the address change */ /* Inform the radio of the address change */
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_SADDR, priv->radio->setattr(priv->radio, IEEE802154_ATTR_MAC_SADDR,
(FAR union ieee802154_attr_u *)priv->addr.saddr); (FAR union ieee802154_attr_u *)priv->addr.saddr);
/* A Short Address field value equal to 0xfffe shall indicate that the device /* A Short Address field value equal to 0xfffe shall indicate that the device
@ -751,15 +835,16 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, priv->addr.saddr); IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, priv->addr.saddr);
/* Unlock the MAC */
mac802154_givesem(&priv->exclsem);
/* We are no longer performing the association operation */ /* We are no longer performing the association operation */
priv->curr_op = MAC802154_OP_NONE; priv->curr_op = MAC802154_OP_NONE;
priv->cmd_desc = NULL; priv->cmd_desc = NULL;
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
mac802154_rxdisable(priv);
/* Unlock the MAC */
mac802154_unlock(priv)
/* Notify the next highest layer of the association status */ /* Notify the next highest layer of the association status */
@ -779,10 +864,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; 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); DEBUGASSERT(priv->curr_op == MAC802154_OP_ASSOC);
/* If the device does not extract an association response command /* If the device does not extract an association response command
@ -796,17 +893,19 @@ static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv)
* Don't allow EINTR to interrupt. * Don't allow EINTR to interrupt.
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
mac802154_notif_alloc(priv, &notif, false); mac802154_notif_alloc(priv, &notif, false);
/* We are no longer performing the association operation */ /* We are no longer performing the association operation */
priv->curr_op = MAC802154_OP_NONE; priv->curr_op = MAC802154_OP_NONE;
priv->cmd_desc = NULL; priv->cmd_desc = NULL;
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
mac802154_rxdisable(priv);
/* Release the MAC */ /* Release the MAC */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC; notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC;
notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA; notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA;

View File

@ -118,7 +118,7 @@ int mac802154_req_data(MACHANDLE mac,
* 5.1.6.4 [1] pg. 118. * 5.1.6.4 [1] pg. 118.
*/ */
*frame_ctrl |= (meta->msdu_flags.ack_tx << IEEE802154_FRAMECTRL_SHIFT_ACKREQ); *frame_ctrl |= (meta->flags.ackreq << IEEE802154_FRAMECTRL_SHIFT_ACKREQ);
/* If the destination address is present, copy the PAN ID and one of the /* If the destination address is present, copy the PAN ID and one of the
* addresses, depending on mode, into the MHR. * addresses, depending on mode, into the MHR.
@ -147,7 +147,7 @@ int mac802154_req_data(MACHANDLE mac,
/* From this point on, we need exclusive access to the privmac struct */ /* From this point on, we need exclusive access to the privmac struct */
ret = mac802154_takesem(&priv->exclsem, true); ret = mac802154_lock(priv, true);
if (ret < 0) if (ret < 0)
{ {
/* Should only fail if interrupted by a signal */ /* Should only fail if interrupted by a signal */
@ -161,7 +161,7 @@ int mac802154_req_data(MACHANDLE mac,
* [1] pg. 41. * [1] pg. 41.
*/ */
if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE && if (meta->srcmode != IEEE802154_ADDRMODE_NONE &&
meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) meta->destaddr.mode != IEEE802154_ADDRMODE_NONE)
{ {
/* If the PAN identifiers are identical, the PAN ID Compression field /* If the PAN identifiers are identical, the PAN ID Compression field
@ -175,7 +175,7 @@ int mac802154_req_data(MACHANDLE mac,
} }
} }
if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE) if (meta->srcmode != IEEE802154_ADDRMODE_NONE)
{ {
/* If the destination address is not included, or if PAN ID Compression /* If the destination address is not included, or if PAN ID Compression
* is off, we need to include the Source PAN ID. * is off, we need to include the Source PAN ID.
@ -188,12 +188,12 @@ int mac802154_req_data(MACHANDLE mac,
mhr_len += 2; mhr_len += 2;
} }
if (meta->srcaddr_mode == IEEE802154_ADDRMODE_SHORT) if (meta->srcmode == IEEE802154_ADDRMODE_SHORT)
{ {
IEEE802154_SADDRCOPY(&frame->io_data[mhr_len], priv->addr.saddr); IEEE802154_SADDRCOPY(&frame->io_data[mhr_len], priv->addr.saddr);
mhr_len += 2; mhr_len += 2;
} }
else if (meta->srcaddr_mode == IEEE802154_ADDRMODE_EXTENDED) else if (meta->srcmode == IEEE802154_ADDRMODE_EXTENDED)
{ {
IEEE802154_EADDRCOPY(&frame->io_data[mhr_len], priv->addr.eaddr); IEEE802154_EADDRCOPY(&frame->io_data[mhr_len], priv->addr.eaddr);
mhr_len += IEEE802154_EADDRSIZE; mhr_len += IEEE802154_EADDRSIZE;
@ -214,7 +214,7 @@ int mac802154_req_data(MACHANDLE mac,
/* Set the source addr mode inside the frame control field */ /* Set the source addr mode inside the frame control field */
*frame_ctrl |= (meta->srcaddr_mode << IEEE802154_FRAMECTRL_SHIFT_SADDR); *frame_ctrl |= (meta->srcmode << IEEE802154_FRAMECTRL_SHIFT_SADDR);
/* Each time a data or a MAC command frame is generated, the MAC sublayer /* Each time a data or a MAC command frame is generated, the MAC sublayer
* shall copy the value of macDSN into the Sequence Number field of the MHR * shall copy the value of macDSN into the Sequence Number field of the MHR
@ -255,7 +255,7 @@ int mac802154_req_data(MACHANDLE mac,
/* Then initialize the TX descriptor */ /* Then initialize the TX descriptor */
txdesc->conf->handle = meta->msdu_handle; txdesc->conf->handle = meta->handle;
txdesc->frame = frame; txdesc->frame = frame;
txdesc->frametype = IEEE802154_FRAME_DATA; txdesc->frametype = IEEE802154_FRAME_DATA;
@ -271,7 +271,7 @@ int mac802154_req_data(MACHANDLE mac,
* [1] pg. 118. * [1] pg. 118.
*/ */
if (meta->msdu_flags.gts_tx) if (meta->flags.usegts)
{ {
/* TODO: Support GTS transmission. This should just change where we link /* TODO: Support GTS transmission. This should just change where we link
* the transaction. Instead of going in the CSMA transaction list, it * the transaction. Instead of going in the CSMA transaction list, it
@ -291,7 +291,7 @@ int mac802154_req_data(MACHANDLE mac,
* described in 5.1.5 and 5.1.6.3. [1] * described in 5.1.5 and 5.1.6.3. [1]
*/ */
if (meta->msdu_flags.indirect_tx) if (meta->flags.indirect)
{ {
/* If the TxOptions parameter specifies that an indirect transmission /* If the TxOptions parameter specifies that an indirect transmission
* is required and if the device receiving this primitive is not a * is required and if the device receiving this primitive is not a
@ -313,7 +313,7 @@ int mac802154_req_data(MACHANDLE mac,
memcpy(&txdesc->destaddr, &meta->destaddr, memcpy(&txdesc->destaddr, &meta->destaddr,
sizeof(struct ieee802154_addr_s)); sizeof(struct ieee802154_addr_s));
mac802154_setupindirect(priv, txdesc); mac802154_setupindirect(priv, txdesc);
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
} }
else else
{ {
@ -329,7 +329,7 @@ int mac802154_req_data(MACHANDLE mac,
/* We no longer need to have the MAC layer locked. */ /* We no longer need to have the MAC layer locked. */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Notify the radio driver that there is data available */ /* Notify the radio driver that there is data available */
@ -346,7 +346,7 @@ errout_with_txdesc:
mac802154_txdesc_free(priv, txdesc); mac802154_txdesc_free(priv, txdesc);
errout_with_sem: errout_with_sem:
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return ret; return ret;
} }

View File

@ -73,7 +73,9 @@
int mac802154_req_disassociate(MACHANDLE mac, int mac802154_req_disassociate(MACHANDLE mac,
FAR struct ieee802154_disassoc_req_s *req) FAR struct ieee802154_disassoc_req_s *req)
{ {
#if 0
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
#endif
return -ENOTTY; return -ENOTTY;
} }

View File

@ -76,14 +76,14 @@ int mac802154_get_mhrlen(MACHANDLE mac,
* to NONE */ * to NONE */
if (meta->destaddr.mode == IEEE802154_ADDRMODE_NONE && if (meta->destaddr.mode == IEEE802154_ADDRMODE_NONE &&
meta->srcaddr_mode == IEEE802154_ADDRMODE_NONE) meta->srcmode == IEEE802154_ADDRMODE_NONE)
{ {
return -EINVAL; return -EINVAL;
} }
/* The source address can only be set to NONE if the device is the PAN coord */ /* The source address can only be set to NONE if the device is the PAN coord */
if (meta->srcaddr_mode == IEEE802154_ADDRMODE_NONE && if (meta->srcmode == IEEE802154_ADDRMODE_NONE &&
priv->devmode != IEEE802154_DEVMODE_PANCOORD) priv->devmode != IEEE802154_DEVMODE_PANCOORD)
{ {
return -EINVAL; return -EINVAL;
@ -95,14 +95,14 @@ int mac802154_get_mhrlen(MACHANDLE mac,
/* Add the source address length */ /* Add the source address length */
ret += mac802154_addr_length[ meta->srcaddr_mode]; ret += mac802154_addr_length[ meta->srcmode];
/* If both destination and source addressing information is present, the MAC /* If both destination and source addressing information is present, the MAC
* sublayer shall compare the destination and source PAN identifiers. * sublayer shall compare the destination and source PAN identifiers.
* [1] pg. 41. * [1] pg. 41.
*/ */
if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE && if (meta->srcmode != IEEE802154_ADDRMODE_NONE &&
meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) meta->destaddr.mode != IEEE802154_ADDRMODE_NONE)
{ {
/* If the PAN identifiers are identical, the PAN ID Compression field /* If the PAN identifiers are identical, the PAN ID Compression field
@ -121,7 +121,7 @@ int mac802154_get_mhrlen(MACHANDLE mac,
* PAN ID if the respective address is included * PAN ID if the respective address is included
*/ */
if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE) if (meta->srcmode != IEEE802154_ADDRMODE_NONE)
{ {
ret += 2; /* 2 bytes for source PAN ID */ ret += 2; /* 2 bytes for source PAN ID */
} }

View File

@ -84,29 +84,55 @@ int mac802154_req_get(MACHANDLE mac, enum ieee802154_attr_e attr,
switch (attr) switch (attr)
{ {
case IEEE802154_ATTR_MAC_PANID: case IEEE802154_ATTR_MAC_PANID:
IEEE802154_PANIDCOPY(attrval->mac.panid, priv->addr.panid); {
IEEE802154_PANIDCOPY(attrval->mac.panid, priv->addr.panid);
}
break; break;
case IEEE802154_ATTR_MAC_SADDR:
IEEE802154_SADDRCOPY(attrval->mac.saddr, priv->addr.saddr);
break;
case IEEE802154_ATTR_MAC_EADDR:
IEEE802154_EADDRCOPY(attrval->mac.eaddr, priv->addr.eaddr);
break;
case IEEE802154_ATTR_MAC_COORD_SADDR:
IEEE802154_SADDRCOPY(attrval->mac.coordsaddr, priv->pandesc.coordaddr.saddr);
break;
case IEEE802154_ATTR_MAC_COORD_EADDR:
IEEE802154_EADDRCOPY(attrval->mac.coordeaddr, priv->pandesc.coordaddr.eaddr);
break;
case IEEE802154_ATTR_MAC_DEVMODE:
attrval->mac.devmode = priv->devmode;
break;
default:
/* The attribute may be handled soley in the radio driver, so pass
* it along.
*/
ret = priv->radio->get_attr(priv->radio, attr, attrval); case IEEE802154_ATTR_MAC_SADDR:
{
IEEE802154_SADDRCOPY(attrval->mac.saddr, priv->addr.saddr);
}
break;
case IEEE802154_ATTR_MAC_EADDR:
{
IEEE802154_EADDRCOPY(attrval->mac.eaddr, priv->addr.eaddr);
}
break;
case IEEE802154_ATTR_MAC_COORD_SADDR:
{
IEEE802154_SADDRCOPY(attrval->mac.coordsaddr, priv->pandesc.coordaddr.saddr);
}
break;
case IEEE802154_ATTR_MAC_COORD_EADDR:
{
IEEE802154_EADDRCOPY(attrval->mac.coordeaddr, priv->pandesc.coordaddr.eaddr);
}
break;
case IEEE802154_ATTR_MAC_DEVMODE:
{
attrval->mac.devmode = priv->devmode;
}
break;
case IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME:
{
attrval->mac.resp_waittime = priv->resp_waittime;
}
break;;
default:
{
/* The attribute may be handled soley in the radio driver, so pass
* it along.
*/
ret = priv->radio->getattr(priv->radio, attr, attrval);
}
break; break;
} }
@ -133,54 +159,56 @@ int mac802154_req_set(MACHANDLE mac, enum ieee802154_attr_e attr,
{ {
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
int ret; int ret = IEEE802154_STATUS_SUCCESS;
switch (attr) switch (attr)
{ {
case IEEE802154_ATTR_MAC_PANID: case IEEE802154_ATTR_MAC_PANID:
{ {
mac802154_setpanid(priv, attrval->mac.panid); mac802154_setpanid(priv, attrval->mac.panid);
ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_SADDR: case IEEE802154_ATTR_MAC_SADDR:
{ {
mac802154_setsaddr(priv, attrval->mac.saddr); mac802154_setsaddr(priv, attrval->mac.saddr);
ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_EADDR: case IEEE802154_ATTR_MAC_EADDR:
{ {
mac802154_seteaddr(priv, attrval->mac.eaddr); mac802154_seteaddr(priv, attrval->mac.eaddr);
ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_COORD_SADDR: case IEEE802154_ATTR_MAC_COORD_SADDR:
{ {
mac802154_setcoordsaddr(priv, attrval->mac.coordsaddr); mac802154_setcoordsaddr(priv, attrval->mac.coordsaddr);
ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_COORD_EADDR: case IEEE802154_ATTR_MAC_COORD_EADDR:
{ {
mac802154_setcoordeaddr(priv, attrval->mac.coordeaddr); mac802154_setcoordeaddr(priv, attrval->mac.coordeaddr);
ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_ASSOCIATION_PERMIT: case IEEE802154_ATTR_MAC_ASSOCIATION_PERMIT:
{ {
priv->sfspec.assocpermit = attrval->mac.assocpermit; priv->sfspec.assocpermit = attrval->mac.assocpermit;
priv->beaconupdate = true; priv->beaconupdate = true;
ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME:
{
priv->resp_waittime = attrval->mac.resp_waittime;
}
case IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE:
{
mac802154_setrxonidle(priv, attrval->mac.rxonidle);
}
default: default:
{ {
/* The attribute may be handled soley in the radio driver, so pass /* The attribute may be handled soley in the radio driver, so pass
* it along. * it along.
*/ */
ret = priv->radio->set_attr(priv->radio, attr, attrval); ret = priv->radio->setattr(priv->radio, attr, attrval);
} }
break; break;
} }

View File

@ -66,7 +66,9 @@
int mac802154_req_gts(MACHANDLE mac, FAR struct ieee802154_gts_req_s *req) int mac802154_req_gts(MACHANDLE mac, FAR struct ieee802154_gts_req_s *req)
{ {
#if 0
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
#endif
return -ENOTTY; return -ENOTTY;
} }

File diff suppressed because it is too large Load Diff

View File

@ -74,14 +74,12 @@
int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) 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; int ret = -EINVAL;
FAR union ieee802154_macarg_u *macarg = FAR union ieee802154_macarg_u *macarg =
(FAR union ieee802154_macarg_u *)((uintptr_t)arg); (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 */ /* Check for IOCTLs aimed at the IEEE802.15.4 MAC layer */
@ -124,7 +122,7 @@ int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg)
break; break;
case MAC802154IOC_MLME_RESET_REQUEST: case MAC802154IOC_MLME_RESET_REQUEST:
{ {
ret = mac802154_req_reset(mac, macarg->resetreq.rst_pibattr); ret = mac802154_req_reset(mac, macarg->resetreq.resetattr);
} }
break; break;
case MAC802154IOC_MLME_RXENABLE_REQUEST: case MAC802154IOC_MLME_RXENABLE_REQUEST:

View File

@ -173,8 +173,8 @@ static void macnet_ind_associate(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_assoc_ind_s *conf); FAR struct ieee802154_assoc_ind_s *conf);
static void macnet_ind_disassociate(FAR struct macnet_driver_s *priv, static void macnet_ind_disassociate(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_disassoc_ind_s *conf); FAR struct ieee802154_disassoc_ind_s *conf);
static void macnet_ind_beaconnotify(FAR struct macnet_driver_s *priv, static void macnet_ind_beacon(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_beaconnotify_ind_s *conf); FAR struct ieee802154_beacon_ind_s *conf);
static void macnet_ind_gts(FAR struct macnet_driver_s *priv, static void macnet_ind_gts(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_gts_ind_s *conf); FAR struct ieee802154_gts_ind_s *conf);
static void macnet_ind_orphan(FAR struct macnet_driver_s *priv, static void macnet_ind_orphan(FAR struct macnet_driver_s *priv,
@ -589,15 +589,15 @@ static void macnet_ind_disassociate(FAR struct macnet_driver_s *priv,
} }
/**************************************************************************** /****************************************************************************
* Name: macnet_ind_beaconnotify * Name: macnet_ind_beacon
* *
* Description: * Description:
* Beacon notification * Beacon notification
* *
****************************************************************************/ ****************************************************************************/
static void macnet_ind_beaconnotify(FAR struct macnet_driver_s *priv, static void macnet_ind_beacon(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_beaconnotify_ind_s *ind) FAR struct ieee802154_beacon_ind_s *ind)
{ {
} }

View File

@ -69,44 +69,22 @@
* *
****************************************************************************/ ****************************************************************************/
int mac802154_notif_free(MACHANDLE mac, void mac802154_notif_free(MACHANDLE mac, FAR struct ieee802154_notif_s *notif)
FAR struct ieee802154_notif_s *notif)
{ {
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
FAR struct mac802154_notif_s *privnotif =
(FAR struct mac802154_notif_s *)notif;
/* Get exclusive access to the MAC */ /* Lock the MAC */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
/* We know how many clients have registered for notifications. Each must /* Call the internal helper function to free the notification */
* call mac802154_notif_free() before we can release the notification
* resource.
*/
if (priv->nnotif < 2) mac802154_notif_free_locked(priv, notif);
{
/* This is the free from the last notification */
privnotif->flink = priv->notif_free; /* Unlock the MAC */
priv->notif_free = privnotif;
priv->nnotif = 0;
mac802154_givesem(&priv->notif_sem); mac802154_unlock(priv)
}
else
{
/* More calls are expected. Decrement the count of expected calls
* and preserve the notification resources.
*/
priv->nnotif--;
}
mac802154_givesem(&priv->exclsem);
return -ENOTTY;
} }
/**************************************************************************** /****************************************************************************
@ -184,15 +162,15 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
if (ret == OK) if (ret == OK)
{ {
privnotif = priv->notif_free; privnotif = priv->notif_free;
priv->notif_free = privnotif->flink; priv->notif_free = privnotif->flink;
priv->nnotif = 0; privnotif->nclients = 0;
} }
else else
{ {
/* Unlock MAC so that other work can be done to free a notification */ /* Unlock MAC so that other work can be done to free a notification */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Take a count from the notification semaphore, waiting if necessary. We /* Take a count from the notification semaphore, waiting if necessary. We
* only return from here with an error if we are allowing interruptions * only return from here with an error if we are allowing interruptions
@ -211,7 +189,7 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
* MAC in order to ensure this happens correctly. * MAC in order to ensure this happens correctly.
*/ */
ret = mac802154_takesem(&priv->exclsem, allow_interrupt); ret = mac802154_lock(priv, allow_interrupt);
if (ret < 0) if (ret < 0)
{ {
mac802154_givesem(&priv->notif_sem); mac802154_givesem(&priv->notif_sem);
@ -220,9 +198,9 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
/* We can now safely unlink the next free structure from the free list */ /* We can now safely unlink the next free structure from the free list */
privnotif = priv->notif_free; privnotif = priv->notif_free;
priv->notif_free = privnotif->flink; priv->notif_free = privnotif->flink;
priv->nnotif = 0; privnotif->nclients = 0;
} }
*notif = (FAR struct ieee802154_notif_s *)privnotif; *notif = (FAR struct ieee802154_notif_s *)privnotif;
@ -230,6 +208,49 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
return OK; return OK;
} }
/****************************************************************************
* Name: mac802154_notif_free_locked
*
* Description:
* When the MAC calls the registered callback, it passes a reference
* to a mac802154_notify_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
* Internal version that already has MAC locked
*
****************************************************************************/
void mac802154_notif_free_locked(FAR struct ieee802154_privmac_s * priv,
FAR struct ieee802154_notif_s *notif)
{
FAR struct mac802154_notif_s *privnotif =
(FAR struct mac802154_notif_s *)notif;
/* We know how many clients have registered for notifications. Each must
* call mac802154_notif_free() before we can release the notification
* resource.
*/
if (privnotif->nclients < 2)
{
/* This is the free from the last notification */
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
privnotif->nclients = 0;
mac802154_givesem(&priv->notif_sem);
}
else
{
/* More calls are expected. Decrement the count of expected calls
* and preserve the notification resources.
*/
privnotif->nclients--;
}
}
/**************************************************************************** /****************************************************************************
* Name: mac802154_notify * Name: mac802154_notify
* *
@ -242,12 +263,13 @@ void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s *notif) FAR struct ieee802154_notif_s *notif)
{ {
FAR struct mac802154_maccb_s *cb; FAR struct mac802154_maccb_s *cb;
FAR struct mac802154_notif_s *privnotif = (FAR struct mac802154_notif_s *)notif;
/* Set the notification count so that the notification resources will be /* Set the notification count so that the notification resources will be
* preserved until the final notification. * preserved until the final notification.
*/ */
priv->nnotif = priv->nclients; privnotif->nclients = priv->nclients;
/* Try to notify every registered MAC client */ /* Try to notify every registered MAC client */

View File

@ -65,6 +65,7 @@ struct mac802154_notif_s
{ {
struct ieee802154_notif_s pub; /* Publically visible structure */ struct ieee802154_notif_s pub; /* Publically visible structure */
FAR struct mac802154_notif_s *flink; /* Supports a singly linked list */ FAR struct mac802154_notif_s *flink; /* Supports a singly linked list */
uint8_t nclients;
}; };
/**************************************************************************** /****************************************************************************
@ -82,4 +83,7 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
void mac802154_notify(FAR struct ieee802154_privmac_s *priv, void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s *notif); FAR struct ieee802154_notif_s *notif);
void mac802154_notif_free_locked(FAR struct ieee802154_privmac_s * priv,
FAR struct ieee802154_notif_s *notif);
#endif /* __WIRELESS_IEEE802154__MAC802154_NOTIF_H */ #endif /* __WIRELESS_IEEE802154__MAC802154_NOTIF_H */

View File

@ -65,7 +65,9 @@
int mac802154_resp_orphan(MACHANDLE mac, int mac802154_resp_orphan(MACHANDLE mac,
FAR struct ieee802154_orphan_resp_s *resp) FAR struct ieee802154_orphan_resp_s *resp)
{ {
#if 0
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
#endif
return -ENOTTY; return -ENOTTY;
} }

View File

@ -60,7 +60,7 @@
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv); static void mac802154_polltimeout(FAR void *arg);
/**************************************************************************** /****************************************************************************
* Public MAC Functions * Public MAC Functions
@ -106,7 +106,7 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req)
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
ret = mac802154_takesem(&priv->exclsem, true); ret = mac802154_lock(priv, true);
if (ret < 0) if (ret < 0)
{ {
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
@ -121,7 +121,7 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req)
ret = mac802154_txdesc_alloc(priv, &txdesc, true); ret = mac802154_txdesc_alloc(priv, &txdesc, true);
if (ret < 0) if (ret < 0)
{ {
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
return ret; return ret;
} }
@ -152,13 +152,15 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req)
priv->cmd_desc = txdesc; priv->cmd_desc = txdesc;
wlinfo("Queuing POLL.request in CSMA queue\n");
/* Link the transaction into the CSMA transaction list */ /* Link the transaction into the CSMA transaction list */
sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue); sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue);
/* We no longer need to have the MAC layer locked. */ /* We no longer need to have the MAC layer locked. */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
/* Notify the radio driver that there is data available */ /* Notify the radio driver that there is data available */
@ -188,9 +190,8 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s *txdesc) FAR struct ieee802154_txdesc_s *txdesc)
{ {
enum ieee802154_status_e status; enum ieee802154_status_e status;
FAR struct mac802154_notif_s *privnotif = FAR struct ieee802154_notif_s *notif =
(FAR struct mac802154_notif_s *)txdesc->conf; (FAR struct ieee802154_notif_s *)txdesc->conf;
FAR struct ieee802154_notif_s *notif = &privnotif->pub;
/* If the data request failed to be sent, notify the next layer /* If the data request failed to be sent, notify the next layer
* that the poll has failed. * that the poll has failed.
@ -223,9 +224,9 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC, call the callback, get exclusive access again */ /* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_notify(priv, notif); mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
} }
else else
{ {
@ -245,13 +246,9 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
mac802154_timerstart(priv, priv->max_frame_waittime, mac802154_timerstart(priv, priv->max_frame_waittime,
mac802154_polltimeout); mac802154_polltimeout);
/* We can deallocate the data conf notification as it is no longer /* Deallocate the data conf notification as it is no longer needed. */
* needed. We can't use the public function here since we already
* have the MAC locked.
*/
privnotif->flink = priv->notif_free; mac802154_notif_free_locked(priv, notif);
priv->notif_free = privnotif;
} }
} }
@ -264,17 +261,29 @@ 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; 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); DEBUGASSERT(priv->curr_op == MAC802154_OP_POLL);
/* Allocate a notification struct to pass to the next highest layer. /* Allocate a notification struct to pass to the next highest layer.
* Don't allow EINTR to interrupt. * Don't allow EINTR to interrupt.
*/ */
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
mac802154_notif_alloc(priv, &notif, false); mac802154_notif_alloc(priv, &notif, false);
/* We are no longer performing the association operation */ /* We are no longer performing the association operation */
@ -284,7 +293,7 @@ void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv)
/* Release the MAC */ /* Release the MAC */
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
notif->notiftype = IEEE802154_NOTIFY_CONF_POLL; notif->notiftype = IEEE802154_NOTIFY_CONF_POLL;
notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA; notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA;

View File

@ -76,8 +76,10 @@
int mac802154_req_purge(MACHANDLE mac, uint8_t msdu_handle) int mac802154_req_purge(MACHANDLE mac, uint8_t msdu_handle)
{ {
#if 0
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
#endif
return -ENOTTY; return -ENOTTY;
} }

View File

@ -74,40 +74,38 @@
* *
* Input Parameters: * Input Parameters:
* mac - Handle to the MAC layer instance * mac - Handle to the MAC layer instance
* rst_pibattr - Whether or not to reset the MAC PIB attributes to defaults * resetattr - Whether or not to reset the MAC PIB attributes to defaults
* *
****************************************************************************/ ****************************************************************************/
int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr) int mac802154_req_reset(MACHANDLE mac, bool resetattr)
{ {
FAR struct ieee802154_privmac_s * priv = FAR struct ieee802154_privmac_s * priv =
(FAR struct ieee802154_privmac_s *) mac; (FAR struct ieee802154_privmac_s *) mac;
union ieee802154_attr_u attr; union ieee802154_attr_u attr;
if (rst_pibattr) if (resetattr)
{ {
priv->isassoc = false; /* Not associated with a PAN */ priv->isassoc = false; /* Not associated with a PAN */
priv->trackingbeacon = false; /* Not tracking beacon by default */ priv->trackingbeacon = false; /* Not tracking beacon by default */
priv->sfspec.assocpermit = false; /* Device (if coord) not accepting ssociation */ priv->sfspec.assocpermit = false; /* Dev (if coord) not accepting assoc */
priv->autoreq = true; /* Auto send data req if addr. in beacon */ priv->autoreq = true; /* Auto send data req if addr in beacon */
priv->sfspec.ble = false; /* BLE disabled */ priv->sfspec.ble = false; /* BLE disabled */
priv->beaconpayloadlength = 0; /* Beacon payload NULL */ priv->beaconpayloadlength = 0; /* Beacon payload NULL */
priv->sfspec.beaconorder = 15; /* Non-beacon enabled network */ priv->sfspec.beaconorder = 15; /* Non-beacon enabled network */
priv->sfspec.sforder = 15; /* Length of active portion of outgoing SF */ priv->sfspec.sforder = 15; /* Length of active portion of outgoing SF */
priv->beacon_txtime = 0; /* Device never sent a beacon */ priv->beacon_txtime = 0; /* Device never sent a beacon */
#warning Set BSN and DSN to random values! priv->dsn = 0; /* Data sequence number */
priv->bsn = 0; priv->gtspermit = true; /* PAN Coord accepting GTS requests */
priv->dsn = 0; priv->minbe = 3; /* Min value of backoff exponent (BE) */
priv->gtspermit = true; /* PAN Coord accepting GTS requests */ priv->maxbe = 5; /* Max value of backoff exponent (BE) */
priv->minbe = 3; /* Min value of backoff exponent (BE) */ priv->max_csmabackoffs = 4; /* Max # of backoffs before failure */
priv->maxbe = 5; /* Max value of backoff exponent (BE) */ priv->maxretries = 3; /* Max # of retries allowed after failure */
priv->max_csmabackoffs = 4; /* Max # of backoffs before failure */ priv->promisc = false; /* Device not in promiscuous mode */
priv->maxretries = 3; /* Max # of retries allowed after failure */ priv->rngsupport = false; /* Ranging not yet supported */
priv->promisc = false; /* Device not in promiscuous mode */ priv->resp_waittime = 32; /* 32 SF durations */
priv->rngsupport = false; /* Ranging not yet supported */ priv->sec_enabled = false; /* Security disabled by default */
priv->resp_waittime = 32; /* 32 SF durations */ priv->tx_totaldur = 0; /* 0 transmit duration */
priv->sec_enabled = false; /* Security disabled by default */
priv->tx_totaldur = 0; /* 0 transmit duration */
priv->trans_persisttime = 0x01F4; priv->trans_persisttime = 0x01F4;
@ -125,35 +123,19 @@ int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr)
IEEE802154_SADDRCOPY(priv->addr.saddr, &IEEE802154_SADDR_UNSPEC); IEEE802154_SADDRCOPY(priv->addr.saddr, &IEEE802154_SADDR_UNSPEC);
IEEE802154_EADDRCOPY(priv->addr.eaddr, &IEEE802154_EADDR_UNSPEC); IEEE802154_EADDRCOPY(priv->addr.eaddr, &IEEE802154_EADDR_UNSPEC);
priv->radio->reset_attrs(priv->radio); priv->radio->reset(priv->radio);
/* The radio is in control of certain attributes, but we keep a mirror /* The radio is in control of certain attributes, but we keep a mirror
* for easy access. Copy in the radio's values now that they've been * for easy access. Copy in the radio's values now that they've been
* reset. * reset.
*/ */
priv->radio->get_attr(priv->radio, IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME, priv->radio->getattr(priv->radio, IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME,
&attr); &attr);
priv->max_frame_waittime = attr.mac.max_frame_waittime; priv->max_frame_waittime = attr.mac.max_frame_waittime;
/* These attributes are effected and determined based on the PHY. Need to mac802154_setdevmode(priv, IEEE802154_DEVMODE_ENDPOINT);
* figure out how to "share" attributes between the radio driver and this
* MAC layer
*
* macAckWaitDuration
* macBattLifeExtPeriods
* macMaxFrameTotalWaitTime
* macLIFSPeriod
* macSIFSPeriod
* macSyncSymbolOffset
* macTimestampSupported
* macTxControlActiveDuration
* macTxControlPauseDuration
* macRxOnWhenIdle
*/
} }
return OK; return OK;
} }

View File

@ -72,7 +72,9 @@
int mac802154_req_rxenable(MACHANDLE mac, int mac802154_req_rxenable(MACHANDLE mac,
FAR struct ieee802154_rxenable_req_s *req) FAR struct ieee802154_rxenable_req_s *req)
{ {
#if 0
FAR struct ieee802154_privmac_s * priv = FAR struct ieee802154_privmac_s * priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
#endif
return -ENOTTY; return -ENOTTY;
} }

View File

@ -60,7 +60,7 @@
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static void mac802154_scantimeout(FAR struct ieee802154_privmac_s *priv); static void mac802154_scantimeout(FAR void *arg);
/**************************************************************************** /****************************************************************************
* Public MAC Functions * Public MAC Functions
@ -93,6 +93,8 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
goto errout; goto errout;
} }
wlinfo("MLME: SCAN.request received\n");
/* Need to get access to the ops semaphore since operations are serial. This /* Need to get access to the ops semaphore since operations are serial. This
* must be done before locking the MAC so that we don't hold the MAC * must be done before locking the MAC so that we don't hold the MAC
*/ */
@ -108,7 +110,7 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
ret = mac802154_takesem(&priv->exclsem, true); ret = mac802154_lock(priv, true);
if (ret < 0) if (ret < 0)
{ {
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
@ -126,6 +128,8 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
{ {
case IEEE802154_SCANTYPE_PASSIVE: case IEEE802154_SCANTYPE_PASSIVE:
{ {
wlinfo("MLME: Starting Passive scan\n");
/* Set the channel to the first channel in the list */ /* Set the channel to the first channel in the list */
mac802154_setchannel(priv, req->channels[priv->scanindex]); mac802154_setchannel(priv, req->channels[priv->scanindex]);
@ -182,11 +186,11 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
break; break;
} }
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return OK; return OK;
errout_with_sem: errout_with_sem:
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
errout: errout:
return ret; return ret;
@ -201,7 +205,7 @@ void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
{ {
FAR struct ieee802154_notif_s * notif; FAR struct ieee802154_notif_s * notif;
mac802154_takesem(&priv->exclsem, false); mac802154_lock(priv, false);
mac802154_notif_alloc(priv, &notif, false); mac802154_notif_alloc(priv, &notif, false);
priv->curr_op = MAC802154_OP_NONE; priv->curr_op = MAC802154_OP_NONE;
@ -229,7 +233,7 @@ void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
mac802154_setpanid(priv, priv->panidbeforescan); mac802154_setpanid(priv, priv->panidbeforescan);
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
mac802154_notify(priv, notif); mac802154_notify(priv, notif);
} }
@ -247,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); DEBUGASSERT(priv->curr_op == MAC802154_OP_SCAN);
/* If we got here it means we are done scanning that channel */ /* If we got here it means we are done scanning that channel */

View File

@ -72,7 +72,7 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
/* Get exclusive access to the MAC */ /* Get exclusive access to the MAC */
ret = mac802154_takesem(&priv->exclsem, true); ret = mac802154_lock(priv, true);
if (ret < 0) if (ret < 0)
{ {
return ret; return ret;
@ -101,9 +101,9 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
/* Tell the radio layer to set the channel number and channel page */ /* Tell the radio layer to set the channel number and channel page */
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CHAN, priv->radio->setattr(priv->radio, IEEE802154_ATTR_PHY_CHAN,
(FAR const union ieee802154_attr_u *)&req->chan); (FAR const union ieee802154_attr_u *)&req->chan);
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_PAGE, priv->radio->setattr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_PAGE,
(FAR const union ieee802154_attr_u *)&req->chpage); (FAR const union ieee802154_attr_u *)&req->chpage);
/* The address used in the Source Address field of the beacon frame shall /* The address used in the Source Address field of the beacon frame shall
@ -147,11 +147,11 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
if (req->pancoord) if (req->pancoord)
{ {
priv->devmode = IEEE802154_DEVMODE_PANCOORD; mac802154_setdevmode(priv, IEEE802154_DEVMODE_PANCOORD);
} }
else else
{ {
priv->devmode = IEEE802154_DEVMODE_COORD; mac802154_setdevmode(priv, IEEE802154_DEVMODE_COORD);
} }
priv->sfspec.pancoord = req->pancoord; priv->sfspec.pancoord = req->pancoord;
@ -194,11 +194,11 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
} }
} }
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return OK; return OK;
errout: errout:
mac802154_givesem(&priv->exclsem); mac802154_unlock(priv)
return ret; return ret;
} }

View File

@ -71,8 +71,10 @@
int mac802154_req_sync(MACHANDLE mac, FAR struct ieee802154_sync_req_s *req) int mac802154_req_sync(MACHANDLE mac, FAR struct ieee802154_sync_req_s *req)
{ {
#if 0
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
#endif
return -ENOTTY; return -ENOTTY;
} }