diff --git a/Documentation/applications/wireless/i8sak/index.rst b/Documentation/applications/wireless/i8sak/index.rst index 22342e72ec635..d7bf623212fec 100644 --- a/Documentation/applications/wireless/i8sak/index.rst +++ b/Documentation/applications/wireless/i8sak/index.rst @@ -3,7 +3,7 @@ ================================================== Description ------------ +=========== The i8sak app is a useful CLI for testing various IEEE 802.15.4 functionality. It also serves as a starting place for learning how to interface with the NuttX @@ -30,7 +30,8 @@ _sticky_, meaning, if you set the endpoint short address once, any future operation using the endpoint short address can default to the previously used address. This is particularly useful to keep the command lengths down. -## How To Use +How To Use +========== The i8sak app has a series of CLI functions that can be invoked. The default i8sak command is ``i8`` to make things quick and easy to type. @@ -47,6 +48,11 @@ This will tell the MAC layer that it should now act as a PAN coordinator using PAN ID CD:AB. For now, this function assumes that we are operating a non-beacon enabled PAN, since, as of this writing, beacon-enabled networks are unfinished. +Configure PAN coordinator short address and EP short addres:: + + i8 set saddr 0A:00 + i8 set ep_saddr 0B:00 + Next, on the same device, run:: i8 acceptassoc @@ -117,7 +123,7 @@ similar to the following:: Dest. Address - 0xDEADBEEF00FADE0C Src. Address - 0xDEADBEEF00FADE0A Command Type - Association Response - Assigned SADDR - 0x000C + Assigned SADDR - 0x000B Assoc Status - Successful 3a) ACK diff --git a/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst b/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst index 04c565c507fd5..f48585f774a08 100644 --- a/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst +++ b/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst @@ -138,3 +138,20 @@ usbnsh ------ Basic NuttShell configuration (CDCACM console enabled in USB Port, at 115200 bps). + +ieee802154_6lowpan +------------------ + +Cheat Sheet. Here is a concise summary of all all the steps needed to +run the UDP test (C=Coordinator; E=Endpoint):: + + C: nsh> i8 wpan0 startpan cd:ab + C: nsh> i8 set saddr 0A:00 + C: nsh> i8 set ep_saddr 0B:00 + C: nsh> i8 acceptassoc + E: nsh> i8 wpan0 assoc + C: nsh> ifup wpan0 + C: nsh> ifconfig <-- To get the + E: nsh> ifup wpan0 + C: nsh> udpserver & + E: nsh> udpclient & diff --git a/Documentation/platforms/arm/nrf52/ieee802154.rst b/Documentation/platforms/arm/nrf52/ieee802154.rst new file mode 100644 index 0000000000000..d3e6c4263a608 --- /dev/null +++ b/Documentation/platforms/arm/nrf52/ieee802154.rst @@ -0,0 +1,47 @@ +========================== +Nordic nRF52 IEEE 802.15.4 +========================== + +.. note:: + + This driver is highly experimental. + Help with development and testing will be appreciated ;) + +Basic support for IEEE 802.15.4 can be found in +``arch/arm/src/nrf52/ieee802154``. + +Supported features: + +* frame transmission +* frame reception and filtering +* immediate ACK (incoming and outgoing) +* promiscuous mode +* delayed transmision +* radio events trace +* setting pending bit for all incoming Data Request frames +* un-slotted CSMA-CA + +Work in progres features (some logic is present, but needs more work): + +* slotted CSMA-CA +* GTS +* beacon transmision + +Fetures not implemented: + +* enhanced ACK (Enh-ACK) +* enhanced beacon +* low power mode +* advanced features from IEEE 802.15.4e + +Reserved peripherals +==================== + +This implementation reserves the following peripherals: + +* ``RADIO`` - used for radio operations + +* ``TIMER0`` - used as high resolution timer for ACK, IFS and other radio delays + +* ``RTC0`` - if superframe support is enabled, used as low power timer to hande + superframe events diff --git a/Documentation/platforms/arm/nrf52/index.rst b/Documentation/platforms/arm/nrf52/index.rst index 2bb73de03cf4e..912422ee17ec8 100644 --- a/Documentation/platforms/arm/nrf52/index.rst +++ b/Documentation/platforms/arm/nrf52/index.rst @@ -51,9 +51,9 @@ Peripheral Support The following list indicates peripherals supported in NuttX: -========== ======= ===== +========== ======= =============== Peripheral Support Notes -========== ======= ===== +========== ======= =============== GPIO Yes GPIOTE Yes I2S No @@ -64,7 +64,7 @@ PPI Yes PWM Yes QDEC No QSPI Yes -RADIO Yes Basic +RADIO Yes BLE, IEEE 802.15.4 RNG Yes RTC Yes SAADC Yes @@ -78,7 +78,7 @@ UART Yes UARTE No USBD Yes WDT Yes -========== ======= ===== +========== ======= =============== Peripherals such as AAR, ACL, CCM, ECB are not directly used by NuttX since they are part of BLE controller implementation (link). @@ -206,6 +206,11 @@ is provided with settings already set. Note that in this case, some peripherals (mostly those related to BLE) will be unavailable. Some PPI channels will also be ocuppied (``NRF52_PPI_NUM_CONFIGURABLE_CHANNELS`` will be set accordingly in this case). +IEEE 802.15.4 Support +===================== + +Details about IEEE 802.15.4 support for nRF52 can be found in :doc:`ieee802154`. + Supported Boards ================ @@ -214,3 +219,4 @@ Supported Boards :maxdepth: 1 boards/*/* + ieee802154.rst diff --git a/Kconfig b/Kconfig index 69c13823d9843..4775813184f45 100644 --- a/Kconfig +++ b/Kconfig @@ -2230,6 +2230,38 @@ config DEBUG_PCI_INFO Enable PCI driver informational output to SYSLOG. endif # DEBUG_PCI + +config DEBUG_RPMSG + bool "RPMSG Debug Features" + default n + depends on RPMSG + ---help--- + Enable RPMSG driver debug features. + +if DEBUG_RPMSG + +config DEBUG_RPMSG_ERROR + bool "RPMSG Error Output" + default n + depends on DEBUG_ERROR + ---help--- + Enable RPMSG driver error output to SYSLOG. + +config DEBUG_RPMSG_WARN + bool "RPMSG Warnings Output" + default n + depends on DEBUG_WARN + ---help--- + Enable RPMSG driver warning output to SYSLOG. + +config DEBUG_RPMSG_INFO + bool "RPMSG Informational Output" + default n + depends on DEBUG_INFO + ---help--- + Enable RPMSG driver informational output to SYSLOG. + +endif # DEBUG_RPMSG endif # DEBUG_FEATURES config ARCH_HAVE_STACKCHECK diff --git a/arch/arm/src/nrf52/CMakeLists.txt b/arch/arm/src/nrf52/CMakeLists.txt index 409db39c17766..cb21326482502 100644 --- a/arch/arm/src/nrf52/CMakeLists.txt +++ b/arch/arm/src/nrf52/CMakeLists.txt @@ -94,6 +94,20 @@ endif() if(CONFIG_NRF52_RADIO) list(APPEND SRCS nrf52_radio.c) + + if(CONFIG_NRF52_RADIO_IEEE802154) + list(APPEND SRCS ieee802154/nrf52_ieee802154_radio.c) + list(APPEND SRCS ieee802154/nrf52_ieee802154_tim.c) + list(APPEND SRCS ieee802154/nrf52_ieee802154.c) + + if(CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME) + list(APPEND SRCS ieee802154/nrf52_ieee802154_rtc.c) + endif() + + if(CONFIG_NRF52_RADIO_IEEE802154_TRACE) + list(APPEND SRCS ieee802154/nrf52_ieee802154_trace.c) + endif() + endif() endif() if(CONFIG_NRF52_TIMER) diff --git a/arch/arm/src/nrf52/Kconfig b/arch/arm/src/nrf52/Kconfig index 2bde7f31047d3..5bd0a293bb182 100644 --- a/arch/arm/src/nrf52/Kconfig +++ b/arch/arm/src/nrf52/Kconfig @@ -42,6 +42,8 @@ config ARCH_CHIP_NRF52840 select NRF52_HAVE_USBDEV select NRF52_HAVE_PWM3 select NRF52_HAVE_CRYPTOCELL + select NRF52_HAVE_IEEE802154 + select NRF52_HAVE_BLELR endchoice # NRF52 Chip Selection @@ -134,6 +136,14 @@ config NRF52_HAVE_CRYPTOCELL bool default n +config NRF52_HAVE_BLELE + bool + default n + +config NRF52_HAVE_IEEE802154 + bool + default n + # Peripheral Selection config NRF52_I2C_MASTER @@ -611,6 +621,52 @@ endif # NRF52_PWM endmenu # PWM configuration +menu "RADIO Configuration" + +if NRF52_RADIO + +config NRF52_RADIO_CUSTOM + bool "RADIO uses custom IRQ handlers" + default n + +config NRF52_RADIO_IEEE802154 + bool "RADIO IEEE802.15.4 protocol" + default n + depends on NRF52_HAVE_IEEE802154 + select ARMV7M_USEBASEPRI + select ARCH_RAMVECTORS + select ARCH_IRQPRIO + select NRF52_RADIO_CUSTOM + select NRF52_TIMER0 + +if NRF52_RADIO_IEEE802154 + +config NRF52_RADIO_IEEE802154_SUPERFRAME + bool "RADIO IEEE802.15.4 superframe support" + default n + select NRF52_RTC0 + select NRF52_USE_LFCLK + +config NRF52_RADIO_IEEE802154_GTS_SLOTS + int "RADIO IEEE802.15.4 GTS slots" + default 2 + depends on NRF52_RADIO_IEEE802154_SUPERFRAME + +config NRF52_RADIO_IEEE802154_TRACE + bool "RADIO IEEE802.15.4 trace support" + default n + +config NRF52_RADIO_IEEE802154_TRACE_BUFSIZE + int "RADIO IEEE802.15.4 trace buffer size" + depends on NRF52_RADIO_IEEE802154_TRACE + default 1024 + +endif + +endif #NRF52_RADIO + +endmenu # "RADIO Configuration" + menu "SAADC Configuration" if NRF52_SAADC diff --git a/arch/arm/src/nrf52/Make.defs b/arch/arm/src/nrf52/Make.defs index c570f66ff4bcb..cf70c38da56bd 100644 --- a/arch/arm/src/nrf52/Make.defs +++ b/arch/arm/src/nrf52/Make.defs @@ -88,7 +88,21 @@ CHIP_CSRCS += nrf52_ppi.c endif ifeq ($(CONFIG_NRF52_RADIO),y) -CHIP_CSRCS += nrf52_radio.c + CHIP_CSRCS += nrf52_radio.c + + ifeq ($(CONFIG_NRF52_RADIO_IEEE802154),y) + CHIP_CSRCS += ieee802154/nrf52_ieee802154_radio.c + CHIP_CSRCS += ieee802154/nrf52_ieee802154_tim.c + CHIP_CSRCS += ieee802154/nrf52_ieee802154.c + + ifeq ($(CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME),y) + CHIP_CSRCS += ieee802154/nrf52_ieee802154_rtc.c + endif + + ifeq ($(CONFIG_NRF52_RADIO_IEEE802154_TRACE),y) + CHIP_CSRCS += ieee802154/nrf52_ieee802154_trace.c + endif + endif endif ifeq ($(CONFIG_NRF52_TIMER),y) diff --git a/arch/arm/src/nrf52/hardware/nrf52_radio.h b/arch/arm/src/nrf52/hardware/nrf52_radio.h index 14f16753c8575..d58793976ce1b 100644 --- a/arch/arm/src/nrf52/hardware/nrf52_radio.h +++ b/arch/arm/src/nrf52/hardware/nrf52_radio.h @@ -206,146 +206,6 @@ /* Register Bitfield Definitions ********************************************/ -/* TASKS_TXEN Register */ - -#define RADIO_TASKS_TXEN (1 << 0) /* Bit 0: Enable RADIO in TX mode */ - -/* TASKS_RXEN Register */ - -#define RADIO_TASKS_RXEN (1 << 0) /* Bit 0: Enable RADIO in RX mode */ - -/* TASKS_START Register */ - -#define RADIO_TASKS_START (1 << 0) /* Bit 0: Start RADIO */ - -/* TASKS_STOP Register */ - -#define RADIO_TASKS_STOP (1 << 0) /* Bit 0: Stop RADIO */ - -/* TASKS_DISABLE Register */ - -#define RADIO_TASKS_DISABLE (1 << 0) /* Bit 0: Disable RADIO */ - -/* TASKS_RSSISTART Register */ - -#define RADIO_TASKS_RSSISTART (1 << 0) /* Bit 0: Start the RSSI */ - -/* TASKS_RSSISTOP Register */ - -#define RADIO_TASKS_RSSISTOP (1 << 0) /* Bit 0: Stop the RSSI */ - -/* TASKS_BCSTART Register */ - -#define RADIO_TASKS_BCSTART (1 << 0) /* Bit 0: Start the bit counter */ - -/* TASKS_BCSTOP Register */ - -#define RADIO_TASKS_BCSTOP (1 << 0) /* Bit 0: Stop the bit counter */ - -/* TASKS_EDSTART Register */ - -#define RADIO_TASKS_EDSTART (1 << 0) /* Bit 0: Start the energy detect measurement (IEEE 802.15.4) */ - -/* TASKS_EDSTOP Register */ - -#define RADIO_TASKS_EDSTOP (1 << 0) /* Bit 0: Stop the energy detect measurement (IEEE 802.15.4) */ - -/* TASKS_CCASTART Register */ - -#define RADIO_TASKS_CCASTART (1 << 0) /* Bit 0: Start the channel assessment (IEEE 802.15.4) */ - -/* TASKS_CCASTOP Register */ - -#define RADIO_TASKS_CCASTOP (1 << 0) /* Bit 0: Stop the channel assessment (IEEE 802.15.4) */ - -/* EVENTS_READY Register */ - -#define RADIO_EVENTS_READY (1 << 0) /* Bit 0: RADIO has ramped up and is ready to be started */ - -/* EVENTS_ADDRESS Register */ - -#define RADIO_EVENTS_ADDRESS (1 << 0) /* Bit 0: Address sent or received */ - -/* EVENTS_PAYLOAD Register */ - -#define RADIO_EVENTS_PAYLOAD (1 << 0) /* Bit 0: Packet payload sent or received */ - -/* EVENTS_END Register */ - -#define RADIO_EVENTS_END (1 << 0) /* Bit 0: Packet sent or received */ - -/* EVENTS_DISABLED Register */ - -#define RADIO_EVENTS_DISABLED (1 << 0) /* Bit 0: RADIO has been disabled */ - -/* EVENTS_DEVMATCH Register */ - -#define RADIO_EVENTS_DEVMATCH (1 << 0) /* Bit 0: A device address match */ - -/* EVENTS_DEVMISS Register */ - -#define RADIO_EVENTS_DEVMISS (1 << 0) /* Bit 0: No device address match */ - -/* EVENTS_RSSIEND Register */ - -#define RADIO_EVENTS_RSSIEND (1 << 0) /* Bit 0: Sampling of receive signal strength complete */ - -/* EVENTS_BCMATCH Register */ - -#define RADIO_EVENTS_BCMATCH (1 << 0) /* Bit 0: Bit counter reached bit count value */ - -/* EVENTS_CRCOK Register */ - -#define RADIO_EVENTS_CRCOK (1 << 0) /* Bit 0: Packet received with CRC ok */ - -/* EVENTS_CRCERROR Register */ - -#define RADIO_EVENTS_CRCERROR (1 << 0) /* Bit 0: Packet received with CRC error */ - -/* EVENTS_FRAMESTART Register */ - -#define RADIO_EVENTS_FRAMESTART (1 << 0) /* Bit 0: IEEE 802.15.4 length field received*/ - -/* EVENTS_EDEND Register */ - -#define RADIO_EVENTS_EDEND (1 << 0) /* Bit 0: ampling of energy detection complete */ - -/* EVENTS_EDSTOPPED Register */ - -#define RADIO_EVENTS_EDSTOPPED (1 << 0) /* Bit 0: The sampling of energy detection has stopped */ - -/* EVENTS_CCAIDLE Register */ - -#define RADIO_EVENTS_CCAIDLE (1 << 0) /* Bit 0: Wireless medium in idle */ - -/* EVENTS_CCABUSY Register */ - -#define RADIO_EVENTS_CCABUSY (1 << 0) /* Bit 0: Wireless medium busy */ - -/* EVENTS_CCASTOPPED Register */ - -#define RADIO_EVENTS_CCASTOPPED (1 << 0) /* Bit 0: The CCA has stopped */ - -/* EVENTS_RATEBOOST Register */ - -#define RADIO_EVENTS_RATEBOOST (1 << 0) /* Bit 0: Ble_LR CI field received */ - -/* EVENTS_TXREADY Register */ - -#define RADIO_EVENTS_TXREADY (1 << 0) /* Bit 0: RADIO has ramped up and is ready to be started TX path */ - -/* EVENTS_RXREADY Register */ - -#define RADIO_EVENTS_RXREADY (1 << 0) /* Bit 0: RADIO has ramped up and is ready to be started RX path */ - -/* EVENTS_MHRMATCH Register */ - -#define RADIO_EVENTS_MHRMATCH (1 << 0) /* Bit 0: MAC header match found */ - -/* EVENTS_PHYEND Register */ - -#define RADIO_EVENTS_PHYEND (1 << 0) /* Bit 0: Last bit is sent on air */ - /* SHORTS Register */ #define RADIO_SHORTS_READY_START (1 << 0) /* Bit 0: Shortcut between event READY and task START */ @@ -622,6 +482,12 @@ # define RADIO_CCACTRL_CCAMODE_CANDED (2 << RADIO_CCACTRL_CCAMODE_SHIFT) # define RADIO_CCACTRL_CCAMODE_CORED (3 << RADIO_CCACTRL_CCAMODE_SHIFT) # define RADIO_CCACTRL_CCAMODE_EDTST1 (4 << RADIO_CCACTRL_CCAMODE_SHIFT) +#define RADIO_CCACTRL_CCAEDTHRES_SHIFT (8) +#define RADIO_CCACTRL_CCAEDTHRES_MASK (0xff << RADIO_CCACTRL_CCAEDTHRES_SHIFT) +#define RADIO_CCACTRL_CCACORRTHRES_SHIFT (16) +#define RADIO_CCACTRL_CCACORRTHRES_MASK (0xff << RADIO_CCACTRL_CCACORRTHRES_SHIFT) +#define RADIO_CCACTRL_CCACORRCNT_SHIFT (24) +#define RADIO_CCACTRL_CCACORRCNT_MASK (0xff << RADIO_CCACTRL_CCACORRCNT_SHIFT) /* POWER Register */ diff --git a/arch/arm/src/nrf52/hardware/nrf52_utils.h b/arch/arm/src/nrf52/hardware/nrf52_utils.h index 4ecbc1ce7dfb0..069234bc1f7eb 100644 --- a/arch/arm/src/nrf52/hardware/nrf52_utils.h +++ b/arch/arm/src/nrf52/hardware/nrf52_utils.h @@ -27,6 +27,8 @@ #include +#include "arm_internal.h" + /**************************************************************************** * Public Function Prototypes / Inline Functions ****************************************************************************/ diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.c b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.c new file mode 100644 index 0000000000000..89f29d13176e6 --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.c @@ -0,0 +1,998 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include + +#include "nrf52_ieee802154_trace.h" + +#include "nrf52_ieee802154.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_NRF52_RADIO_CUSTOM +# error RADIO custom interrupts must be enabled +#endif + +#ifndef CONFIG_SCHED_HPWORK +# error High priority work queue required in this driver +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* IEEE 802.15.4 radio data */ + +static struct nrf52_radioi8_dev_s g_nrf52_radioi8; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Set/get radio attributes */ + +static int nrf52_radioi8_setrxmode(struct nrf52_radioi8_dev_s *dev, + int mode); +static int nrf52_radioi8_setpanid(struct nrf52_radioi8_dev_s *dev, + const uint8_t *panid); +static int nrf52_radioi8_setsaddr(struct nrf52_radioi8_dev_s *dev, + const uint8_t *saddr); +static int nrf52_radioi8_seteaddr(struct nrf52_radioi8_dev_s *dev, + const uint8_t *eaddr); +static int nrf52_radioi8_setcoordsaddr(struct nrf52_radioi8_dev_s *dev, + const uint8_t *saddr); +static int nrf52_radioi8_setdevmode(struct nrf52_radioi8_dev_s *dev, + uint8_t mode); + +/* Radio ops */ + +static int nrf52_radioi8_bind(struct ieee802154_radio_s *radio, + struct ieee802154_radiocb_s *radiocb); +static int nrf52_radioi8_reset(struct ieee802154_radio_s *radio); +static int nrf52_radioi8_getattr(struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + union ieee802154_attr_u *attrval); +static int nrf52_radioi8_setattr(struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + const union ieee802154_attr_u *attrval); +static int nrf52_radioi8_txnotify(struct ieee802154_radio_s *radio, + bool gts); +static int nrf52_radioi8_txdelayed(struct ieee802154_radio_s *radio, + struct ieee802154_txdesc_s *txdesc, + uint32_t symboldelay); +static int nrf52_radioi8_rxenable(struct ieee802154_radio_s *radio, + bool enable); +static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev, + uint8_t chan); +static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_cca_s *cca); +static int nrf52_radioi8_energydetect(struct ieee802154_radio_s *radio, + uint32_t nsymbols); + +static int +nrf52_radioi8_beaconstart(struct ieee802154_radio_s *radio, + const struct ieee802154_superframespec_s *sfspec, + struct ieee802154_beaconframe_s *beacon); +static int +nrf52_radioi8_beaconupdate(struct ieee802154_radio_s *radio, + struct ieee802154_beaconframe_s *beacon); +static int nrf52_radioi8_beaconstop(struct ieee802154_radio_s *radio); +static int +nrf52_radioi8_sfupdate(struct ieee802154_radio_s *radio, + const struct ieee802154_superframespec_s *sfspec); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_setrxmode + * + * Description: + * Set the RX mode (normal, promiscuous, no CRC). + * + ****************************************************************************/ + +static int nrf52_radioi8_setrxmode(struct nrf52_radioi8_dev_s *dev, + int mode) +{ + wlinfo("setrxmode %d\n", mode); + + if (mode < NRF52_RXMODE_NORMAL || mode > NRF52_RXMODE_NOCRC) + { + return -EINVAL; + } + + dev->state.rxmode = mode; + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setpanid + * + * Description: + * Define the PAN ID the device is operating on. + * + ****************************************************************************/ + +static int nrf52_radioi8_setpanid(struct nrf52_radioi8_dev_s *dev, + const uint8_t *panid) +{ + wlinfo("setpanid: %02X:%02X\n", panid[0], panid[1]); + IEEE802154_PANIDCOPY(dev->state.addr.panid, panid); + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setsaddr + * + * Description: + * Define the device short address. The following addresses are special: + * + * FFFEh : Broadcast + * FFFFh : Unspecified + * + ****************************************************************************/ + +static int nrf52_radioi8_setsaddr(struct nrf52_radioi8_dev_s *dev, + const uint8_t *saddr) +{ + wlinfo("setsaddr: %02X:%02X\n", saddr[0], saddr[1]); + IEEE802154_SADDRCOPY(dev->state.addr.saddr, saddr); + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_seteaddr + * + * Description: + * Define the device extended address. The following addresses are special: + * + * ffffffffffffffffh : Unspecified + * + ****************************************************************************/ + +static int nrf52_radioi8_seteaddr(struct nrf52_radioi8_dev_s *dev, + const uint8_t *eaddr) +{ + int i = 0; + + wlinfo("seteaddr: %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]); + + for (i = 0; i < 8; i++) + { + dev->state.addr.eaddr[i] = eaddr[i]; + } + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setcoordsaddr + * + * Description: + * Define the coordinator short address. The following addresses are + * special: + * + * FFFEh : Broadcast + * FFFFh : Unspecified + * + ****************************************************************************/ + +static int nrf52_radioi8_setcoordsaddr(struct nrf52_radioi8_dev_s *dev, + const uint8_t *saddr) +{ + IEEE802154_SADDRCOPY(dev->state.addr.saddr, saddr); + + wlinfo("setcoordsaddr: %02X:%02X\n", saddr[0], saddr[1]); + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setcoordeaddr + * + * Description: + * Define the coordinator extended address. The following addresses are + * special: + * + * FFFFFFFFFFFFFFFFh : Unspecified + * + ****************************************************************************/ + +static int nrf52_radioi8_setcoordeaddr(struct nrf52_radioi8_dev_s *dev, + const uint8_t *eaddr) +{ + int i = 0; + + wlinfo("setcoordeaddr: %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]); + + for (i = 0; i < 8; i++) + { + dev->state.addr.eaddr[i] = eaddr[i]; + } + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setdevmode + * + * Description: + * Define the device behaviour: endpoint, coord or PAN coord. + * + ****************************************************************************/ + +static int nrf52_radioi8_setdevmode(struct nrf52_radioi8_dev_s *dev, + uint8_t mode) +{ + wlinfo("setdevmode %d\n", mode); + + if (mode < IEEE802154_DEVMODE_ENDPOINT || + mode > IEEE802154_DEVMODE_PANCOORD) + { + return -EINVAL; + } + + dev->state.devmode = mode; + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_bind + * + * Description: + * Bind radio callbacks. + * + ****************************************************************************/ + +static int nrf52_radioi8_bind(struct ieee802154_radio_s *radio, + struct ieee802154_radiocb_s *radiocb) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + + DEBUGASSERT(dev != NULL); + dev->radiocb = radiocb; + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_reset + * + * Description: + * Reset radio. + * + ****************************************************************************/ + +static int nrf52_radioi8_reset(struct ieee802154_radio_s *radio) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + struct ieee802154_cca_s cca; + int ret = OK; + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_TRACE + /* Reset trace */ + + nrf52_radioi8_trace_init(); +#endif + + /* Reset radio state */ + + memset(&dev->state, 0, sizeof(struct nrf52_radioi8_state_s)); + + /* Initialize radio in IEEE 802.15.4 mode */ + + ret = dev->radio->ops->reset(dev->radio); + if (ret < 0) + { + goto errout; + } + + /* Reset TIMER */ + + dev->tim->ops->reset(dev); + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* Reset RTC */ + + dev->rtc->ops->reset(dev); +#endif + + /* Set channel */ + + nrf52_radioi8_setchannel(dev, 11); + + /* Configure default CCA: + * - CCA mode ED + * - no carrier sense + * - recommenced ED threshold -69 dBm + */ + + cca.use_ed = 1; + cca.use_cs = 0; + cca.edth = 0x60; + cca.csth = 0x00; + nrf52_radioi8_setcca(dev, &cca); + + /* Configure initial RX mode */ + + nrf52_radioi8_setrxmode(dev, NRF52_RXMODE_NORMAL); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf52_radioi8_getattr + * + * Description: + * Get radio attribute. + * + ****************************************************************************/ + +static int nrf52_radioi8_getattr(struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + union ieee802154_attr_u *attrval) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + int ret = OK; + + switch (attr) + { + case IEEE802154_ATTR_MAC_EADDR: + { + memcpy(&attrval->mac.eaddr[0], &dev->state.addr.eaddr[0], 8); + ret = IEEE802154_STATUS_SUCCESS; + break; + } + + case IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME: + { + attrval->mac.max_frame_waittime = + dev->radio->state.max_frame_waittime; + ret = IEEE802154_STATUS_SUCCESS; + break; + } + + case IEEE802154_ATTR_PHY_SYMBOL_DURATION: + { + attrval->phy.symdur_picosec = (IEEE802154_SYMBOL_US * 1000000); + ret = IEEE802154_STATUS_SUCCESS; + break; + } + + case IEEE802154_ATTR_PHY_CHAN: + { + attrval->phy.chan = dev->state.chan; + ret = IEEE802154_STATUS_SUCCESS; + break; + } + + case IEEE802154_ATTR_PHY_FCS_LEN: + { + attrval->phy.fcslen = 2; + ret = IEEE802154_STATUS_SUCCESS; + break; + } + + case IEEE802154_ATTR_PHY_REGDUMP: + { + NRF52_RADIO_DUMPREGS(dev->radio->lower); + break; + } + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_TRACE + case IEEE802154_ATTR_PHY_TRACEDUMP: + { + nrf52_radioi8_trace_dump(); + break; + } +#endif + + default: + { + ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; + break; + } + } + + return ret; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setattr + * + * Description: + * Set radio attribute. + * + ****************************************************************************/ + +static int nrf52_radioi8_setattr(struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + const union ieee802154_attr_u *attrval) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + int ret = IEEE802154_STATUS_SUCCESS; + + switch (attr) + { + case IEEE802154_ATTR_MAC_PANID: + { + nrf52_radioi8_setpanid(dev, attrval->mac.panid); + break; + } + + case IEEE802154_ATTR_MAC_SADDR: + { + nrf52_radioi8_setsaddr(dev, attrval->mac.saddr); + break; + } + + case IEEE802154_ATTR_MAC_EADDR: + { + nrf52_radioi8_seteaddr(dev, attrval->mac.eaddr); + break; + } + + case IEEE802154_ATTR_MAC_COORD_SADDR: + { + nrf52_radioi8_setcoordsaddr(dev, attrval->mac.coordsaddr); + break; + } + + case IEEE802154_ATTR_MAC_COORD_EADDR: + { + nrf52_radioi8_setcoordeaddr(dev, attrval->mac.coordeaddr); + break; + } + + case IEEE802154_ATTR_MAC_PROMISCUOUS_MODE: + { + if (attrval->mac.promisc_mode) + { + nrf52_radioi8_setrxmode(dev, NRF52_RXMODE_PROMISC); + } + else + { + nrf52_radioi8_setrxmode(dev, NRF52_RXMODE_NORMAL); + } + break; + } + + case IEEE802154_ATTR_PHY_CHAN: + { + nrf52_radioi8_setchannel(dev, attrval->phy.chan); + break; + } + + case IEEE802154_ATTR_MAC_DEVMODE: + { + nrf52_radioi8_setdevmode(dev, attrval->mac.devmode); + break; + } + + default: + { + ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; + break; + } + } + + return ret; +} + +/**************************************************************************** + * Name: nrf52_radioi8_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. + * + ****************************************************************************/ + +static int nrf52_radioi8_txnotify(struct ieee802154_radio_s *radio, + bool gts) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + int ret = OK; + + if (gts) + { + ret = dev->radio->ops->gts_poll(dev); + } + else + { + ret = dev->radio->ops->csma_poll(dev); + } + + return ret; +} + +/**************************************************************************** + * Name: nrf52_radioi8_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. + * + ****************************************************************************/ + +static int nrf52_radioi8_txdelayed(struct ieee802154_radio_s *radio, + struct ieee802154_txdesc_s *txdesc, + uint32_t symboldelay) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + int ret = OK; + + /* Get exclusive access to the radio device */ + + ret = nxmutex_lock(&dev->lock); + if (ret < 0) + { + return ret; + } + + /* There should never be more than one of these transactions at once. */ + + DEBUGASSERT(!dev->state.txdelayed_busy); + + dev->state.txdelayed_desc = txdesc; + dev->state.txdelayed_busy = true; + +#warning DO WE NEED THIS ? do we need reschedule_csma + if (dev->radio->state.csma_busy) + { + dev->state.reschedule_csma = true; + } + + /* Wait for ACKTX done - we start transmition in + * nrf52_radioi8_state_acktx() + */ + + if (dev->radio->state.state == NRF52_RADIO_STATE_ACKTX) + { + goto out; + } + + /* Setup TX */ + + dev->radio->ops->norm_setup(dev, txdesc->frame, false); + + if (symboldelay == 0) + { + /* Send now */ + + dev->radio->ops->norm_trigger(dev); + } + else + { + /* Run TIMER - TX is handled in timer isr */ + + dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_TXDELAY, symboldelay); + } + +out: + nxmutex_unlock(&dev->lock); + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_rxenable + * + * Description: + * Enable/Disable receiver. + * + ****************************************************************************/ + +static int nrf52_radioi8_rxenable(struct ieee802154_radio_s *radio, + bool enable) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + + wlinfo("rxenable %d\n", enable); + return dev->radio->ops->rxenable(dev, enable); +} + +/**************************************************************************** + * Name: nrf52_radioi8_energydetect + * + * Description: + * Start the energy detect measurement. + * + ****************************************************************************/ + +static int nrf52_radioi8_energydetect(struct ieee802154_radio_s *radio, + uint32_t nsymbols) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + + return dev->radio->ops->energydetect(dev, nsymbols); +} + +/**************************************************************************** + * Name: nrf52_radioi8_setchannel + * + * Description: + * Define the current radio channel the device is operating on. + * In the 2.4 GHz, there are 16 channels, each 2 MHz wide, 5 MHz spacing: + * + * Chan MHz Chan MHz Chan MHz Chan MHz + * 11 2405 15 2425 19 2445 23 2465 + * 12 2410 16 2430 20 2450 24 2470 + * 13 2415 17 2435 21 2455 25 2475 + * 14 2420 18 2440 22 2460 26 2480 + * + ****************************************************************************/ + +static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev, + uint8_t chan) +{ + int ret = OK; + + wlinfo("setchannel: %u\n", (unsigned)chan); + + if (dev->state.chan == chan) + { + return OK; + } + + if (chan < 11 || chan > 26) + { + wlerr("Invalid chan: %d\n", chan); + return -EINVAL; + } + + ret = dev->radio->ops->setchannel(dev, chan); + if (ret < 0) + { + wlerr("dev->radio->ops->setchannel failed %d\n", ret); + return -EINVAL; + } + + dev->state.chan = chan; + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setcca + * + * Description: + * Define the Clear Channel Assessement method. + * + ****************************************************************************/ + +static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_cca_s *cca) +{ + int ret = OK; + + if (!cca->use_ed && !cca->use_cs) + { + return -EINVAL; + } + + if (cca->use_cs && cca->csth > 0x0f) + { + return -EINVAL; + } + + /* Configure CCA */ + + ret = dev->radio->ops->setcca(dev, cca); + if (ret < 0) + { + wlerr("dev->radio->ops->setcca failed %d\n", ret); + return -EINVAL; + } + + memcpy(&dev->state.cca, cca, sizeof(struct ieee802154_cca_s)); + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_beaconstart + * + * Description: + * Start beacon. + * + ****************************************************************************/ + +static int +nrf52_radioi8_beaconstart(struct ieee802154_radio_s *radio, + const struct ieee802154_superframespec_s *sfspec, + struct ieee802154_beaconframe_s *beacon) +{ +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + irqstate_t flags; + + if (sfspec->pancoord) + { + flags = enter_critical_section(); + + /* Local copy */ + + memcpy(&dev->state.sf, (void *)sfspec, + sizeof(struct ieee802154_superframespec_s)); + + /* Setup beacon transmition */ + + dev->radio->ops->beacon_setup(dev, beacon->bf_data, beacon->bf_len); + + /* Configure RTC events */ + + dev->rtc->ops->setup(dev, &dev->state.sf); + + /* Start RTC */ + + dev->rtc->ops->start(dev); + + leave_critical_section(flags); + } + else + { + /* TODO: missing logic for non-PAN coord */ + + return -ENOTTY; + } + + return OK; +#else + return -ENOTSUP; +#endif +} + +/**************************************************************************** + * Name: nrf52_radioi8_beaconupdate + * + * Description: + * Update beacon. + * + ****************************************************************************/ + +static int +nrf52_radioi8_beaconupdate(struct ieee802154_radio_s *radio, + struct ieee802154_beaconframe_s *beacon) +{ +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Arm the beacon TX buffer */ + + memcpy(&dev->radio->beaconbuf[1], beacon->bf_data, beacon->bf_len); + + /* Length = Frame data + CRC */ + + dev->radio->beaconbuf[0] = beacon->bf_len + 2; + + leave_critical_section(flags); + + return OK; +#else + return -ENOTSUP; +#endif +} + +/**************************************************************************** + * Name: nrf52_radioi8_beaconstop + * + * Description: + * Stop beacon. + * + ****************************************************************************/ + +static int nrf52_radioi8_beaconstop(struct ieee802154_radio_s *radio) +{ +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Stop RTC */ + + dev->rtc->ops->stop(dev); + + leave_critical_section(flags); + + return OK; +#else + return -ENOTSUP; +#endif +} + +/**************************************************************************** + * Name: nrf52_radioi8_sfupdate + * + * Description: + * Update super frame. + * + ****************************************************************************/ + +static int +nrf52_radioi8_sfupdate(struct ieee802154_radio_s *radio, + const struct ieee802154_superframespec_s *sfspec) +{ +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Local copy */ + + memcpy(&dev->state.sf, (void *)sfspec, + sizeof(struct ieee802154_superframespec_s)); + + /* If we are operating on a beacon-enabled network, use slotted CSMA */ + + if (sfspec->beaconorder < 15) + { + /* Need slotted CSMA-CA */ + + dev->radio->state.slotted = true; + + /* Configure RTC */ + + dev->rtc->ops->setup(dev, &dev->state.sf); + + /* Wait for beacon to sync */ + + dev->radio->state.wait_for_beacon = true; + } + else + { + /* Need un-slotted CSMA-CA */ + + dev->radio->state.slotted = false; + } + + leave_critical_section(flags); + + return OK; +#else + return -ENOTSUP; +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_register + * + * Description: + * Register NRF52 radio in IEE802154 mode. + * + ****************************************************************************/ + +struct ieee802154_radio_s * +nrf52_radioi8_register(struct nrf52_radio_board_s *board) +{ + struct nrf52_radioi8_dev_s *dev = &g_nrf52_radioi8; + + /* Reset data */ + + memset(&g_nrf52_radioi8, 0, sizeof(struct nrf52_radioi8_dev_s)); + + /* Allow exclusive access to the privmac struct */ + + nxmutex_init(&dev->lock); + + /* Initialize lower-half radio */ + + dev->radio = nrf52_radioi8_radio_init(dev, board); + if (dev->radio == NULL) + { + wlerr("nrf52_radioi8_radio_init failed %d\n", -errno); + return NULL; + } + + DEBUGASSERT(dev->radio->ops->txstart); + DEBUGASSERT(dev->radio->ops->notify_noack); + DEBUGASSERT(dev->radio->ops->ccastart); + DEBUGASSERT(dev->radio->ops->rxenable); + DEBUGASSERT(dev->radio->ops->energydetect); + DEBUGASSERT(dev->radio->ops->setchannel); + DEBUGASSERT(dev->radio->ops->setcca); + DEBUGASSERT(dev->radio->ops->norm_setup); + DEBUGASSERT(dev->radio->ops->norm_trigger); +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + DEBUGASSERT(dev->radio->ops->beacon_setup); + DEBUGASSERT(dev->radio->ops->beacon_tx); +#endif + DEBUGASSERT(dev->radio->ops->reset); + DEBUGASSERT(dev->radio->ops->csma_poll); + DEBUGASSERT(dev->radio->ops->gts_poll); + + /* Initialize TIMER */ + + dev->tim = nrf52_radioi8_tim_init(dev); + if (dev->tim == NULL) + { + wlerr("nrf52_radioi8_tim_init failed %d\n", -errno); + return NULL; + } + + DEBUGASSERT(dev->tim->ops->setup); + DEBUGASSERT(dev->tim->ops->stop); + DEBUGASSERT(dev->tim->ops->reset); + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* Initialize RTC */ + + dev->rtc = nrf52_radioi8_rtc_init(dev); + if (dev->rtc == NULL) + { + wlerr("nrf52_radioi8_rtc_init failed %d\n", -errno); + return NULL; + } + + DEBUGASSERT(dev->rtc->ops->setup); + DEBUGASSERT(dev->rtc->ops->start); + DEBUGASSERT(dev->rtc->ops->stop); + DEBUGASSERT(dev->rtc->ops->reset); +#endif + + /* Connect MAC ops */ + + dev->macops.bind = nrf52_radioi8_bind; + dev->macops.reset = nrf52_radioi8_reset; + dev->macops.getattr = nrf52_radioi8_getattr; + dev->macops.setattr = nrf52_radioi8_setattr; + dev->macops.txnotify = nrf52_radioi8_txnotify; + dev->macops.txdelayed = nrf52_radioi8_txdelayed; + dev->macops.rxenable = nrf52_radioi8_rxenable; + dev->macops.energydetect = nrf52_radioi8_energydetect; + dev->macops.beaconstart = nrf52_radioi8_beaconstart; + dev->macops.beaconupdate = nrf52_radioi8_beaconupdate; + dev->macops.beaconstop = nrf52_radioi8_beaconstop; + dev->macops.sfupdate = nrf52_radioi8_sfupdate; + + return &dev->macops; +} diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.h b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.h new file mode 100644 index 0000000000000..339251d419a9a --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.h @@ -0,0 +1,145 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_H +#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "nrf52_ieee802154_radio.h" +#include "nrf52_ieee802154_rtc.h" +#include "nrf52_ieee802154_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GTS slots */ + +#ifndef CONFIG_NRF52_RADIO_IEEE802154_GTS_SLOTS +# define NRF52_GTS_SLOTS 0 +#else +# define NRF52_GTS_SLOTS CONFIG_NRF52_RADIO_IEEE802154_GTS_SLOTS +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* RX modes */ + +enum nrf52_ieee802154_rxmode_e +{ + NRF52_RXMODE_NORMAL, + NRF52_RXMODE_PROMISC, + NRF52_RXMODE_NOCRC +}; + +/* Device modes */ + +enum nrf52_ieee802154_devmode_e +{ + NRF52_DEVMODE_ENDPOINT, + NRF52_DEVMODE_COORD, + NRF52_DEVMODE_PANCOORD +}; + +/* IEEE 802.15.4 device state */ + +struct nrf52_radioi8_state_s +{ + /* MAC Attributes */ + + struct ieee802154_addr_s addr; /* Address */ + struct ieee802154_cca_s cca; /* Clear channel assessement method */ + + /* TX CSMA */ + + struct ieee802154_txdesc_s *txdelayed_desc; + struct ieee802154_txdesc_s *csma_desc; + + /* Radio state */ + + uint8_t chan; /* 11 to 26 for the 2.4 GHz band */ + uint8_t devmode; /* device mode: endpoint, coord, PAN coord */ + uint8_t rxmode; /* Reception mode: Normal, no CRC, promiscuous */ + + /* TX state */ + + bool txdelayed_busy; /* No CSMA transfer */ + bool reschedule_csma; /* Reschedule CSMA transfer */ + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* Superframe data */ + + struct ieee802154_superframespec_s sf; + + /* TX GTS */ + + struct ieee802154_txdesc_s *gts_desc[NRF52_GTS_SLOTS]; + bool gts_busy[NRF52_GTS_SLOTS]; +#endif +}; + +/* IEEE 802.15.4 radio device */ + +struct nrf52_radioi8_dev_s +{ + /* The public device instance - must be first */ + + struct ieee802154_radio_s macops; + + /* Registered callbacks */ + + struct ieee802154_radiocb_s *radiocb; + + /* Radio interface */ + + struct nrf52_radioi8_radio_s *radio; + + /* High resolution timer */ + + struct nrf52_radioi8_tim_s *tim; + + /* Low resolution, low power timer */ + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + struct nrf52_radioi8_rtc_s *rtc; +#endif + + /* Radio state */ + + struct nrf52_radioi8_state_s state; + + /* Exclusive access to this struct */ + + mutex_t lock; +}; + +#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_H */ diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.c b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.c new file mode 100644 index 0000000000000..8bad8162d1df1 --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.c @@ -0,0 +1,2115 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "nrf52_ieee802154_radio.h" +#include "nrf52_ieee802154_trace.h" + +#include "nrf52_ieee802154.h" + +#include "hardware/nrf52_utils.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Constant from NRF52 manual */ + +#define NRF52_ED_RSSISCALE (4) + +/* ED configuration: + * - IRQ on EDEND event (sampling of energy detection complete) + * - shortcut between READY and EDSTART + * - shortcut between EDEND and DISABLE + * + * Set in nrf52_radioi8_energydetect() reset in nrf52_radioi8_isr_radio(). + * + * EDSTART task set in nrf52_radioi8_energydetect(). + */ + +#define IEEE802154_ED_INT (RADIO_INT_EDEND) +#define IEEE802154_ED_SHORTS (RADIO_SHORTS_READY_EDSTART | \ + RADIO_SHORTS_EDEND_DISABLE) + +/* RX configuration: + * - IRQ on END event (packet recveived) + * - shortcut between RXREADY and START + * - shortcut between END and DISABLE + * + * Set in nrf52_radioi8_rxenable() reset in nrf52_radioi8_rxenable(). + * + * RXEN task set in nrf52_radioi8_rxenable() and + * nrf52_radioi8_isr_radio() after RX handled and no pending ACKTX. + */ + +#define IEEE802154_RX_INT (RADIO_INT_END) +#define IEEE802154_RX_SHORTS (RADIO_SHORTS_RXREADY_START | \ + RADIO_SHORTS_END_DISABLE) + +/* NOTE: for TX we trigger interrupts on PHYEND event, not END! */ + +/* TX CCA un-slotted configuration: + * - IRQ on PHYEND event + * - IRQ on CCABUSY event + * - shortcut between TXREADY and START + * - shortcut between PHYEND and DISABLE + * - shortcut between RXREADY and CCASTART + * - shortcut between CCAIDLE and STOP + * - shortcut between CCAIDLE and TXEN + * + * Set in nrf52_radioi8_radio_norm_setup() reset in + * nrf52_radioi8_isr_radio(). + * + * CCASTART task set in nrf52_radioi8_isr_tim() when CCA transfer. + */ + +#define IEEE802154_TXCCAUNSLT_INT (RADIO_INT_PHYEND | \ + RADIO_INT_CCABUSY) +#define IEEE802154_TXCCAUNSLT_SHORTS (RADIO_SHORTS_TXREADY_START | \ + RADIO_SHORTS_PHYEND_DISABLE | \ + RADIO_SHORTS_RXREADY_CCASTART | \ + RADIO_SHORTS_CCAIDLE_STOP | \ + RADIO_SHORTS_CCAIDLE_TXEN) + +/* TX CCA slotted configuration: + * - IRQ on PHYEND event + * - IRQ on CCABUSY event + * - IRQ on CCAIDLE event + * - shortcut between TXREADY and START + * - shortcut between PHYEND and DISABLE + * + * Set in nrf52_radioi8_radio_norm_setup() reset in + * nrf52_radioi8_isr_radio(). + * + * CCASTART task set in nrf52_radioi8_isr_tim() when CCA transfer. + */ + +#define IEEE802154_TXCCASLT_INT (RADIO_INT_PHYEND | \ + RADIO_INT_CCAIDLE | \ + RADIO_INT_CCABUSY) +#define IEEE802154_TXCCASLT_SHORTS (RADIO_SHORTS_TXREADY_START | \ + RADIO_SHORTS_PHYEND_DISABLE | \ + RADIO_SHORTS_RXREADY_CCASTART) + +/* TX no-CCA configuration: + * - IRQ on PHYEND event + * - shortcut between TXREADY and START + * - shortcut between PHYEND and DISABLE + * + * Set in nrf52_radioi8_radio_norm_setup() reset in + * nrf52_radioi8_isr_radio(). + * + * TXEN task set in nrf52_radioi8_radio_norm_trigger() when non-CCA + * transfer or in nrf52_radioi8_isr_tim() for TXDELAY. + */ + +#define IEEE802154_TX_INT (RADIO_INT_PHYEND) +#define IEEE802154_TX_SHORTS (RADIO_SHORTS_TXREADY_START | \ + RADIO_SHORTS_PHYEND_DISABLE) + +/* ACK configuration: + * - IRQ on PHYEND event + * - shortcut between PHYEND and DISABLE + * + * Set in nrf52_radioi8_ack_transmit reset in nrf52_radioi8_isr_radio(). + * + * TXEN task set in nrf52_radioi8_ack_transmit(). + * START task set in nrf52_radioi8_isr_tim(). + */ + +#define IEEE802154_ACKTX_INT (RADIO_INT_PHYEND) +#define IEEE802154_ACKTX_SHORTS (RADIO_SHORTS_PHYEND_DISABLE) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void nrf52_radioi8_rx_parse(struct nrf52_radioi8_dev_s *dev, + uint8_t *ftype, uint8_t *cmdtype); +static void nrf52_radioi8_ack_transmit(struct nrf52_radioi8_dev_s *dev); +static bool nrf52_radioi8_filter(struct nrf52_radioi8_dev_s *dev); +#if NRF52_GTS_SLOTS > 0 +static void nrf52_radioi8_gts_setup(struct nrf52_radioi8_dev_s *dev, + uint8_t fifo, struct iob_s *frame); +#endif + +/* Ops */ + +static void nrf52_radioi8_txstart(struct nrf52_radioi8_dev_s *dev); +static void nrf52_radioi8_ccastart(struct nrf52_radioi8_dev_s *dev); +static void nrf52_radioi8_notify_noack(struct nrf52_radioi8_dev_s *dev); +static int nrf52_radioi8_rxenable(struct nrf52_radioi8_dev_s *dev, + bool enable); +static int nrf52_radioi8_energydetect(struct nrf52_radioi8_dev_s *dev, + uint32_t nsymbols); +static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev, + uint8_t chan); +static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_cca_s *cca); +static void nrf52_radioi8_norm_setup_buf(struct nrf52_radioi8_dev_s *dev, + uint8_t *buf, bool csma); +static void nrf52_radioi8_norm_setup(struct nrf52_radioi8_dev_s *dev, + struct iob_s *frame, bool csma); +static void nrf52_radioi8_norm_trigger(struct nrf52_radioi8_dev_s *dev); +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME +static void nrf52_radioi8_beacon_setup(struct nrf52_radioi8_dev_s *dev, + uint8_t *data, uint8_t len); +static void nrf52_radioi8_beacon_tx(struct nrf52_radioi8_dev_s *dev); +#endif +static int nrf52_radioi8_reset(struct nrf52_radioi8_radio_s *dev); +static int nrf52_radioi8_csmapoll(struct nrf52_radioi8_dev_s *dev); +static int nrf52_radioi8_gtspoll(struct nrf52_radioi8_dev_s *dev); + +/* Interrupts logic */ + +static void nrf52_radioi8_work_noack(void *arg); +static void nrf52_radioi8_work_rx(void *arg); +static void nrf52_radioi8_work_tx(void *arg); +static void nrf52_radioi8_work_busy(void *arg); +static void nrf52_radioi8_work_ed(void *arg); +static void nrf52_radioi8_state_rx(struct nrf52_radioi8_dev_s *dev); +static void nrf52_radioi8_state_tx(struct nrf52_radioi8_dev_s *dev); +static void nrf52_radioi8_state_acktx(struct nrf52_radioi8_dev_s *dev); +static void nrf52_radioi8_state_ed(struct nrf52_radioi8_dev_s *dev); +static int nrf52_radioi8_isr_radio(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Packet buffers - must be byte aligned in RAM. + * + * NOTE: The first byte is PHR, the last byte is LQI. + */ + +static uint8_t aligned_data(8) + g_nrf52_radioi8_rxbuf[IEEE802154_MAX_PHY_PACKET_SIZE + 2]; + +static uint8_t aligned_data(8) + g_nrf52_radioi8_txbuf[IEEE802154_MAX_PHY_PACKET_SIZE + 2]; + +static uint8_t aligned_data(8) + g_nrf52_radioi8_ackbuf[IEEE802154_ACK_FRAME_SIZE + 1]; + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME +static uint8_t aligned_data(8) + g_nrf52_radioi8_beaconbuf[IEEE802154_MAX_PHY_PACKET_SIZE + 2]; +#endif + +/* Radio ops */ + +struct nrf52_radioi8_radio_ops_s g_radioi8_radio_ops = +{ + .txstart = nrf52_radioi8_txstart, + .ccastart = nrf52_radioi8_ccastart, + .notify_noack = nrf52_radioi8_notify_noack, + .rxenable = nrf52_radioi8_rxenable, + .energydetect = nrf52_radioi8_energydetect, + .setchannel = nrf52_radioi8_setchannel, + .setcca = nrf52_radioi8_setcca, + .norm_setup = nrf52_radioi8_norm_setup, + .norm_trigger = nrf52_radioi8_norm_trigger, +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + .beacon_setup = nrf52_radioi8_beacon_setup, + .beacon_tx = nrf52_radioi8_beacon_tx, +#endif + .reset = nrf52_radioi8_reset, + .csma_poll = nrf52_radioi8_csmapoll, + .gts_poll = nrf52_radioi8_gtspoll +}; + +/* Radio interface */ + +struct nrf52_radioi8_radio_s g_radioi8_radio; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_rx_parse + * + * Description: + * Get the RX frame type and command type if present. + * + ****************************************************************************/ + +static void nrf52_radioi8_rx_parse(struct nrf52_radioi8_dev_s *dev, + uint8_t *ftype, uint8_t *cmdtype) +{ + uint16_t *frame_ctrl = NULL; + uint8_t smode = 0; + uint8_t dmode = 0; + uint8_t panid_comp = 0; + int i = 0; + + /* Frame starts from offset 1 */ + + i = 1; + + /* Frame ctrl */ + + frame_ctrl = (uint16_t *)&dev->radio->rxbuf[i]; + i += sizeof(uint16_t); + + /* Frame seq */ + + i += 1; + + /* Return now if a given frame is not a command frame */ + + *ftype = ((*frame_ctrl & IEEE802154_FRAMECTRL_FTYPE) >> + IEEE802154_FRAMECTRL_SHIFT_FTYPE); + if (*ftype != IEEE802154_FRAME_COMMAND) + { + return; + } + + /* Now we have to find the offset for the frame command type */ + + smode = ((*frame_ctrl & IEEE802154_FRAMECTRL_SADDR) >> + IEEE802154_FRAMECTRL_SHIFT_SADDR); + + dmode = ((*frame_ctrl & IEEE802154_FRAMECTRL_DADDR) >> + IEEE802154_FRAMECTRL_SHIFT_DADDR); + + panid_comp = ((*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP) >> + IEEE802154_FRAMECTRL_SHIFT_PANIDCOMP); + + if (dmode != IEEE802154_ADDRMODE_NONE) + { + i += IEEE802154_PANIDSIZE; + + if (dmode == IEEE802154_ADDRMODE_SHORT) + { + i += IEEE802154_SADDRSIZE; + } + else if (dmode == IEEE802154_ADDRMODE_EXTENDED) + { + i += IEEE802154_EADDRSIZE; + } + } + + if (smode != IEEE802154_ADDRMODE_NONE) + { + if (!panid_comp) + { + i += IEEE802154_PANIDSIZE; + } + + if (smode == IEEE802154_ADDRMODE_SHORT) + { + i += IEEE802154_SADDRSIZE; + } + else if (smode == IEEE802154_ADDRMODE_EXTENDED) + { + i += IEEE802154_EADDRSIZE; + } + } + + *cmdtype = dev->radio->rxbuf[i]; +} + +/**************************************************************************** + * Name: nrf52_radioi8_ack_transmit + * + * Description: + * Transmit ACK. + * + ****************************************************************************/ + +static void nrf52_radioi8_ack_transmit(struct nrf52_radioi8_dev_s *dev) +{ + struct nrf52_radio_dev_s *lower = NULL; + uint8_t *ackbuf = dev->radio->ackbuf; + uint32_t regval = 0; + uint8_t ftype = 0; + uint8_t cmdtype = 0; + bool pending = false; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + /* Restore RX after ACK - we already are in DISABLE state so no need to + * disable RX + */ + + if (dev->radio->state.rxenabled) + { + dev->radio->state.rxrestore = true; + } + + /* Clear events */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_TXREADY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_RXREADY_OFFSET, 0); + + /* Fill ACK buffer */ + + ackbuf[0] = IEEE802154_ACK_FRAME_SIZE; + ackbuf[1] = 0x02; + ackbuf[2] = 0; + ackbuf[3] = dev->radio->rxbuf[3]; + + /* Get RX frame type */ + + nrf52_radioi8_rx_parse(dev, &ftype, &cmdtype); + + /* If this is ACK for Data Request command - set frame pending flag */ + + if (dev->state.devmode != NRF52_DEVMODE_ENDPOINT && + ftype == IEEE802154_FRAME_COMMAND && + cmdtype == IEEE802154_CMD_DATA_REQ) + { + pending = true; + } + + /* Set frame pedning flag for this ACK */ + + if (pending) + { + ackbuf[1] |= 0x10; + } + + /* Configure shorts and interrupts */ + + NRF52_RADIO_SHRTSET(lower, IEEE802154_ACKTX_SHORTS); + NRF52_RADIO_INTEN(lower, IEEE802154_ACKTX_INT); + + /* Set packet pointer - buffer must be aligned */ + + regval = (uint32_t)ackbuf; + DEBUGASSERT(nrf52_easydma_valid(regval)); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_PACKETPTR_OFFSET, regval); + + /* Set state to ACK */ + + dev->radio->state.state = NRF52_RADIO_STATE_ACKTX; + + /* Enable TX - start TX is called from timer interrupt */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_TXEN_OFFSET, 1); + + /* Run TIMER - TX is handled in timer isr */ + + nrf52_radioi8_trace_put(RADIO_TRACE_ACKTX, pending); + dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_ACK, IEEE802154_ACKIFS_SYMBOLS); +} + +/**************************************************************************** + * Name: nrf52_radioi8_filter + * + * Description: + * Filter received frames. + * + ****************************************************************************/ + +static bool nrf52_radioi8_filter(struct nrf52_radioi8_dev_s *dev) +{ + struct ieee802154_addr_s addr; + uint8_t *rx = &dev->radio->rxbuf[1]; + uint16_t *fc = (uint16_t *)&rx[0]; + + /* Promiscuous mode */ + + if (dev->state.rxmode == NRF52_RXMODE_PROMISC) + { + return true; + } + + /* Beacon frame */ + + if (((*fc & IEEE802154_FRAMECTRL_FTYPE) == IEEE802154_FRAME_BEACON) && + IEEE802154_PANIDCMP(IEEE802154_PANID_UNSPEC, &dev->state.addr.panid)) + { + return true; + } + + /* Get destination address */ + + IEEE802154_PANIDCOPY(addr.panid, &rx[3]); + addr.mode = ((*fc & IEEE802154_FRAMECTRL_DADDR) >> + IEEE802154_FRAMECTRL_SHIFT_DADDR); + if (addr.mode == IEEE802154_ADDRMODE_SHORT) + { + IEEE802154_SADDRCOPY(addr.saddr, &rx[5]); + } + else if (addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + IEEE802154_EADDRCOPY(addr.eaddr, &rx[5]); + } + + /* PAN ID match */ + + if (!IEEE802154_PANIDCMP(IEEE802154_PANID_UNSPEC, dev->state.addr.panid) && + !IEEE802154_PANIDCMP(addr.panid, &dev->state.addr.panid)) + { + return false; + } + + /* Destination address match */ + + if (addr.mode == IEEE802154_ADDRMODE_SHORT) + { + if (IEEE802154_SADDRCMP(addr.saddr, + &dev->state.addr.saddr)) + { + return true; + } + + else if (IEEE802154_SADDRCMP(addr.saddr, + IEEE802154_SADDR_UNSPEC)) + { + return true; + } + } + else if (addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + if (IEEE802154_EADDRCMP(addr.eaddr, + &dev->state.addr.eaddr)) + { + return true; + } + + else if (IEEE802154_EADDRCMP(addr.eaddr, + IEEE802154_EADDR_UNSPEC)) + { + return true; + } + } + + /* Otherwise drop this frame */ + + return false; +} + +#if NRF52_GTS_SLOTS > 0 +/**************************************************************************** + * Name: nrf52_radioi8_gts_setup + * + * Description: + * Setup a GTS transaction. + * + ****************************************************************************/ + +static void nrf52_radioi8_gts_setup(struct nrf52_radioi8_dev_s *dev, + uint8_t fifo, struct iob_s *frame) +{ + /* Missing logic */ + + ASSERT(0); +} + +/**************************************************************************** + * Name: nrf52_radioi8_dopoll_gts + * + * Description: + * This function is called in order to perform an out-of-sequence TX poll. + * + ****************************************************************************/ + +static void nrf52_radioi8_dopoll_gts(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + int gts = 0; + int len = 0; + + /* Get exclusive access to the driver */ + + while (nxmutex_lock(&dev->lock) < 0) + { + } + + for (gts = 0; gts < NRF52_GTS_SLOTS; gts++) + { + if (!dev->state.gts_busy[gts]) + { + len = dev->radiocb->poll(dev->radiocb, true, + &dev->state.gts_desc[gts]); + + if (len > 0) + { + /* Now the txdesc is in use */ + + dev->state.gts_busy[gts] = 1; + + /* Setup the GTS transaction */ + + nrf52_radioi8_gts_setup(dev, gts, + dev->state.gts_desc[gts]->frame); + } + } + } + + nxmutex_unlock(&dev->lock); +} +#endif /* NRF52_GTS_SLOTS > 0 */ + +/**************************************************************************** + * Name: nrf52_radioi8_txstart + * + * Description: + * Start transmition, TX must be armed (TXEN must be set). + * + ****************************************************************************/ + +static void nrf52_radioi8_txstart(struct nrf52_radioi8_dev_s *dev) +{ + struct nrf52_radio_dev_s *lower = NULL; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_START_OFFSET, 1); +} + +/**************************************************************************** + * Name: nrf52_radioi8_ccastart + * + * Description: + * Start CCA, RX must be armed (RXEN must be set). + * + ****************************************************************************/ + +static void nrf52_radioi8_ccastart(struct nrf52_radioi8_dev_s *dev) +{ + struct nrf52_radio_dev_s *lower = NULL; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_CCASTART_OFFSET, 1); +} + +/**************************************************************************** + * Name: nrf52_radioi8_notify_noack + * + * Description: + * Notify Radio layer about noack event. + * + ****************************************************************************/ + +static void nrf52_radioi8_notify_noack(struct nrf52_radioi8_dev_s *dev) +{ + /* If flag is set - no ACK was received */ + + if (dev->radio->state.waitack == true) + { + /* Notify MAC layer */ + + DEBUGASSERT(work_available(&dev->radio->noackwork)); + work_queue(HPWORK, &dev->radio->noackwork, nrf52_radioi8_work_noack, + (void *)dev, 0); + + /* Clear flag */ + + dev->radio->state.waitack = false; + } +} + +/**************************************************************************** + * Name: nrf52_radioi8_rxenable + * + * Description: + * Enable/Disable receiver. + * + ****************************************************************************/ + +static int nrf52_radioi8_rxenable(struct nrf52_radioi8_dev_s *dev, + bool enable) +{ + struct nrf52_radio_dev_s *lower = NULL; + uint32_t regval = 0; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + if (enable) + { + nrf52_radioi8_trace_put(RADIO_TRACE_RXENABLE, 0); + + /* Clear events */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_TXREADY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_RXREADY_OFFSET, 0); + + /* Configure shorts and interrupts */ + + NRF52_RADIO_SHRTSET(lower, IEEE802154_RX_SHORTS); + NRF52_RADIO_INTEN(lower, IEEE802154_RX_INT); + + /* Set packet pointer - buffer must be aligned */ + + regval = (uint32_t)dev->radio->rxbuf; + DEBUGASSERT(nrf52_easydma_valid(regval)); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_PACKETPTR_OFFSET, regval); + + /* Set state to RX */ + + dev->radio->state.state = NRF52_RADIO_STATE_RX; + + /* Start RX */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_RXEN_OFFSET, 1); + } + else + { + nrf52_radioi8_trace_put(RADIO_TRACE_RXDISABLE, 0); + + /* Disalbe interrups and shorts */ + + NRF52_RADIO_INTCLR(lower, IEEE802154_RX_INT); + NRF52_RADIO_SHRTSET(lower, 0); + + /* Stop RX */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_STOP_OFFSET, 1); + } + + /* Store state */ + + dev->radio->state.rxenabled = enable; + + /* Data returned by callback in ISR */ + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_energydetect + * + * Description: + * Start the energy detect measurement. + * + ****************************************************************************/ + +static int nrf52_radioi8_energydetect(struct nrf52_radioi8_dev_s *dev, + uint32_t nsymbols) +{ + struct nrf52_radio_dev_s *lower = NULL; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + /* Clear events */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_EDEND_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_RXREADY_OFFSET, 0); + + /* Configure shortucts and interrupts */ + + NRF52_RADIO_SHRTSET(lower, IEEE802154_ED_SHORTS); + NRF52_RADIO_INTEN(lower, IEEE802154_ED_INT); + + /* Configure ED symbols */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EDCNT_OFFSET, nsymbols); + + /* Set state to ENERGY_DETECT (ED) */ + + dev->radio->state.state = NRF52_RADIO_STATE_ED; + + /* Start RX */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_RXEN_OFFSET, 1); + + /* Data returned by callback in ISR */ + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_setchannel + * + * Description: + * Define the current radio channel the device is operating on. + * + ****************************************************************************/ + +static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev, + uint8_t chan) +{ + struct nrf52_radio_dev_s *lower = NULL; + uint32_t freq = 2405 + 5 * (chan - 11); + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + return NRF52_RADIO_FREQSET(lower, freq); +} + +/**************************************************************************** + * Name: nrf52_radioi8_setcca + * + * Description: + * Configure the Clear Channel Assessement. + * + ****************************************************************************/ + +static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_cca_s *cca) +{ + struct nrf52_radio_dev_s *lower = NULL; + struct nrf52_radio_cca_s c; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + /* Fill radio sturcture */ + + memset(&c, 0, sizeof(struct nrf52_radio_cca_s)); + + if (cca->use_ed && !cca->use_cs) + { + c.mode = NRF52_RADIO_CCA_ED; + } + else if (~cca->use_ed && cca->use_cs) + { + c.mode = NRF52_RADIO_CCA_CARRIER; + } + else if (cca->use_ed && cca->use_cs) + { + c.mode = NRF52_RADIO_CCA_CARRIER_AND_ED; + } + + c.edthres = cca->edth; + c.corrthres = cca->csth; + c.corrcnt = 5; + + /* Configure radio */ + + NRF52_RADIO_CCACFG(lower, &c); + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_norm_setup_buf + * + * Description: + * Setup a normal transaction (non GTS) from buffer. + * + ****************************************************************************/ + +static void nrf52_radioi8_norm_setup_buf(struct nrf52_radioi8_dev_s *dev, + uint8_t *buf, bool csma) +{ + struct nrf52_radio_dev_s *lower = NULL; + uint32_t regval = 0; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + nrf52_radioi8_trace_put(RADIO_TRACE_CSMASETUP, csma); + + /* If RX is enabled - we have to temporarly disable it */ + + if (dev->radio->state.rxenabled) + { + dev->macops.rxenable((struct ieee802154_radio_s *)dev, false); + + /* Restore RX after TX completed */ + + dev->radio->state.rxrestore = true; + } + + /* Set packet pointer - buffer must be aligned */ + + regval = (uint32_t)buf; + DEBUGASSERT(nrf52_easydma_valid(regval)); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_PACKETPTR_OFFSET, regval); + + if (csma) + { + /* Clear events */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_TXREADY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCABUSY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCAIDLE_OFFSET, 0); + + /* Configure shorts and interrupts */ + + if (dev->radio->state.slotted) + { +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + NRF52_RADIO_SHRTSET(lower, IEEE802154_TXCCASLT_SHORTS); + NRF52_RADIO_INTEN(lower, IEEE802154_TXCCASLT_INT); +#else + ASSERT(0); +#endif + } + else + { + NRF52_RADIO_SHRTSET(lower, IEEE802154_TXCCAUNSLT_SHORTS); + NRF52_RADIO_INTEN(lower, IEEE802154_TXCCAUNSLT_INT); + } + + dev->radio->state.state = NRF52_RADIO_STATE_TX_CSMA; + } + else + { + /* Clear events */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0); + + /* Configure shorts and interrupts */ + + NRF52_RADIO_SHRTSET(lower, IEEE802154_TX_SHORTS); + NRF52_RADIO_INTEN(lower, IEEE802154_TX_INT); + dev->radio->state.state = NRF52_RADIO_STATE_TX_NOCSMA; + } +} + +/**************************************************************************** + * Name: nrf52_radioi8_norm_setup + * + * Description: + * Setup a normal transaction (non GTS). + * + ****************************************************************************/ + +static void nrf52_radioi8_norm_setup(struct nrf52_radioi8_dev_s *dev, + struct iob_s *frame, bool csma) +{ + /* The first byte in TX buffer is PHR */ + + dev->radio->txbuf[0] = frame->io_len; + + /* Allocate space for CRC */ + + dev->radio->txbuf[0] += 2; + + /* Copy frame to RX buffer - we must send from aligned buffer */ + + memcpy(&dev->radio->txbuf[1], &frame->io_data[0], frame->io_len); + + /* Setup buffer */ + + nrf52_radioi8_norm_setup_buf(dev, dev->radio->txbuf, csma); +} + +/**************************************************************************** + * Name: nrf52_radioi8_trg_csma + * + * Description: + * Trigger transaction with CSMA-CA. + * + ****************************************************************************/ + +static void nrf52_radioi8_trg_csma(struct nrf52_radioi8_dev_s *dev) +{ + uint32_t delay = 0; + + /* Set state to TX */ + + dev->radio->state.state = NRF52_RADIO_STATE_TX; + + /* Need slotted CSMA-CA */ + + if (dev->radio->state.slotted) + { +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + if (!dev->radio->state.csma_busy) + { + /* Initial backoff state */ + + dev->radio->state.NB = 0; + dev->radio->state.CW = IEEE802154_CW0; + } + + /* Battery life extension */ + + if (dev->radio->state.ble) + { + dev->radio->state.BE = MIN(2, dev->radio->state.min_be); + } + else + { + dev->radio->state.BE = dev->radio->state.min_be; + } + + /* Get random unit backoff period delay */ + + delay = rand() % ((1 << dev->radio->state.BE) - 1); + + /* TODO: + * - locate backoff period boundary + * - perform CCA on backoff period boundary + */ + + ASSERT(0); +#else + ASSERT(0); +#endif + } + + /* Need un-slotted CSMA-CA */ + + else + { + if (!dev->radio->state.csma_busy) + { + /* Initial backoff state */ + + dev->radio->state.NB = 0; + dev->radio->state.BE = dev->radio->state.min_be; + } + + /* Get random unit backoff period delay */ + + delay = rand() % ((1 << dev->radio->state.BE) - 1); + } + + /* CSMA is in use */ + + dev->radio->state.csma_busy = true; + nrf52_radioi8_trace_put(RADIO_TRACE_CSMATRIGGER, delay); + + dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_CSMADELAY, + delay * IEEE802154_UNIT_BACKOFF_PERIOD); +} + +/**************************************************************************** + * Name: nrf52_radioi8_trg_nocsma + * + * Description: + * Trigger transaction without CSMA-CA; + * + ****************************************************************************/ + +static void nrf52_radioi8_trg_nocsma(struct nrf52_radioi8_dev_s *dev) +{ + struct nrf52_radio_dev_s *lower = NULL; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + /* Set state to TX */ + + dev->radio->state.state = NRF52_RADIO_STATE_TX; + + /* Start TX - we transmit immediately */ + + nrf52_radioi8_trace_put(RADIO_TRACE_NOCSMATRIGGER, + dev->radio->state.state); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_TXEN_OFFSET, 1); +} + +/**************************************************************************** + * Name: nrf52_radioi8_norm_trigger + * + * Description: + * Trigger normal transaction (non GTS). + * + ****************************************************************************/ + +static void nrf52_radioi8_norm_trigger(struct nrf52_radioi8_dev_s *dev) +{ + /* Wait for ACK */ + + if (dev->radio->txbuf[1] & IEEE802154_FRAMECTRL_ACKREQ) + { + dev->radio->state.waitack = true; + } + + /* CSMA transmition */ + + if (dev->radio->state.state == NRF52_RADIO_STATE_TX_CSMA) + { + nrf52_radioi8_trg_csma(dev); + } + + /* No-CSMA transmition */ + + else if (dev->radio->state.state == NRF52_RADIO_STATE_TX_NOCSMA) + { + nrf52_radioi8_trg_nocsma(dev); + } + + /* Invalid state */ + + else + { + /* We should not be there */ + + DEBUGASSERT(0); + } +} + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME +/**************************************************************************** + * Name: nrf52_radioi8_beacon_setup + * + * Description: + * Setup a beacon frame transfer + * + ****************************************************************************/ + +static void nrf52_radioi8_beacon_setup(struct nrf52_radioi8_dev_s *dev, + uint8_t *data, uint8_t len) +{ + /* Set beacon TX buffer */ + + memcpy(&dev->radio->beaconbuf[1], data, len); + + /* Length = Frame data + CRC */ + + dev->radio->beaconbuf[0] = len + 2; +} + +/**************************************************************************** + * Name: nrf52_radioi8_beacon_tx + * + * Description: + * Transmit a beacon frame (non CSMA-CA transfer). + * + ****************************************************************************/ + +static void nrf52_radioi8_beacon_tx(struct nrf52_radioi8_dev_s *dev) +{ + /* Beacon buffer is ready to send - transmit as non CSMA-CA */ + + nrf52_radioi8_norm_setup_buf(dev, dev->radio->beaconbuf, false); + + /* Send now */ + + nrf52_radioi8_norm_trigger(dev); +} +#endif + +/**************************************************************************** + * Name: nrf52_radioi8_reset + * + * Description: + * Reset radio state to work with IEEE 802.15.4. + * + ****************************************************************************/ + +static int nrf52_radioi8_reset(struct nrf52_radioi8_radio_s *dev) +{ + struct nrf52_radio_dev_s *radio = NULL; + struct nrf52_radio_crc_s crc; + struct nrf52_radio_pktcfg_s pcfg; + int ret = OK; + + DEBUGASSERT(dev); + radio = dev->lower; + + /* Reset radio state */ + + memset(&dev->state, 0, sizeof(struct nrf52_radioi8_radio_data_s)); + + /* Reset radio */ + + NRF52_RADIO_RESET(radio); + + /* MAC prameters */ + + dev->state.max_frame_waittime = IEEE802154_MAX_FRAME_WAITTIME; + dev->state.max_csma_backoffs = IEEE802154_MAX_CSMA_BACKOFFS; + dev->state.min_be = IEEE802154_MIN_BE; + dev->state.max_be = IEEE802154_MAX_BE; + + /* Set radio IEEE 802.15.4 mode */ + + ret = NRF52_RADIO_MODESET(radio, NRF52_RADIO_MODE_IEEE802154); + if (ret < 0) + { + goto errout; + } + + /* Configure CRC */ + + crc.len = 2; + crc.skip = NRF52_RADIO_CRC_SKIPADDR_IEEE802154; + crc.poly = 0x011021; + crc.init = 0; + + ret = NRF52_RADIO_CRCCFG(radio, &crc); + if (ret < 0) + { + goto errout; + } + + /* Configure packet for IEEE 802.15.4 mode */ + + pcfg.max_len = IEEE802154_MAX_PHY_PACKET_SIZE; + pcfg.stat_len = 0; + pcfg.bal_len = 0; + pcfg.lf_len = 8; + pcfg.s0_len = 0; + pcfg.s1_len = 0; + pcfg.ci_len = 0; + pcfg.pl_len = NRF52_RADIO_PREAMBLE_32BITZERO; + pcfg.term_len = 0; + pcfg.crcinc = true; + pcfg.endian = false; + pcfg.whiteen = false; + + ret = NRF52_RADIO_PKTCFG(radio, &pcfg); + if (ret < 0) + { + goto errout; + } + + /* Disable hardware TIFS */ + + NRF52_RADIO_PUTREG(radio, NRF52_RADIO_MODECNF0_OFFSET, + RADIO_MODECNF0_RU); + + /* Set TX power */ + + NRF52_RADIO_TXPWRSET(radio, 0); + + /* TODO: Configure LNA/PA */ + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf52_radioi8_dopoll_csma + * + * Description: + * Out-of-sequence TX poll. + * + ****************************************************************************/ + +void nrf52_radioi8_dopoll_csma(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + int len = 0; + + /* Get exclusive access to the driver */ + + while (nxmutex_lock(&dev->lock) < 0) + { + } + + /* If this a CSMA transaction and we have room in the CSMA */ + + if (!dev->radio->state.csma_busy) + { + wlinfo("Polling for frame\n"); + len = dev->radiocb->poll(dev->radiocb, false, &dev->state.csma_desc); + + if (len > 0) + { + wlinfo("Frame received. Frame length: %d\n", len); + + /* Setup the CSMA transaction */ + + dev->radio->ops->norm_setup(dev, dev->state.csma_desc->frame, + true); + dev->radio->ops->norm_trigger(dev); + } + } + + nxmutex_unlock(&dev->lock); +} + +/**************************************************************************** + * Name: nrf52_radioi8_csmapoll + * + * Description: + * Handle CSMA poll. + * + ****************************************************************************/ + +static int nrf52_radioi8_csmapoll(struct nrf52_radioi8_dev_s *dev) +{ + /* 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->radio->csma_pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->radio->csma_pollwork, + nrf52_radioi8_dopoll_csma, dev, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_gtspoll + * + * Description: + * Handle GTS poll. + * + ****************************************************************************/ + +static int nrf52_radioi8_gtspoll(struct nrf52_radioi8_dev_s *dev) +{ +#if NRF52_GTS_SLOTS > 0 + /* 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->radio->gts_pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->radio->gts_pollwork, + nrf52_radioi8_dopoll_gts, dev, 0); + } + + return OK; +#else + /* GTS not supported */ + + return -ENOTSUP; +#endif +} + +/**************************************************************************** + * Name: nrf52_radioi8_work_noack + * + * Description: + * Handle no ACK work. + * + ****************************************************************************/ + +static void nrf52_radioi8_work_noack(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + struct nrf52_radio_dev_s *lower = NULL; + struct ieee802154_txdesc_s *tx = NULL; + bool *busy = NULL; + bool csma = false; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + nrf52_radioi8_trace_put(RADIO_TRACE_WORK_NOACK, 0); + + /* Get exclusive access to the driver */ + + while (nxmutex_lock(&dev->lock) < 0) + { + } + + if (dev->state.txdelayed_busy) + { + tx = dev->state.txdelayed_desc; + busy = &dev->state.txdelayed_busy; + csma = false; + } + else + { + tx = dev->state.csma_desc; + busy = &dev->radio->state.csma_busy; + csma = true; + } + + if (tx->retrycount > 0) + { + /* Disable RX */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_DISABLE_OFFSET, 1); + + /* Try again */ + + tx->retrycount -= 1; + nrf52_radioi8_trace_put(RADIO_TRACE_TXRETRY, tx->retrycount); + nrf52_radioi8_norm_setup(dev, tx->frame, csma); + nrf52_radioi8_norm_trigger(dev); + } + else + { + nrf52_radioi8_trace_put(RADIO_TRACE_NOACK, 0); + + tx->conf->status = IEEE802154_STATUS_NO_ACK; + tx->framepending = false; + dev->radiocb->txdone(dev->radiocb, tx); + *busy = false; + } + + /* Unlock the radio device */ + + nxmutex_unlock(&dev->lock); +} + +/**************************************************************************** + * Name: nrf52_radioi8_work_irq + * + * Description: + * Handle RX work. + * + ****************************************************************************/ + +static void nrf52_radioi8_work_rx(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + struct nrf52_radio_dev_s *lower = NULL; + struct ieee802154_primitive_s *prim = NULL; + struct ieee802154_data_ind_s *ind = NULL; + uint8_t index = 0; + bool crcok = false; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + nrf52_radioi8_trace_put(RADIO_TRACE_WORK_RX, 0); + + /* Get exclusive access to the driver */ + + while (nxmutex_lock(&dev->lock) < 0) + { + } + + /* Check CRC */ + + crcok = NRF52_RADIO_GETREG(lower, NRF52_RADIO_CRCSTATUS_OFFSET); + if (dev->state.rxmode != NRF52_RXMODE_NOCRC && crcok == false) + { + goto out; + } + + /* Allocate a data_ind to put the frame in */ + + prim = ieee802154_primitive_allocate(); + ind = (struct ieee802154_data_ind_s *)prim; + if (ind == NULL) + { + wlerr("ERROR: Unable to allocate data_ind. Discarding frame\n"); + goto out; + } + + prim->type = IEEE802154_PRIMITIVE_IND_DATA; + + /* Allocate an IOB to put the frame into */ + + ind->frame = iob_alloc(false); + DEBUGASSERT(ind->frame != NULL); + + /* First byte is the PHR */ + + ind->frame->io_len = dev->radio->rxbuf[0]; + + /* Reduce len by 2, we only receive frames with correct crc, no check + * required. + */ + + ind->frame->io_len -= 2; + + for (index = 0; index < ind->frame->io_len; index++) + { + ind->frame->io_data[index] = dev->radio->rxbuf[index + 1]; + } + + /* Set CRC fields to 0 */ + + ind->frame->io_data[index + 1] = 0; + ind->frame->io_data[index + 2] = 0; + + /* LQI is the last byte in RAM */ + + ind->lqi = dev->radio->rxbuf[index + 1]; + + /* RSSI is non-standard field and is not supported here. + * TODO: get RSSI from LQI ? + */ + + ind->rssi = 0; + + /* Callback the receiver in the next highest layer */ + + dev->radiocb->rxframe(dev->radiocb, ind); + +out: + + /* Re-Enable RX if not handling ACK TX now */ + + if (dev->radio->state.state != NRF52_RADIO_STATE_ACKTX) + { + /* Enable packet reception */ + + dev->macops.rxenable((struct ieee802154_radio_s *)dev, true); + } + + /* Unlock the radio device */ + + nxmutex_unlock(&dev->lock); +} + +/**************************************************************************** + * Name: nrf52_radioi8_work_tx + * + * Description: + * Handle TX work. + * + ****************************************************************************/ + +static void nrf52_radioi8_work_tx(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + enum ieee802154_status_e status; + bool fpending = false; + + nrf52_radioi8_trace_put(RADIO_TRACE_WORK_TX, 0); + + /* Get exclusive access to the driver */ + + while (nxmutex_lock(&dev->lock) < 0) + { + } + + /* Get frame pending flag from the last TX ACK */ + + fpending = dev->radio->state.framepending; + dev->radio->state.framepending = false; + + status = IEEE802154_STATUS_SUCCESS; + + if (dev->state.txdelayed_busy) + { + /* Inform the next layer of the transmission success/failure */ + + dev->state.txdelayed_desc->conf->status = status; + dev->state.txdelayed_desc->framepending = fpending; + dev->radiocb->txdone(dev->radiocb, dev->state.txdelayed_desc); + dev->state.txdelayed_desc = NULL; + + dev->state.txdelayed_busy = false; + + if (dev->state.reschedule_csma) + { + nrf52_radioi8_norm_setup(dev, dev->state.csma_desc->frame, + true); + nrf52_radioi8_norm_trigger(dev); + dev->state.reschedule_csma = false; + } + } + else + { + /* Inform the next layer of the transmission success/failure */ + + dev->state.csma_desc->conf->status = status; + dev->state.csma_desc->framepending = fpending; + dev->radiocb->txdone(dev->radiocb, dev->state.csma_desc); + dev->state.csma_desc = NULL; + + /* We are now done with the transaction */ + + dev->radio->state.csma_busy = false; + + /* Must unlock the radio before calling poll */ + + nxmutex_unlock(&dev->lock); + nrf52_radioi8_dopoll_csma(dev); + while (nxmutex_lock(&dev->lock) < 0) + { + } + } + + /* Re-Enable RX if not handling ACK TX now */ + + if (dev->radio->state.state != NRF52_RADIO_STATE_ACKTX) + { + /* Enable packet reception */ + + dev->macops.rxenable((struct ieee802154_radio_s *)dev, true); + } + + /* Unlock the radio device */ + + nxmutex_unlock(&dev->lock); +} + +/**************************************************************************** + * Name: nrf52_radioi8_work_busy + * + * Description: + * Handle CCABUSY work. + * + ****************************************************************************/ + +static void nrf52_radioi8_work_busy(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + + nrf52_radioi8_trace_put(RADIO_TRACE_WORK_BUSY, 0); + + /* Get exclusive access to the driver */ + + while (nxmutex_lock(&dev->lock) < 0) + { + } + + dev->state.txdelayed_desc->conf->status = + IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE; + + dev->radiocb->txdone(dev->radiocb, dev->state.txdelayed_desc); + + /* Unlock the radio device */ + + nxmutex_unlock(&dev->lock); +} + +/**************************************************************************** + * Name: nrf52_radioi8_work_ed + * + * Description: + * Handle ED work. + * + ****************************************************************************/ + +static void nrf52_radioi8_work_ed(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + struct nrf52_radio_dev_s *lower = NULL; + int ed = 0; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + nrf52_radioi8_trace_put(RADIO_TRACE_WORK_ED, 0); + + /* Get result */ + + ed = NRF52_RADIO_GETREG(lower, NRF52_RADIO_EDSAMPLE_OFFSET); + + /* Convert to IEEE 802.15.4 scale */ + + ed = ((ed > 63) ? 255: (ed * NRF52_ED_RSSISCALE)); + + /* Callback the receiver in the next highest layer */ + + dev->radiocb->edresult(dev->radiocb, ed); +} + +/**************************************************************************** + * Name: nrf52_radioi8_state_rx + * + * Description: + * Handle radio interrupt for RX state. + * + ****************************************************************************/ + +static void nrf52_radioi8_state_rx(struct nrf52_radioi8_dev_s *dev) +{ + uint8_t *rxbuf = dev->radio->rxbuf; + + /* Frame filter */ + + if (dev->radio->state.waitack == false) + { + if (!nrf52_radioi8_filter(dev)) + { + nrf52_radioi8_trace_put(RADIO_TRACE_DROPFRAME, 0); + + /* Enable RX and ignore this frame */ + + dev->macops.rxenable((struct ieee802154_radio_s *)dev, + true); + return; + } + } + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* TODO: resync with beacon ? */ + + if (dev->radio->state.wait_for_beacon == true) + { + uint16_t *fc = (uint16_t *)&rxbuf[0]; + + /* TODO: NOT TESTES, should we check panid here ? */ + + if (((*fc & IEEE802154_FRAMECTRL_FTYPE) == IEEE802154_FRAME_BEACON) && + IEEE802154_PANIDCMP(IEEE802154_PANID_UNSPEC, + &dev->state.addr.panid)) + { + /* Start RTC */ + + dev->rtc->ops->start(dev); + + dev->radio->state.wait_for_beacon = false; + } + } +#endif + + /* Start ACK handling now - this must be done in isr */ + + if (dev->state.rxmode == NRF52_RXMODE_NORMAL && + rxbuf[1] & IEEE802154_FRAMECTRL_ACKREQ && + rxbuf[0] != IEEE802154_ACK_FRAME_SIZE) + { + nrf52_radioi8_ack_transmit(dev); + } + + /* Store RX frame long flag */ + + dev->radio->state.rxlong = rxbuf[0] > 18 ? true : false; + + /* We don't wait for TX ACK - forward this frame to MAC */ + + if (dev->radio->state.waitack == false) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RXDONE, 0); + + /* Receive DONE */ + + DEBUGASSERT(work_available(&dev->radio->irqwork)); + work_queue(HPWORK, &dev->radio->irqwork, nrf52_radioi8_work_rx, + (void *)dev, 0); + } + + /* We wait for TX ACK and this frame is ACK - confirm TX to MAC */ + + else if (rxbuf[0] == IEEE802154_ACK_FRAME_SIZE && + dev->radio->state.waitack == true) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RXACKDONE, 0); + + /* ACK frame received */ + + dev->radio->state.waitack = false; + + /* Get frame pedning flag */ + + dev->radio->state.framepending = rxbuf[1] & 0x10; + + /* Clear timer */ + + dev->tim->ops->stop(dev); + + /* This is ACK - notify MAC that TX complete */ + + DEBUGASSERT(work_available(&dev->radio->irqwork)); + work_queue(HPWORK, &dev->radio->irqwork, nrf52_radioi8_work_tx, + (void *)dev, 0); + } + + /* We wait for TX ACK and this is not ACK - notify TX failure */ + + else + { + /* Clear flag */ + + dev->radio->state.waitack = false; + + /* And notify MAC */ + + DEBUGASSERT(work_available(&dev->radio->noackwork)); + work_queue(HPWORK, &dev->radio->noackwork, nrf52_radioi8_work_noack, + (void *)dev, 0); + } +} + +/**************************************************************************** + * Name: nrf52_radioi8_state_tx + * + * Description: + * Handle radio interrupt for TX state. + * + ****************************************************************************/ + +static void nrf52_radioi8_state_tx(struct nrf52_radioi8_dev_s *dev) +{ + struct nrf52_radio_dev_s *lower = NULL; + + DEBUGASSERT(dev); + lower = dev->radio->lower; + + if (dev->radio->state.waitack == true) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_WAITACK, 0); + + /* Start timer and wait for ACK */ + + dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_WAITACK, + IEEE802154_ACK_WAIT); + } + else + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TXDONE, 0); + + /* Transmit DONE */ + + DEBUGASSERT(work_available(&dev->radio->irqwork)); + work_queue(HPWORK, &dev->radio->irqwork, nrf52_radioi8_work_tx, + (void *)dev, 0); + } + + /* CCABUSY event for TX */ + + if (NRF52_RADIO_GETREG(lower, NRF52_RADIO_EVENTS_CCABUSY_OFFSET)) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TXCCABUSY, 0); + + /* Clear event */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCABUSY_OFFSET, 0); + + /* Slotted CSMA-CA */ + + if (dev->radio->state.slotted == true) + { +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + dev->radio->state.NB += 1; + dev->radio->state.CW = IEEE802154_CW0; + dev->radio->state.BE = MIN(2, dev->radio->state.min_be); + + if (dev->radio->state.NB > dev->radio->state.max_csma_backoffs) + { + /* Return fauilure to MAC */ + + DEBUGASSERT(work_available(&dev->radio->irqwork)); + work_queue(HPWORK, &dev->radio->irqwork, + nrf52_radioi8_work_busy, (void *)dev, 0); + } + else + { + /* Try again */ + + dev->radio->state.state = NRF52_RADIO_STATE_TX_CSMA; + nrf52_radioi8_norm_trigger(dev); + + /* Do not restore RX */ + + return; + } +#else + ASSERT(0); +#endif + } + + /* Un-slotted CSMA-CA */ + + else + { + /* Update backoff */ + + dev->radio->state.NB -= 1; + dev->radio->state.BE = MIN(dev->radio->state.BE + 1, + dev->radio->state.max_be); + + if (dev->radio->state.NB > dev->radio->state.max_csma_backoffs) + { + /* Return fauilure to MAC */ + + DEBUGASSERT(work_available(&dev->radio->irqwork)); + work_queue(HPWORK, &dev->radio->irqwork, + nrf52_radioi8_work_busy, (void *)dev, 0); + } + else + { + /* Try again */ + + dev->radio->state.state = NRF52_RADIO_STATE_TX_CSMA; + nrf52_radioi8_norm_trigger(dev); + + /* Do not restore RX */ + + return; + } + } + } + + /* CCAIDLE event for TX */ + + if (NRF52_RADIO_GETREG(lower, NRF52_RADIO_EVENTS_CCAIDLE_OFFSET)) + { + /* Clear event */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCAIDLE_OFFSET, 0); + + /* Slotted CSMA-CA */ + + if (dev->radio->state.slotted == true) + { +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + dev->radio->state.CW -= 1; + + if (dev->radio->state.CW == 0) + { + /* Enable TX - short TXREADY-START is enabled */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_TXEN_OFFSET, 1); + } + else + { + /* Do not restore RX */ + + return; + } +#else + ASSERT(0); +#endif + } + + /* Un-slotted CSMA-CA */ + + else + { + /* Nothing here */ + } + } + + /* Restore RX */ + + if (dev->radio->state.rxrestore | dev->radio->state.waitack) + { + dev->macops.rxenable((struct ieee802154_radio_s *)dev, true); + dev->radio->state.rxrestore = false; + } +} + +/**************************************************************************** + * Name: nrf52_radioi8_state_acktx + * + * Description: + * Handle radio interrupt for ACKTX state. + * + ****************************************************************************/ + +static void nrf52_radioi8_state_acktx(struct nrf52_radioi8_dev_s *dev) +{ + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_ACKTX, 0); + + /* Handle pending TX */ + + if (dev->state.txdelayed_busy) + { + nrf52_radioi8_norm_setup(dev, + dev->state.txdelayed_desc->frame, + false); + + /* Send with timer to keep IFS */ + + if (dev->radio->state.rxlong) + { + dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_TXDELAY, + IEEE802154_LIFS_SYMBOLS); + } + else + { + dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_TXDELAY, + IEEE802154_SIFS_SYMBOLS); + } + } + + /* Restore RX */ + + else if (dev->radio->state.rxrestore) + { + dev->macops.rxenable((struct ieee802154_radio_s *)dev, true); + dev->radio->state.rxrestore = false; + } +} + +/**************************************************************************** + * Name: nrf52_radioi8_state_ed + * + * Description: + * Handle radio interrupt for ED state. + * + ****************************************************************************/ + +static void nrf52_radioi8_state_ed(struct nrf52_radioi8_dev_s *dev) +{ + /* Energy detect DONE */ + + DEBUGASSERT(work_available(&dev->radio->irqwork)); + work_queue(HPWORK, &dev->radio->irqwork, nrf52_radioi8_work_ed, + (void *)dev, 0); +} + +/**************************************************************************** + * Name: nrf52_radioi8_isr_radio + * + * Description: + * Radio IEEE 802.15.4 interrupt handler. + * + ****************************************************************************/ + +static int nrf52_radioi8_isr_radio(int irq, void *context, void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + struct nrf52_radio_dev_s *lower = NULL; + irqstate_t flags; + uint8_t state; + + DEBUGASSERT(dev != NULL); + lower = dev->radio->lower; + + flags = enter_critical_section(); + + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RADIO, 0); + + /* Get state */ + + state = dev->radio->state.state; + dev->radio->state.state = NRF52_RADIO_STATE_DISABLED; + + /* Always clear END and PHYEND events */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0); + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0); + + /* Clear interrupts and shorts */ + + NRF52_RADIO_INTCLR(lower, 0xffffffff); + NRF52_RADIO_SHRTSET(lower, 0); + + /* If by chance radio is not disabled - disable it now. This should be + * handled by SHORTS, but this not always work... + */ + + if (NRF52_RADIO_GETREG(lower, NRF52_RADIO_STATE_OFFSET) + != RADIO_STATE_DISABLED) + { + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_DISABLE_OFFSET, 1); + + /* Don't wait for the DISABLED event, hopefully the radio will be + * disabled by the time we use it again. Max delay is TX->DSIABLED + * and takes 21us. + */ + } + + /* Handle IRQ depending on the current state */ + + switch (state) + { + case NRF52_RADIO_STATE_RX: + { + nrf52_radioi8_state_rx(dev); + + break; + } + + case NRF52_RADIO_STATE_TX: + { + nrf52_radioi8_state_tx(dev); + + break; + } + + case NRF52_RADIO_STATE_ACKTX: + { + nrf52_radioi8_state_acktx(dev); + + break; + } + + case NRF52_RADIO_STATE_ED: + { + /* Clear event */ + + NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_EDEND_OFFSET, 0); + + nrf52_radioi8_state_ed(dev); + + break; + } + + default: + { + ASSERT(0); + break; + } + } + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_radio_init + * + * Description: + * Initialize RADIO for IEEE802154 operations. + * + ****************************************************************************/ + +struct nrf52_radioi8_radio_s * +nrf52_radioi8_radio_init(struct nrf52_radioi8_dev_s *dev, + struct nrf52_radio_board_s *board) +{ + struct nrf52_radio_dev_s *radio = NULL; + + /* Initialize lower-half radio */ + + radio = nrf52_radio_initialize(0, board); + if (radio == NULL) + { + wlerr("nrf52_radio_initialize failed %d\n", -errno); + return NULL; + } + + /* Attach custom RADIO interrupt */ + + irq_attach(radio->irq, nrf52_radioi8_isr_radio, dev); + up_enable_irq(radio->irq); + + /* Set interrupts priority */ + + up_prioritize_irq(radio->irq, 0); + + /* Connect radioer */ + + memset(&g_radioi8_radio, 0, sizeof(struct nrf52_radioi8_radio_s)); + g_radioi8_radio.ops = &g_radioi8_radio_ops; + g_radioi8_radio.lower = radio; + + /* Connect buffers */ + + g_radioi8_radio.rxbuf = g_nrf52_radioi8_rxbuf; + g_radioi8_radio.txbuf = g_nrf52_radioi8_txbuf; + g_radioi8_radio.ackbuf = g_nrf52_radioi8_ackbuf; +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + g_radioi8_radio.beaconbuf = g_nrf52_radioi8_beaconbuf; +#endif + + return &g_radioi8_radio; +} diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.h b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.h new file mode 100644 index 0000000000000..45c81061c439e --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.h @@ -0,0 +1,244 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_radio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_RADIO_H +#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_RADIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "hardware/nrf52_radio.h" + +#include "nrf52_radio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* IEEE 802.15.4 constants */ + +#define IEEE802154_MAX_FRAME_WAITTIME (16 + 32 + 4064) +#define IEEE802154_MAX_CSMA_BACKOFFS (1) +#define IEEE802154_MIN_BE (3) +#define IEEE802154_MAX_BE (5) +#define IEEE802154_CW0 (2) + +/* ACK_SYM + turnaround symbols + backoff */ + +#define IEEE802154_ACK_WAIT (12+ \ + IEEE802154_TURN_AROUND_TIME+ \ + IEEE802154_UNIT_BACKOFF_PERIOD) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Radio state */ + +enum nrf52_radioi8_state_e +{ + NRF52_RADIO_STATE_DISABLED = 0, /* Radio disabled */ + NRF52_RADIO_STATE_TX_CSMA, /* CSMA TX armed */ + NRF52_RADIO_STATE_TX_NOCSMA, /* Non CSMA TX armed */ + NRF52_RADIO_STATE_TX, /* TX on the air */ + NRF52_RADIO_STATE_RX, /* RX active */ + NRF52_RADIO_STATE_ACKTX, /* Transmiting ACK now */ + NRF52_RADIO_STATE_ED, /* Energy detection now */ +}; + +/* Radio data */ + +struct nrf52_radioi8_radio_data_s +{ + /* Radio state */ + + uint8_t state; + + /* CSMA-CA */ + + uint8_t NB; /* Number of required back offs */ + uint8_t CW; /* Contention window length */ + uint8_t BE; /* Backoff exponent */ + + /* RX state */ + + bool rxenabled; /* RX enabled now */ + bool rxrestore; /* RX needs to be restored */ + bool rxlong; /* Last RX frame was long */ + + /* TX state */ + + bool waitack; /* TX needs ACK */ + bool framepending; /* Frame pending from the last TX ACK */ + bool csma_busy; /* Un-slotted CSMA busy */ + bool slotted; /* Slotted CSMA-CA */ + + /* Radio configuration */ + + uint32_t max_frame_waittime; /* Max Frame wait time */ + uint8_t max_csma_backoffs; /* Max CSMA backoffs */ + uint8_t min_be; /* Min backoff exponent (BE) */ + uint8_t max_be; /* Max backoff exponent (BE) */ + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* Superframe data */ + + bool wait_for_beacon; /* Device wait for beacon */ + bool ble; /* Batter life extension */ +#endif +}; + +/* Forward reference */ + +struct nrf52_radioi8_radio_s; +struct ieee802154_radio_s; +struct nrf52_radioi8_dev_s; +struct ieee802154_cca_s; + +/* Radio ops */ + +struct nrf52_radioi8_radio_ops_s +{ + /* Start transmition - TX must be armed (TXEN set) */ + + void (*txstart)(struct nrf52_radioi8_dev_s *dev); + + /* Start CCA - RX must be armed (RXEN set) */ + + void (*ccastart)(struct nrf52_radioi8_dev_s *dev); + + /* Notify MAC about no ACK */ + + void (*notify_noack)(struct nrf52_radioi8_dev_s *dev); + + /* Enable/Disable receiver */ + + int (*rxenable)(struct nrf52_radioi8_dev_s *dev, bool enable); + + /* Start the energy detect measurement */ + + int (*energydetect)(struct nrf52_radioi8_dev_s *dev, uint32_t nsymbols); + + /* Define the current radio channel the device is operating on */ + + int (*setchannel)(struct nrf52_radioi8_dev_s *dev, uint8_t chan); + + /* Configure the Clear Channel Assessement */ + + int (*setcca)(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_cca_s *cca); + + /* Setup a normal transaction (non GTS) */ + + void (*norm_setup)(struct nrf52_radioi8_dev_s *dev, + struct iob_s *frame, bool csma); + + /* Trigger normal transaction (non GTS) */ + + void (*norm_trigger)(struct nrf52_radioi8_dev_s *dev); + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* Setup a beacon frame transfe */ + + void (*beacon_setup)(struct nrf52_radioi8_dev_s *dev, + uint8_t *data, uint8_t len); + + /* Transmit a beacon frame (non CSMA-CA transfer) */ + + void (*beacon_tx)(struct nrf52_radioi8_dev_s *dev); +#endif + + /* Reset radio state to work with IEEE 802.15.4 */ + + int (*reset)(struct nrf52_radioi8_radio_s *dev); + + /* Handle TX poll (no GTS) */ + + int (*csma_poll)(struct nrf52_radioi8_dev_s *dev); + + /* Handle GTS poll */ + + int (*gts_poll)(struct nrf52_radioi8_dev_s *dev); +}; + +/* Radio interface */ + +struct nrf52_radioi8_radio_s +{ + /* Radio lower-half */ + + struct nrf52_radio_dev_s *lower; + + /* IEEE 802.15.4 radio operations */ + + struct nrf52_radioi8_radio_ops_s *ops; + + /* Packet buffers */ + + uint8_t *rxbuf; + uint8_t *txbuf; + uint8_t *ackbuf; +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + uint8_t *beaconbuf; +#endif + + /* For deferring interrupts work */ + + struct work_s irqwork; + + /* For deferring no ACK work */ + + struct work_s noackwork; + + /* For deferring poll work to the work queue */ + + struct work_s csma_pollwork; + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* For deferring poll work to the work queue */ + + struct work_s gts_pollwork; +#endif + + /* Radio data */ + + struct nrf52_radioi8_radio_data_s state; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_radio_init + * + * Description: + * Initialize RADIO for IEEE802154 operations. + * + ****************************************************************************/ + +struct nrf52_radioi8_radio_s * +nrf52_radioi8_radio_init(struct nrf52_radioi8_dev_s *dev, + struct nrf52_radio_board_s *board); + +#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_RADIO_H */ diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.c b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.c new file mode 100644 index 0000000000000..a339d7e80ce0e --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.c @@ -0,0 +1,392 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include + +#include "nrf52_ieee802154_rtc.h" +#include "nrf52_ieee802154_trace.h" + +#include "nrf52_ieee802154.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME +# warning Beacon and superframe support work in progress +#endif + +#ifndef CONFIG_NRF52_RTC0 +# error CONFIG_NRF52_RTC0 is needed to handle radio timings +#endif + +/* RTC instance - 0 */ + +#define NRF52_IEEE802154_RTC0 (0) + +/* RTC prescaler set to 0, freq = 32.768kHz, resolution = 30.517 us */ + +#define NRF52_RTC_PRESCALER (0) +#define NRF52_RTC_FREQUENCY (32768) + +#define NRF52_RTC_RESOLUTION_NS (30517) + +/* 31 * 30.517us = 946.027us */ + +#define NRF52_RTC_TIMESLOT_CC (31) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* RTC ops */ + +static int nrf52_radioi8_rtc(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_superframespec_s *sfspec); +static int nrf52_radioi8_rtc_start(struct nrf52_radioi8_dev_s *dev); +static int nrf52_radioi8_rtc_stop(struct nrf52_radioi8_dev_s *dev); +static void nrf52_radioi8_rtc_reset(struct nrf52_radioi8_dev_s *dev); + +/* Interrupts logic */ + +static void nrf52_radioi8_work_inactive(void *arg); +static int nrf52_radioi8_isr_rtc(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* RTC ops */ + +static struct nrf52_radioi8_rtc_ops_s g_radioi8_rtc_ops = +{ + .setup = nrf52_radioi8_rtc, + .start = nrf52_radioi8_rtc_start, + .stop = nrf52_radioi8_rtc_stop, + .reset = nrf52_radioi8_rtc_reset +}; + +/* RTC instance */ + +static struct nrf52_radioi8_rtc_s g_radioi8_rtc; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_rtc + * + * Description: + * Configure RTC events according to superframe spec. + * + ****************************************************************************/ + +static int nrf52_radioi8_rtc(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_superframespec_s *sfspec) +{ + uint32_t bi = 0; + uint32_t sd = 0; + uint32_t cap = 0; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Stop RTC and clear the counter */ + + NRF52_RTC_STOP(dev->rtc->rtc); + NRF52_RTC_CLEAR(dev->rtc->rtc); + + /* Initialize BI counter */ + + bi = ((IEEE802154_BASE_SUPERFRAME_DURATION * + (2 << sfspec->beaconorder) * + IEEE802154_SYMBOL_US * 1000) / + NRF52_RTC_RESOLUTION_NS); + NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_BI, bi); + + /* Initialize SD counter */ + + sd = ((IEEE802154_BASE_SUPERFRAME_DURATION * + (2 << sfspec->sforder) * + IEEE802154_SYMBOL_US * 1000) / + NRF52_RTC_RESOLUTION_NS); + NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_SD, sd); + + /* Initialize CAP counter */ + + cap = ((sfspec->final_capslot * + IEEE802154_TIMESLOT_US * 1000) / + NRF52_RTC_RESOLUTION_NS); + NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_CAP, cap); + + /* Initialize timeslot counter */ + + dev->rtc->rtc_timeslot = NRF52_RTC_TIMESLOT_CC; + NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_TIMESLOT, dev->rtc->rtc_timeslot); + + /* Configure interupts */ + + NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_BI); + NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_SD); + NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_CAP); + NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_TIMESLOT); + + /* Configure events */ + + NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_BI); + NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_SD); + NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_CAP); + NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_TIMESLOT); + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_rtc_start + * + * Description: + * Start RTC. + * + ****************************************************************************/ + +static int nrf52_radioi8_rtc_start(struct nrf52_radioi8_dev_s *dev) +{ + NRF52_RTC_START(dev->rtc->rtc); + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_rtc_stop + * + * Description: + * Stop RTC. + * + ****************************************************************************/ + +static int nrf52_radioi8_rtc_stop(struct nrf52_radioi8_dev_s *dev) +{ + NRF52_RTC_STOP(dev->rtc->rtc); + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_rtc_reset + * + * Description: + * Reset RTC. + * + ****************************************************************************/ + +static void nrf52_radioi8_rtc_reset(struct nrf52_radioi8_dev_s *dev) +{ + /* Configure RTC - freq = 32.768 kHz */ + + NRF52_RTC_STOP(dev->rtc->rtc); + NRF52_RTC_SETPRE(dev->rtc->rtc, NRF52_RTC_PRESCALER); + + /* Reset data */ + + dev->rtc->rtc_timeslot = 0; +} + +/**************************************************************************** + * Name: nrf52_radioi8_work_inactive + * + * Description: + * Work when we enter inactive state. + * + ****************************************************************************/ + +static void nrf52_radioi8_work_inactive(void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + enum ieee802154_sfevent_e sfevent; + + /* Notify MAC */ + + sfevent = IEEE802154_SFEVENT_ENDOFACTIVE; + dev->radiocb->sfevent(dev->radiocb, sfevent); +} + +/**************************************************************************** + * Name: nrf52_radioi8_isr_rtc + * + * Description: + * Helper RTC0 interrupt handler. + * + ****************************************************************************/ + +static int nrf52_radioi8_isr_rtc(int irq, void *context, void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + struct nrf52_radioi8_rtc_s *rtc = NULL; + irqstate_t flags; + + DEBUGASSERT(dev != NULL); + rtc = dev->rtc; + + flags = enter_critical_section(); + + /* End of CAP */ + + if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_CAP)) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCCAP, 0); + + /* TODO */ + + /* Clear event */ + + NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_CAP); + } + + /* End of active portion */ + + else if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_SD)) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCSD, 0); + + /* Schedule work */ + + DEBUGASSERT(work_available(&dev->rtc->inactive_work)); + work_queue(HPWORK, &dev->rtc->inactive_work, + nrf52_radioi8_work_inactive, dev, 0); + + /* Reset timeslot */ + + rtc->rtc_timeslot = NRF52_RTC_TIMESLOT_CC; + + /* Clear event */ + + NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_SD); + } + + /* Beacon interval */ + + else if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_BI)) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCBI, 0); + + /* Transmit beacon if we are not endpoint */ + + if (dev->state.devmode != NRF52_DEVMODE_ENDPOINT) + { + /* Transmit data from beaconbuf */ + + dev->radio->ops->beacon_tx(dev); + } + + /* Clear event */ + + NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_BI); + + /* Next cycle */ + + NRF52_RTC_TRGOVRFLW(rtc->rtc); + + /* TODO: resync with beacon ? */ + } + + /* Timeslot in active portion */ + + if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_TIMESLOT)) + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCTIMESLOT, 0); + + /* TODO: how to sync transmition with timeslot ? + * do we need count every timeslot here ? + * or wait for the timeslot we are interested in ? + * or just use txdelay ? + */ + + /* Update timeslot */ + + rtc->rtc_timeslot += NRF52_RTC_TIMESLOT_CC; + NRF52_RTC_SETCC(rtc->rtc, NRF52_RTC_TIMESLOT, rtc->rtc_timeslot); + + /* Clear event */ + + NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_TIMESLOT); + } + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_rtc_init + * + * Description: + * Initialize low resoluton, low power timer for IEEE802154 operations. + * Used to handle superframe timings. + * + ****************************************************************************/ + +struct nrf52_radioi8_rtc_s * +nrf52_radioi8_rtc_init(struct nrf52_radioi8_dev_s *dev) +{ + struct nrf52_rtc_dev_s *rtc = NULL; + + /* Reserve RTC0 */ + + rtc = nrf52_rtc_init(NRF52_IEEE802154_RTC0); + if (rtc == NULL) + { + wlerr("nrf52_rtc_init(0) failed %d\n", -errno); + return NULL; + } + + /* Atach RTC interrupt */ + + NRF52_RTC_SETISR(rtc, nrf52_radioi8_isr_rtc, dev); + + /* Set interrupts priority */ + + up_prioritize_irq(NRF52_IRQ_RTC0, 0); + + /* Connect RTC */ + + memset(&g_radioi8_rtc, 0, sizeof(struct nrf52_radioi8_rtc_s)); + g_radioi8_rtc.ops = &g_radioi8_rtc_ops; + g_radioi8_rtc.rtc = rtc; + + return &g_radioi8_rtc; +} diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.h b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.h new file mode 100644 index 0000000000000..24f1ac976f097 --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_rtc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_RTC_H +#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "nrf52_rtc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* RTC events */ + +enum nrf52_ieee802154_rtc_e +{ + NRF52_RTC_BI = 0, /* Beacon Interval interval (BI) */ + NRF52_RTC_TIMESLOT = 1, /* Time slot */ + NRF52_RTC_CAP = 2, /* Contention Access Period (CAP) */ + NRF52_RTC_SD = 3 /* Super Frame Duration (SD) */ +}; + +/* Forward reference */ + +struct nrf52_radioi8_rtc_s; +struct nrf52_radioi8_dev_s; + +/* RTC ops */ + +struct nrf52_radioi8_rtc_ops_s +{ + /* Configure RTC events according to superframe spec */ + + int (*setup)(struct nrf52_radioi8_dev_s *dev, + struct ieee802154_superframespec_s *sfspec); + + /* Start RTC */ + + int (*start)(struct nrf52_radioi8_dev_s *dev); + + /* Stop RTC */ + + int (*stop)(struct nrf52_radioi8_dev_s *dev); + + /* Reset RTC */ + + void (*reset)(struct nrf52_radioi8_dev_s *dev); +}; + +/* RTC interface */ + +struct nrf52_radioi8_rtc_s +{ + /* RTC lower-half */ + + struct nrf52_rtc_dev_s *rtc; + + /* IEEE 802.15.4 RTC operations */ + + struct nrf52_radioi8_rtc_ops_s *ops; + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME + /* For deferring inactive state work to the work queue */ + + struct work_s inactive_work; + + /* RTC state */ + + uint32_t rtc_timeslot; +#endif +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_rtc_init + * + * Description: + * Initialize low resoluton, low power timer for IEEE802154 operations. + * Used to handle superframe timings. + * + ****************************************************************************/ + +struct nrf52_radioi8_rtc_s * +nrf52_radioi8_rtc_init(struct nrf52_radioi8_dev_s *dev); + +#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_RTC_H */ diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.c b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.c new file mode 100644 index 0000000000000..b310a28f7a870 --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.c @@ -0,0 +1,347 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "nrf52_ieee802154_tim.h" +#include "nrf52_ieee802154_trace.h" + +#include "nrf52_ieee802154.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_NRF52_TIMER0 +# error CONFIG_NRF52_TIMER0 is needed to handle radio timings +#endif + +/* Timer instance - 0 */ + +#define NRF52_IEEE802154_TIMER0 (0) + +/* Timer period set to 16us (symbol duration) */ + +#define NRF52_TIMER_FREQUENCY (1000000 / 16) + +/* 16MHz / (2 ** 8) = 62500 */ + +#define NRF52_TIMER_PRESCALER (8) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* RTC ops */ + +static int nrf52_radioi8_tim(struct nrf52_radioi8_dev_s *dev, uint8_t chan, + uint32_t val); +static void nrf52_radioi8_tim_stop(struct nrf52_radioi8_dev_s *dev); +static void nrf52_radioi8_tim_reset(struct nrf52_radioi8_dev_s *dev); + +/* Interrupts logic */ + +static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Timer ops */ + +static struct nrf52_radioi8_tim_ops_s g_radioi8_tim_ops = +{ + .setup = nrf52_radioi8_tim, + .stop = nrf52_radioi8_tim_stop, + .reset = nrf52_radioi8_tim_reset +}; + +/* Timer instance */ + +static struct nrf52_radioi8_tim_s g_radioi8_tim; + +/**************************************************************************** + * Private Function + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_tim + * + * Description: + * Configure TIMER event. + * + ****************************************************************************/ + +static int nrf52_radioi8_tim(struct nrf52_radioi8_dev_s *dev, uint8_t chan, + uint32_t val) +{ + struct nrf52_radioi8_tim_s *tim = NULL; + irqstate_t flags; + + DEBUGASSERT(dev != NULL); + tim = dev->tim; + + flags = enter_critical_section(); + + if (tim->tim_pending == true) + { + wlerr("TIMER busy! drop %" PRId8 " %" PRId32 " request\n", chan, val); + ASSERT(0); + return -EBUSY; + } + + /* Stop timer and clear the counter */ + + NRF52_TIM_STOP(tim->tim); + NRF52_TIM_CLEAR(tim->tim); + + /* Clear the previous event */ + + NRF52_TIM_ACKINT(tim->tim, chan); + + /* Set compare register */ + + NRF52_TIM_SETCC(tim->tim, chan, val); + + /* Configure interupt */ + + NRF52_TIM_ENABLEINT(tim->tim, chan); + + /* Set TIMER pending flag and used channel */ + + tim->tim_pending = true; + tim->tim_now = chan; + + /* Start timer */ + + nrf52_radioi8_trace_put(RADIO_TRACE_TIMSTART, chan); + + if (val > 0) + { + NRF52_TIM_START(tim->tim); + } + else + { + /* Call handler now */ + + nrf52_radioi8_isr_tim(0, NULL, dev); + } + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: nrf52_radioi8_tim_stop + * + * Description: + * Stop timer. + * + ****************************************************************************/ + +static void nrf52_radioi8_tim_stop(struct nrf52_radioi8_dev_s *dev) +{ + NRF52_TIM_STOP(dev->tim->tim); + NRF52_TIM_DISABLEINT(dev->tim->tim, dev->tim->tim_now); + + /* Reset state */ + + dev->tim->tim_pending = false; + dev->tim->tim_now = -1; +} + +/**************************************************************************** + * Name: nrf52_radioi8_tim_reset + * + * Description: + * Reset TIMER. + * + ****************************************************************************/ + +static void nrf52_radioi8_tim_reset(struct nrf52_radioi8_dev_s *dev) +{ + /* Configure TIMER - freq = 62500 */ + + NRF52_TIM_STOP(dev->tim->tim); + NRF52_TIM_CONFIGURE(dev->tim->tim, NRF52_TIM_MODE_TIMER, + NRF52_TIM_WIDTH_32B); + NRF52_TIM_SETPRE(dev->tim->tim, NRF52_TIMER_PRESCALER); + + /* Reset state */ + + dev->tim->tim_pending = false; + dev->tim->tim_now = -1; +} + +/**************************************************************************** + * Name: nrf52_radioi8_isr_tim + * + * Description: + * Helper tim interrupt handler. + * + ****************************************************************************/ + +static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg) +{ + struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg; + struct nrf52_radioi8_tim_s *tim = NULL; + irqstate_t flags; + + DEBUGASSERT(dev != NULL); + tim = dev->tim; + + flags = enter_critical_section(); + + switch (tim->tim_now) + { + /* RX ACK handler */ + + case NRF52_TIMER_CHAN_ACK: + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMACKTX, 0); + + /* Start TX */ + + dev->radio->ops->txstart(dev); + + break; + } + + /* Delayed TX handler */ + + case NRF52_TIMER_CHAN_TXDELAY: + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMTXDELAY, 0); + + /* Trigger TX */ + + dev->radio->ops->norm_trigger(dev); + + break; + } + + /* ACK wait handler */ + + case NRF52_TIMER_CHAN_WAITACK: + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMWAITACK, 0); + + /* Notify radio layer */ + + dev->radio->ops->notify_noack(dev); + + break; + } + + case NRF52_TIMER_CHAN_CSMADELAY: + { + nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMCSMADELAY, 0); + + /* Start CCA - we transmit immediately after the CCA procedure ends + * (CCAIDLE_TXEN short), or CCABUSY interrupt happen. + */ + + dev->radio->ops->ccastart(dev); + + break; + } + + default: + { + ASSERT(0); + break; + } + } + + /* Stop timer */ + + NRF52_TIM_STOP(tim->tim); + + /* Disable and clear interrupts */ + + NRF52_TIM_DISABLEINT(tim->tim, tim->tim_now); + NRF52_TIM_ACKINT(tim->tim, tim->tim_now); + + /* Clear TIMER pending flag and used channel */ + + tim->tim_pending = false; + tim->tim_now = -1; + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_tim_init + * + * Description: + * Initialize high resoluton timer for IEEE802154 operations. + * Used to handle short radio timeouts like ACK, IFS or delayed + * transmitions. + * + ****************************************************************************/ + +struct nrf52_radioi8_tim_s * +nrf52_radioi8_tim_init(struct nrf52_radioi8_dev_s *dev) +{ + struct nrf52_tim_dev_s *tim = NULL; + + /* Reserve TIMER0 */ + + tim = nrf52_tim_init(NRF52_IEEE802154_TIMER0); + if (tim == NULL) + { + wlerr("nrf52_tim_init(0) failed %d\n", -errno); + return NULL; + } + + /* Atach TIMER interrupt */ + + NRF52_TIM_SETISR(tim, nrf52_radioi8_isr_tim, dev); + + /* Set interrupts priority */ + + up_prioritize_irq(NRF52_IRQ_TIMER0, 0); + + /* Connect timer */ + + memset(&g_radioi8_tim, 0, sizeof(struct nrf52_radioi8_tim_s)); + g_radioi8_tim.ops = &g_radioi8_tim_ops; + g_radioi8_tim.tim = tim; + + return &g_radioi8_tim; +} diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.h b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.h new file mode 100644 index 0000000000000..dc689b0712036 --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_tim.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_TIM_H +#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "nrf52_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum nrf52_ieee802154_timer_e +{ + NRF52_TIMER_CHAN_ACK = 0, /* Handle ACK time */ + NRF52_TIMER_CHAN_TXDELAY = 1, /* Handle TX delay */ + NRF52_TIMER_CHAN_WAITACK = 2, /* Handle ACK wait */ + NRF52_TIMER_CHAN_CSMADELAY = 3, /* Handle CSMA wait */ +}; + +/* Forward reference */ + +struct nrf52_radioi8_tim_s; +struct nrf52_radioi8_dev_s; + +/* Timer ops */ + +struct nrf52_radioi8_tim_ops_s +{ + /* Configure TIMER event */ + + int (*setup)(struct nrf52_radioi8_dev_s *dev, uint8_t chan, uint32_t val); + + /* Stop timer */ + + void (*stop)(struct nrf52_radioi8_dev_s *dev); + + /* Reset timer */ + + void (*reset)(struct nrf52_radioi8_dev_s *dev); +}; + +/* Timer interface */ + +struct nrf52_radioi8_tim_s +{ + /* Timer lower-half */ + + struct nrf52_tim_dev_s *tim; + + /* IEEE 802.15.4 timer operations */ + + struct nrf52_radioi8_tim_ops_s *ops; + + /* Timer state */ + + int8_t tim_now; + bool tim_pending; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_tim_init + * + * Description: + * Initialize high resoluton timer for IEEE802154 operations. + * Used to handle short radio timeouts like ACK, IFS or delayed + * transmitions. + * + ****************************************************************************/ + +struct nrf52_radioi8_tim_s * +nrf52_radioi8_tim_init(struct nrf52_radioi8_dev_s *dev); + +#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_TIM_H */ diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.c b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.c new file mode 100644 index 0000000000000..b9e46873674cc --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "nrf52_ieee802154_trace.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This must match enum radio_trace_type_e */ + +const static char *g_radio_trace_str[] = +{ + "RADIO IRQ", + "RADIO IRQ: RX DONE", + "RADIO IRQ: TX DONE", + "RADIO IRQ: ACK TX", + "RADIO IRQ: WAIT ACK", + "RADIO IRQ: RX ACK DONE", + "RADIO IRQ: TX CCA BUSY", + + "TIM IRQ: TIM ACK TX", + "TIM IRQ; TIM TX DELAY", + "TIM IRQ: TIM WAIT ACK", + "TIM IRQ: TIM CSMA DELAY", + "RTC IRQ: RTC SD", + "RTC IRQ: RTC CAP", + "RTC IRQ: RTC TIMESLOT", + "RTC IRQ: RTC BI", + + "WORK: RX", + "WORK: TX", + "WORK: BUSY", + "WORK: ED", + "WORK: NO ACK", + + "ACKTX", + "TIMSTART", + "RXENABLE", + "RXDISABLE", + "CSMASETUP", + "CSMATRIGGER", + "NOCSMATRIGGER", + "NOACK", + "DROPFRAME", + "TXTRYAGAIN", +}; + +/* Trace data */ + +volatile static size_t g_radio_trace_cntr = 0; +volatile static struct radio_trace_s +g_radio_trace[CONFIG_NRF52_RADIO_IEEE802154_TRACE_BUFSIZE]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_trace_init + * + * Description: + * Initialize trace interface. + * + ****************************************************************************/ + +void nrf52_radioi8_trace_init(void) +{ + g_radio_trace_cntr = 0; + memset((void *)g_radio_trace, 0, sizeof(g_radio_trace)); +} + +/**************************************************************************** + * Name: nrf52_radioi8_trace_put + * + * Description: + * Put trace event. + * + ****************************************************************************/ + +void nrf52_radioi8_trace_put(uint8_t type, uint32_t arg) +{ + if (g_radio_trace_cntr >= CONFIG_NRF52_RADIO_IEEE802154_TRACE_BUFSIZE) + { + g_radio_trace_cntr = 0; + } + + g_radio_trace[g_radio_trace_cntr].time = perf_gettime(); + g_radio_trace[g_radio_trace_cntr].str = g_radio_trace_str[type]; + g_radio_trace[g_radio_trace_cntr].arg = arg; + g_radio_trace_cntr += 1; +} + +/**************************************************************************** + * Name: nrf52_radioi8_trace_dump + * + * Description: + * Dump radio trace. + * + ****************************************************************************/ + +void nrf52_radioi8_trace_dump(void) +{ + int i = 0; + + printf("NRF52 Radio IEEE 802.15.4 Trace dump:\n"); + printf("CPU freq: %d\n\n", BOARD_SYSTICK_CLOCK); + + for (i = 0; i < g_radio_trace_cntr; i += 1) + { + printf("[%lu]: %s %lu\n\n", + g_radio_trace[i].time, + g_radio_trace[i].str, + g_radio_trace[i].arg); + } + + /* Reset trace buffer */ + + g_radio_trace_cntr = 0; + memset((void *)g_radio_trace, 0, sizeof(g_radio_trace)); +} diff --git a/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.h b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.h new file mode 100644 index 0000000000000..5e95c62aafcde --- /dev/null +++ b/arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.h @@ -0,0 +1,106 @@ +/**************************************************************************** + * arch/arm/src/nrf52/ieee802154/nrf52_ieee802154_trace.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_TRACE_H +#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_TRACE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Trace item */ + +struct radio_trace_s +{ + clock_t time; /* Event timestamp */ + const char *str; /* Event string */ + uint32_t arg; /* Optional data */ +}; + +/* This must match char *g_radio_trace_str[] */ + +enum radio_trace_type_e +{ + /* Radio interupts */ + + RADIO_TRACE_IRQ_RADIO, + RADIO_TRACE_IRQ_RXDONE, + RADIO_TRACE_IRQ_TXDONE, + RADIO_TRACE_IRQ_ACKTX, + RADIO_TRACE_IRQ_WAITACK, + RADIO_TRACE_IRQ_RXACKDONE, + RADIO_TRACE_IRQ_TXCCABUSY, + + /* Timer interrupts */ + + RADIO_TRACE_IRQ_TIMACKTX, + RADIO_TRACE_IRQ_TIMTXDELAY, + RADIO_TRACE_IRQ_TIMWAITACK, + RADIO_TRACE_IRQ_TIMCSMADELAY, + RADIO_TRACE_IRQ_RTCSD, + RADIO_TRACE_IRQ_RTCCAP, + RADIO_TRACE_IRQ_RTCTIMESLOT, + RADIO_TRACE_IRQ_RTCBI, + + /* Works */ + + RADIO_TRACE_WORK_RX, + RADIO_TRACE_WORK_TX, + RADIO_TRACE_WORK_BUSY, + RADIO_TRACE_WORK_ED, + RADIO_TRACE_WORK_NOACK, + + /* Various events */ + + RADIO_TRACE_ACKTX, + RADIO_TRACE_TIMSTART, + RADIO_TRACE_RXENABLE, + RADIO_TRACE_RXDISABLE, + RADIO_TRACE_CSMASETUP, + RADIO_TRACE_CSMATRIGGER, + RADIO_TRACE_NOCSMATRIGGER, + RADIO_TRACE_NOACK, + RADIO_TRACE_DROPFRAME, + RADIO_TRACE_TXRETRY, +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_NRF52_RADIO_IEEE802154_TRACE +void nrf52_radioi8_trace_init(void); +void nrf52_radioi8_trace_put(uint8_t type, uint32_t arg); +void nrf52_radioi8_trace_dump(void); +#else +# define nrf52_radioi8_trace_put(...) +#endif + +#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_NRF52_IEEE802154_TRACE_H */ diff --git a/arch/arm/src/nrf52/nrf52_gpiote.c b/arch/arm/src/nrf52/nrf52_gpiote.c index f2bf33855ab3b..d01083bd8b375 100644 --- a/arch/arm/src/nrf52/nrf52_gpiote.c +++ b/arch/arm/src/nrf52/nrf52_gpiote.c @@ -53,8 +53,9 @@ struct nrf52_gpiote_callback_s { - xcpt_t callback; - void *arg; + xcpt_t callback; + void *arg; + uint32_t pinset; }; /**************************************************************************** @@ -462,12 +463,15 @@ int nrf52_gpiote_set_event(uint32_t pinset, flags = enter_critical_section(); - /* Get free channel */ + /* Get free channel or */ for (i = 0; i < GPIOTE_CHANNELS; i++) { - if (g_gpiote_ch_callbacks[i].callback == NULL) + if (g_gpiote_ch_callbacks[i].callback == NULL || + g_gpiote_ch_callbacks[i].pinset == pinset) { + g_gpiote_ch_callbacks[i].pinset = pinset; + /* Configure channel */ nrf52_gpiote_set_ch_event(pinset, i, diff --git a/arch/arm/src/nrf52/nrf52_radio.c b/arch/arm/src/nrf52/nrf52_radio.c index 60ba3f1a071cc..7b72fd36b82b7 100644 --- a/arch/arm/src/nrf52/nrf52_radio.c +++ b/arch/arm/src/nrf52/nrf52_radio.c @@ -41,15 +41,6 @@ #include "hardware/nrf52_radio.h" #include "hardware/nrf52_utils.h" -#warning NRF52 RADIO support is EXPERIMENTAL! - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define NRF52_RADIO_RXBUFFER (255) -#define NRF52_RADIO_TXBUFFER (255) - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -64,17 +55,20 @@ static uint32_t nrf52_radio_getreg(struct nrf52_radio_dev_s *dev, /* Radio operations *********************************************************/ +static void nrf52_radio_reset(struct nrf52_radio_dev_s *dev); +static void nrf52_radio_inten(struct nrf52_radio_dev_s *dev, uint32_t irq); +static void nrf52_radio_intclr(struct nrf52_radio_dev_s *dev, uint32_t irq); +static void nrf52_radio_shorts(struct nrf52_radio_dev_s *dev, uint32_t sh); static int nrf52_radio_power(struct nrf52_radio_dev_s *dev, bool state); static int nrf52_radio_mode_set(struct nrf52_radio_dev_s *dev, uint8_t mode); static int nrf52_radio_freq_set(struct nrf52_radio_dev_s *dev, uint32_t freq); static int nrf52_radio_rssi_get(struct nrf52_radio_dev_s *dev, - int *rssi); + int8_t *rssi); static int nrf52_radio_txpower_set(struct nrf52_radio_dev_s *dev, uint8_t txpower); -static int nrf52_radio_tifs_set(struct nrf52_radio_dev_s *dev, - uint16_t us); +static int nrf52_radio_tifs_set(struct nrf52_radio_dev_s *dev, uint16_t us); static int nrf52_radio_pkt_cfg(struct nrf52_radio_dev_s *dev, struct nrf52_radio_pktcfg_s *cfg); static int nrf52_radio_crc_cfg(struct nrf52_radio_dev_s *dev, @@ -83,22 +77,15 @@ static int nrf52_radio_white_set(struct nrf52_radio_dev_s *dev, uint8_t init); static int nrf52_radio_addr_set(struct nrf52_radio_dev_s *dev, uint8_t i, struct nrf52_radio_addr_s *addr); -static int nrf52_radio_write(struct nrf52_radio_dev_s *dev, - uint8_t *buf, int len); -static int nrf52_radio_read(struct nrf52_radio_dev_s *dev, - uint8_t *buf, int len); static void nrf52_radio_dumpregs(struct nrf52_radio_dev_s *dev); -/* Radio interrupts *********************************************************/ - -static int nrf52_radio_isr(int irq, void *context, void *arg); -static int nrf52_radio_isr_rx(struct nrf52_radio_dev_s *dev); -static int nrf52_radio_isr_tx(struct nrf52_radio_dev_s *dev); - -/* Radio configuration ******************************************************/ - -static int nrf52_radio_setup(struct nrf52_radio_dev_s *dev); -static int nrf52_radio_reset(struct nrf52_radio_dev_s *dev); +#ifdef CONFIG_NRF52_HAVE_IEEE802154 +static void nrf52_radio_sfd_set(struct nrf52_radio_dev_s *dev, uint8_t sfd); +static void nrf52_radio_edcnt_set(struct nrf52_radio_dev_s *dev, + uint32_t edcnt); +static void nrf52_radio_cca_cfg(struct nrf52_radio_dev_s *dev, + struct nrf52_radio_cca_s *cca); +#endif /**************************************************************************** * Private Data @@ -107,8 +94,14 @@ static int nrf52_radio_reset(struct nrf52_radio_dev_s *dev); /* NRF52 radio operations */ struct nrf52_radio_dev_s; -struct nrf52_radio_ops_s g_nrf52_radio_ops = +static struct nrf52_radio_ops_s g_nrf52_radio_ops = { + .reset = nrf52_radio_reset, + .putreg = nrf52_radio_putreg, + .getreg = nrf52_radio_getreg, + .inten = nrf52_radio_inten, + .intclr = nrf52_radio_intclr, + .shorts = nrf52_radio_shorts, .power = nrf52_radio_power, .mode_set = nrf52_radio_mode_set, .freq_set = nrf52_radio_freq_set, @@ -119,33 +112,23 @@ struct nrf52_radio_ops_s g_nrf52_radio_ops = .white_set = nrf52_radio_white_set, .crc_cfg = nrf52_radio_crc_cfg, .addr_set = nrf52_radio_addr_set, - .read = nrf52_radio_read, - .write = nrf52_radio_write, - .dumpregs = nrf52_radio_dumpregs + .dumpregs = nrf52_radio_dumpregs, +#ifdef CONFIG_NRF52_HAVE_IEEE802154 + .sfd_set = nrf52_radio_sfd_set, + .edcnt_set = nrf52_radio_edcnt_set, + .cca_cfg = nrf52_radio_cca_cfg, +#endif }; -/* RX buffer 1 */ - -uint8_t g_nrf52_radio_dev_rx1[NRF52_RADIO_RXBUFFER]; - -/* TX buffer 1 */ - -uint8_t g_nrf52_radio_dev_tx1[NRF52_RADIO_TXBUFFER]; - /* Radio device 1 */ -struct nrf52_radio_dev_s g_nrf52_radio_dev_1 = +static struct nrf52_radio_dev_s g_nrf52_radio_dev_1 = { .ops = &g_nrf52_radio_ops, .irq = NRF52_IRQ_RADIO, .base = NRF52_RADIO_BASE, .mode = 0, - .rxbuf_len = NRF52_RADIO_RXBUFFER, - .txbuf_len = NRF52_RADIO_TXBUFFER, - .rxbuf = g_nrf52_radio_dev_rx1, - .txbuf = g_nrf52_radio_dev_tx1, .lock = NXMUTEX_INITIALIZER, - .sem_isr = SEM_INITIALIZER(0), }; /**************************************************************************** @@ -181,6 +164,45 @@ static uint32_t nrf52_radio_getreg(struct nrf52_radio_dev_s *dev, return getreg32(dev->base + offset); } +/**************************************************************************** + * Name: nrf52_radio_inten + * + * Description: + * Enable interrupts. + * + ****************************************************************************/ + +static void nrf52_radio_inten(struct nrf52_radio_dev_s *dev, uint32_t irq) +{ + nrf52_radio_putreg(dev, NRF52_RADIO_INTENSET_OFFSET, irq); +} + +/**************************************************************************** + * Name: nrf52_radio_intclr + * + * Description: + * Disable interrupts. + * + ****************************************************************************/ + +static void nrf52_radio_intclr(struct nrf52_radio_dev_s *dev, uint32_t irq) +{ + nrf52_radio_putreg(dev, NRF52_RADIO_INTENCLR_OFFSET, irq); +} + +/**************************************************************************** + * Name: nrf52_radio_shorts + * + * Description: + * Configure RADIO shorts + * + ****************************************************************************/ + +static void nrf52_radio_shorts(struct nrf52_radio_dev_s *dev, uint32_t sh) +{ + nrf52_radio_putreg(dev, NRF52_RADIO_SHORTS_OFFSET, sh); +} + /**************************************************************************** * Name: nrf52_radio_power * @@ -272,7 +294,7 @@ static int nrf52_radio_freq_set(struct nrf52_radio_dev_s *dev, if (freq < 2360 || freq > 2500) { - wlerr("ERROR: unsupported radio frequency %d MHz\n", freq); + wlerr("ERROR: unsupported radio frequency %" PRId32" MHz\n", freq); ret = -EINVAL; goto errout; } @@ -282,6 +304,11 @@ static int nrf52_radio_freq_set(struct nrf52_radio_dev_s *dev, if (freq < 2400) { regval |= RADIO_FREQUENCY_MAP_2360MHZ; + freq -= 2360; + } + else + { + freq -= 2400; } regval |= freq; @@ -300,14 +327,13 @@ static int nrf52_radio_freq_set(struct nrf52_radio_dev_s *dev, ****************************************************************************/ static int nrf52_radio_rssi_get(struct nrf52_radio_dev_s *dev, - int *rssi) + int8_t *rssi) { uint32_t regval = 0; /* Start the RSSI meassurement */ - nrf52_radio_putreg(dev, NRF52_RADIO_TASKS_RSSISTART_OFFSET, - RADIO_TASKS_RSSISTART); + nrf52_radio_putreg(dev, NRF52_RADIO_TASKS_RSSISTART_OFFSET, 1); /* Wait for the RSSI sample */ @@ -316,7 +342,7 @@ static int nrf52_radio_rssi_get(struct nrf52_radio_dev_s *dev, /* Get the RSSI sample */ regval = nrf52_radio_getreg(dev, NRF52_RADIO_RSSISAMPLE_OFFSET); - *rssi = -(int)regval; + *rssi = -(int8_t)regval; return OK; } @@ -382,13 +408,13 @@ static int nrf52_radio_addr_set(struct nrf52_radio_dev_s *dev, uint8_t i, /* Get current BASE and PREFIX registers */ base_now = nrf52_radio_getreg(dev, basereg); + UNUSED(base_now); prefix_now = nrf52_radio_getreg(dev, prefixreg); /* TODO: check if new address match to old BASE1 */ if (basereg == NRF52_RADIO_BASE1_OFFSET) { -#warning missing logic! } /* Get new BASE */ @@ -457,8 +483,7 @@ static int nrf52_radio_txpower_set(struct nrf52_radio_dev_s *dev, * ****************************************************************************/ -static int nrf52_radio_tifs_set(struct nrf52_radio_dev_s *dev, - uint16_t us) +static int nrf52_radio_tifs_set(struct nrf52_radio_dev_s *dev, uint16_t us) { int ret = OK; @@ -496,7 +521,7 @@ static int nrf52_radio_pkt_cfg(struct nrf52_radio_dev_s *dev, { uint32_t pcnf0 = 0; uint32_t pcnf1 = 0; - int ret = OK; + int ret = OK; /* LENGTH field length */ @@ -588,14 +613,17 @@ static int nrf52_radio_pkt_cfg(struct nrf52_radio_dev_s *dev, /* Configure base address length */ - if (cfg->bal_len < RADIO_PCNF1_BALEN_MIN || - cfg->bal_len > RADIO_PCNF1_BALEN_MAX) + if (cfg->bal_len) { - ret = -EINVAL; - goto errout; - } + if (cfg->bal_len < RADIO_PCNF1_BALEN_MIN || + cfg->bal_len > RADIO_PCNF1_BALEN_MAX) + { + ret = -EINVAL; + goto errout; + } - pcnf1 |= (cfg->bal_len << RADIO_PCNF1_BALEN_SHIFT); + pcnf1 |= (cfg->bal_len << RADIO_PCNF1_BALEN_SHIFT); + } /* Configure on-air endianness of packet */ @@ -714,126 +742,6 @@ static int nrf52_radio_crc_cfg(struct nrf52_radio_dev_s *dev, return ret; } -/**************************************************************************** - * Name: nrf52_radio_write - * - * Description: - * Write radio packet - * - ****************************************************************************/ - -static int nrf52_radio_write(struct nrf52_radio_dev_s *dev, - uint8_t *buf, int len) -{ - int ret = OK; - - /* Lock device */ - - ret = nxmutex_lock(&dev->lock); - if (ret < 0) - { - return ret; - } - - /* */ - - if (len > dev->txbuf_len) - { - ret = -ENOMEM; - goto errout; - } - - /* Copy packet */ - - memcpy(dev->txbuf, buf, len); - - /* Set packet pointer */ - - DEBUGASSERT(nrf52_easydma_valid(&dev->txbuf)); - nrf52_radio_putreg(dev, NRF52_RADIO_PACKETPTR_OFFSET, &dev->txbuf); - - /* Set state to TX */ - - dev->state = NRF52_RADIO_STATE_TX; - - /* Start TX. - * NOTE: shortcut between READ and START is enabled. - */ - - nrf52_radio_putreg(dev, NRF52_RADIO_TASKS_TXEN_OFFSET, RADIO_TASKS_TXEN); - - /* Wait for IRQ */ - - ret = nxsem_wait(&dev->sem_isr); - -errout: - - /* Unlock device */ - - nxmutex_unlock(&dev->lock); - return ret; -} - -/**************************************************************************** - * Name: nrf52_radio_read - * - * Description: - * Read radio packet - * - ****************************************************************************/ - -static int nrf52_radio_read(struct nrf52_radio_dev_s *dev, - uint8_t *buf, int len) -{ - int ret = OK; - - /* Lock radio */ - - ret = nxmutex_lock(&dev->lock); - if (ret < 0) - { - return ret; - } - - /* */ - - if (len > dev->rxbuf_len) - { - ret = -ENOMEM; - goto errout; - } - - /* Set packet pointer */ - - DEBUGASSERT(nrf52_easydma_valid(&dev->rxbuf)); - nrf52_radio_putreg(dev, NRF52_RADIO_PACKETPTR_OFFSET, &dev->rxbuf); - - /* Set state to RX */ - - dev->state = NRF52_RADIO_STATE_RX; - - /* Start RX. - * NOTE: shortcut between READ and START is enabled. - */ - - nrf52_radio_putreg(dev, NRF52_RADIO_TASKS_RXEN_OFFSET, RADIO_TASKS_RXEN); - - /* Wait for IRQ */ - - ret = nxsem_wait(&dev->sem_isr); - - /* Copy packet */ - - memcpy(buf, dev->rxbuf, len); - -errout: - - /* Unlock radio */ - - nxmutex_unlock(&dev->lock); - return ret; -} - /**************************************************************************** * Name: nrf52_radio_dumpregs * @@ -846,250 +754,176 @@ static void nrf52_radio_dumpregs(struct nrf52_radio_dev_s *dev) { printf("\nnrf52_radio_dumpregs:\n"); - printf("SHORTS 0x%08x\n", + printf("SHORTS 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_SHORTS_OFFSET)); - printf("INTENSET 0x%08x\n", + printf("INTENSET 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_INTENSET_OFFSET)); - printf("CRCSTATUS 0x%08x\n", + printf("CRCSTATUS 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_CRCSTATUS_OFFSET)); - printf("RXMATCH 0x%08x\n", + printf("RXMATCH 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_RXMATCH_OFFSET)); - printf("RXCRC 0x%08x\n", + printf("RXCRC 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_RXCRC_OFFSET)); - printf("DAI 0x%08x\n", + printf("DAI 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAI_OFFSET)); - printf("PDUSTAT 0x%08x\n", + printf("PDUSTAT 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_PDUSTAT_OFFSET)); - printf("PACKETPTR 0x%08x\n", + printf("PACKETPTR 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_PACKETPTR_OFFSET)); - printf("FREQUENCY 0x%08x\n", + printf("FREQUENCY 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_FREQUENCY_OFFSET)); - printf("TXPOWER 0x%08x\n", + printf("TXPOWER 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_TXPOWER_OFFSET)); - printf("MODE 0x%08x\n", + printf("MODE 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_MODE_OFFSET)); - printf("PCNF0 0x%08x\n", + printf("PCNF0 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_PCNF0_OFFSET)); - printf("PCNF1 0x%08x\n", + printf("PCNF1 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_PCNF1_OFFSET)); - printf("BASE0 0x%08x\n", + printf("BASE0 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_BASE0_OFFSET)); - printf("BASE1 0x%08x\n", + printf("BASE1 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_BASE1_OFFSET)); - printf("PREFIX0 0x%08x\n", + printf("PREFIX0 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_PREFIX0_OFFSET)); - printf("PREFIX1 0x%08x\n", + printf("PREFIX1 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_PREFIX1_OFFSET)); - printf("TXADDRESS 0x%08x\n", + printf("TXADDRESS 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_TXADDRESS_OFFSET)); - printf("RXADDRESS 0x%08x\n", - nrf52_radio_getreg(dev, NRF52_RADIO_RXADDRESS_OFFSET)); - printf("CRCCNF 0x%08x\n", + printf("RXADDRESSES 0x%08" PRIx32 "\n", + nrf52_radio_getreg(dev, NRF52_RADIO_RXADDRESSES_OFFSET)); + printf("CRCCNF 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_CRCCNF_OFFSET)); - printf("CRCPOLY 0x%08x\n", + printf("CRCPOLY 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_CRCPOLY_OFFSET)); - printf("CRCINIT 0x%08x\n", + printf("CRCINIT 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_CRCINIT_OFFSET)); - printf("TIFS 0x%08x\n", + printf("TIFS 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_TIFS_OFFSET)); - printf("RSSISAMPLE 0x%08x\n", + printf("RSSISAMPLE 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_RSSISAMPLE_OFFSET)); - printf("STATE 0x%08x\n", + printf("STATE 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_STATE_OFFSET)); - printf("DATAWHITEIV 0x%08x\n", + printf("DATAWHITEIV 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DATAWHITEIV_OFFSET)); - printf("BCC 0x%08x\n", + printf("BCC 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_BCC_OFFSET)); - printf("DAB0 0x%08x\n", + printf("DAB0 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(0))); - printf("DAB1 0x%08x\n", + printf("DAB1 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(1))); - printf("DAB2 0x%08x\n", + printf("DAB2 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(2))); - printf("DAB3 0x%08x\n", + printf("DAB3 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(3))); - printf("DAB4 0x%08x\n", + printf("DAB4 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(4))); - printf("DAB5 0x%08x\n", + printf("DAB5 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(5))); - printf("DAB6 0x%08x\n", + printf("DAB6 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(6))); - printf("DAB7 0x%08x\n", + printf("DAB7 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(6))); - printf("DAP0 0x%08x\n", + printf("DAP0 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(0))); - printf("DAP1 0x%08x\n", + printf("DAP1 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(1))); - printf("DAP2 0x%08x\n", + printf("DAP2 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(2))); - printf("DAP3 0x%08x\n", + printf("DAP3 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(3))); - printf("DAP4 0x%08x\n", + printf("DAP4 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(4))); - printf("DAP5 0x%08x\n", + printf("DAP5 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(5))); - printf("DAP6 0x%08x\n", + printf("DAP6 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(6))); - printf("DAP7 0x%08x\n", + printf("DAP7 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(6))); - printf("DACNF 0x%08x\n", + printf("DACNF 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_DACNF_OFFSET)); - printf("MHRMATCHCONF 0x%08x\n", + printf("MHRMATCHCONF 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_MHRMATCHCONF_OFFSET)); - printf("MHRMATCHMAS 0x%08x\n", + printf("MHRMATCHMAS 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_MHRMATCHMAS_OFFSET)); - printf("MODECNF0 0x%08x\n", + printf("MODECNF0 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_MODECNF0_OFFSET)); - printf("SFD 0x%08x\n", + printf("SFD 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_SFD_OFFSET)); - printf("EDCNT 0x%08x\n", + printf("EDCNT 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_EDCNT_OFFSET)); - printf("EDSAMPLE 0x%08x\n", + printf("EDSAMPLE 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_EDSAMPLE_OFFSET)); - printf("CCACTRL 0x%08x\n", + printf("CCACTRL 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_CCACTRL_OFFSET)); - printf("POWER 0x%08x\n", + printf("POWER 0x%08" PRIx32 "\n", nrf52_radio_getreg(dev, NRF52_RADIO_POWER_OFFSET)); } -/**************************************************************************** - * Name: nrf52_radio_isr_rx - * - * Description: - * RX radio interrupt handler - * - ****************************************************************************/ - -static int nrf52_radio_isr_rx(struct nrf52_radio_dev_s *dev) -{ - /* RX done */ - - nxsem_post(&dev->sem_isr); - - return OK; -} +#ifdef CONFIG_NRF52_HAVE_IEEE802154 /**************************************************************************** - * Name: nrf52_radio_isr_tx + * Name: nrf52_radio_sfd_set * * Description: - * TX radio interrupt handler + * Set SFD. * ****************************************************************************/ -static int nrf52_radio_isr_tx(struct nrf52_radio_dev_s *dev) +static void nrf52_radio_sfd_set(struct nrf52_radio_dev_s *dev, uint8_t sfd) { - /* TX done */ - - nxsem_post(&dev->sem_isr); - - return OK; + nrf52_radio_putreg(dev, NRF52_RADIO_SFD_OFFSET, sfd); } /**************************************************************************** - * Name: nrf52_radio_isr + * Name: nrf52_radio_edcnt_set * * Description: - * Radio interrupt handler + * Set EDCNT. * ****************************************************************************/ -static int nrf52_radio_isr(int irq, void *context, void *arg) +static void nrf52_radio_edcnt_set(struct nrf52_radio_dev_s *dev, + uint32_t edcnt) { - struct nrf52_radio_dev_s *dev = (struct nrf52_radio_dev_s *)arg; - int ret = OK; - uint32_t state = 0; - - DEBUGASSERT(dev); - - /* Get radio state */ - - wlinfo("RADIO ISR STATE=%d\n", dev->state); - - /* Handle radio state */ - - switch (dev->state) - { - case NRF52_RADIO_STATE_RX: - { - /* Transmit DONE */ - - ret = nrf52_radio_isr_rx(dev); - - break; - } - - case NRF52_RADIO_STATE_TX: - { - /* Receive DONE */ - - ret = nrf52_radio_isr_tx(dev); - - break; - } - - case NRF52_RADIO_STATE_DISABLED: - { - break; - } - - default: - { - PANIC(); - break; - } - } - - /* Clear END event */ - - nrf52_radio_putreg(dev, NRF52_RADIO_EVENTS_END_OFFSET, 0); - - /* Update radio state - * NOTE: shortcut between END and DISABLE is enabled. - */ - - dev->state = NRF52_RADIO_STATE_DISABLED; - - return ret; + nrf52_radio_putreg(dev, NRF52_RADIO_EDCNT_OFFSET, edcnt); } /**************************************************************************** - * Name: nrf52_radio_setup + * Name: nrf52_radio_cca_cfg * * Description: - * Initial RADIO setup + * Set CCA configuration * ****************************************************************************/ -static int nrf52_radio_setup(struct nrf52_radio_dev_s *dev) +static void nrf52_radio_cca_cfg(struct nrf52_radio_dev_s *dev, + struct nrf52_radio_cca_s *cca) { uint32_t regval = 0; - int ret = OK; - DEBUGASSERT(dev); + /* CCA mode of operation */ - /* Configure interrupts: - * 1. END - packet sent or received - */ + regval |= (cca->mode << 0); - regval = (RADIO_INT_END); - nrf52_radio_putreg(dev, NRF52_RADIO_INTENSET_OFFSET, regval); + /* CCA energy busy threshold */ - /* Configure shortucts: - * 1. shortcut between READY and START - * 2. shortcut between END and DISABLE - */ + regval |= ((cca->edthres << RADIO_CCACTRL_CCAEDTHRES_SHIFT) + & RADIO_CCACTRL_CCAEDTHRES_MASK); - regval = RADIO_SHORTS_READY_START; - regval |= RADIO_SHORTS_END_DISABLE; - nrf52_radio_putreg(dev, NRF52_RADIO_SHORTS_OFFSET, regval); + /* CCA correlator busy threshold */ - /* Power on radio */ + regval |= ((cca->corrthres << RADIO_CCACTRL_CCACORRTHRES_SHIFT) + & RADIO_CCACTRL_CCACORRTHRES_MASK); - nrf52_radio_power(dev, true); + /* Limit for occurances above CCACORRTHRES */ - return ret; + regval |= ((cca->corrcnt << RADIO_CCACTRL_CCACORRCNT_SHIFT) + & RADIO_CCACTRL_CCACORRCNT_MASK); + + nrf52_radio_putreg(dev, NRF52_RADIO_CCACTRL_OFFSET, regval); } +#endif /**************************************************************************** * Name: nrf52_radio_reset @@ -1099,21 +933,22 @@ static int nrf52_radio_setup(struct nrf52_radio_dev_s *dev) * ****************************************************************************/ -static int nrf52_radio_reset(struct nrf52_radio_dev_s *dev) +static void nrf52_radio_reset(struct nrf52_radio_dev_s *dev) { /* Turn off radio power */ nrf52_radio_power(dev, false); - - /* Wait some time */ - - nxsig_usleep(100000); - - /* Turn on radio power */ - + up_udelay(100); nrf52_radio_power(dev, true); + up_udelay(100); - return OK; + /* Reset radio state */ + + dev->mode = 0; + dev->tifs = 0; + dev->txpower = 0; + memset(&dev->pktcfg, 0, sizeof(dev->pktcfg)); + memset(&dev->addr, 0, sizeof(dev->addr)); } /**************************************************************************** @@ -1132,7 +967,6 @@ struct nrf52_radio_dev_s * nrf52_radio_initialize(int intf, struct nrf52_radio_board_s *board) { struct nrf52_radio_dev_s *dev = NULL; - int ret = OK; /* Get radio interface */ @@ -1157,13 +991,6 @@ nrf52_radio_initialize(int intf, struct nrf52_radio_board_s *board) /* Reset some data */ memset(&dev->pktcfg, 0, sizeof(struct nrf52_radio_pktcfg_s)); - memset(dev->rxbuf, 0, NRF52_RADIO_RXBUFFER); - memset(dev->txbuf, 0, NRF52_RADIO_TXBUFFER); - - /* Attach radio interrupt */ - - irq_attach(dev->irq, nrf52_radio_isr, dev); - up_enable_irq(dev->irq); /* Connect board-specific data */ @@ -1171,21 +998,7 @@ nrf52_radio_initialize(int intf, struct nrf52_radio_board_s *board) /* Reset radio */ - ret = nrf52_radio_reset(dev); - if (ret < 0) - { - wlerr("ERROR: failed to reset radio interface %d\n", ret); - goto errout; - } - - /* Initial radio setup */ - - ret = nrf52_radio_setup(dev); - if (ret < 0) - { - wlerr("ERROR: failed to setup radio interface %d\n", ret); - goto errout; - } + nrf52_radio_reset(dev); return dev; diff --git a/arch/arm/src/nrf52/nrf52_radio.h b/arch/arm/src/nrf52/nrf52_radio.h index a0e01804d629f..517c6f459a8bd 100644 --- a/arch/arm/src/nrf52/nrf52_radio.h +++ b/arch/arm/src/nrf52/nrf52_radio.h @@ -40,6 +40,29 @@ #define NRF52_RADIO_LOGICAL_ADDRESS_MAX (8) +/* Ops */ + +#define NRF52_RADIO_RESET(lower) lower->ops->reset(lower) +#define NRF52_RADIO_PUTREG(lower, o, v) lower->ops->putreg(lower, o, v) +#define NRF52_RADIO_GETREG(lower, o) lower->ops->getreg(lower, o) +#define NRF52_RADIO_INTEN(lower, i) lower->ops->inten(lower, i) +#define NRF52_RADIO_INTCLR(lower, i) lower->ops->intclr(lower, i) +#define NRF52_RADIO_SHRTSET(lower, s) lower->ops->shorts(lower, s) +#define NRF52_RADIO_PWRSET(lower, pwr) lower->ops->power(lower, pwr) +#define NRF52_RADIO_MODESET(lower, m) lower->ops->mode_set(lower, m) +#define NRF52_RADIO_FREQSET(lower, f) lower->ops->freq_set(lower, f) +#define NRF52_RADIO_RSSIGET(lower, r) lower->ops->rssi_get(lower, r) +#define NRF52_RADIO_TXPWRSET(lower, p) lower->ops->txpower_set(lower, p) +#define NRF52_RADIO_TIFSSET(lower, p) lower->ops->tifs_set(lower, t) +#define NRF52_RADIO_PKTCFG(lower, cfg) lower->ops->pkt_cfg(lower, cfg) +#define NRF52_RADIO_CRCCFG(lower, cfg) lower->ops->crc_cfg(lower, cfg) +#define NRF52_RADIO_WHITESET(lower, cfg) lower->ops->white_set(lower, c) +#define NRF52_RADIO_ADDRSET(lower, i, a) lower->ops->addr_set(lower, i, a) +#define NRF52_RADIO_DUMPREGS(lower) lower->ops->dumpregs(lower) +#define NRF52_RADIO_SFDSET(lower, sfd) lower->ops->sfd_set(lower, sfd) +#define NRF52_RADIO_EDCNTSET(lower, ec) lower->ops->edcnt_set(lower, ec) +#define NRF52_RADIO_CCACFG(lower, cca) lower->ops->cca_cfg(lower, cca) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -50,20 +73,16 @@ enum nrf52_radio_mode_e { NRF52_RADIO_MODE_NRF1MBIT = 0, NRF52_RADIO_MODE_NRF2MBIT = 1, - NRF52_RADIO_MODE_BLE1MBIT = 2, - NRF52_RADIO_MODE_BLE2MBIT = 3, - NRF52_RADIO_MODE_BLELR125KBIT = 4, - NRF52_RADIO_MODE_BLELR500KBIT = 5, - NRF52_RADIO_MODE_IEEE802154 = 6 -}; - -/* Radio state */ - -enum nrf52_radio_state_e -{ - NRF52_RADIO_STATE_DISABLED = 0, - NRF52_RADIO_STATE_TX = 1, - NRF52_RADIO_STATE_RX = 2, + NRF52_RADIO_MODE_NRF250KBIT = 2, + NRF52_RADIO_MODE_BLE1MBIT = 3, + NRF52_RADIO_MODE_BLE2MBIT = 4, +#ifdef CONFIG_NRF52_HAVE_BLELR + NRF52_RADIO_MODE_BLELR125KBIT = 5, + NRF52_RADIO_MODE_BLELR500KBIT = 6, +#endif +#ifdef CONFIG_NRF52_HAVE_IEEE802154 + NRF52_RADIO_MODE_IEEE802154 = 15 +#endif }; /* Preamble configuration */ @@ -95,7 +114,18 @@ enum nrf52_radio_crc_skipaddr_e NRF52_RADIO_CRC_SKIPADDR_IEEE802154 = 2, }; -/* On air packet layout: +/* CCA mode of operation */ + +enum nrf52_radio_cca_mode_e +{ + NRF52_RADIO_CCA_ED = 0, + NRF52_RADIO_CCA_CARRIER = 1, + NRF52_RADIO_CCA_CARRIER_AND_ED = 2, + NRF52_RADIO_CCA_CARRIER_OR_ED = 2, + NRF52_RADIO_CCA_EDTEST1 = 4, +}; + +/* On air packet layout (no IEEE802154 mode): * * +---------------------------------------+ * | FIRST | @@ -105,7 +135,6 @@ enum nrf52_radio_crc_skipaddr_e * | | ADDRESS | | | * +----------+---------------+----+-------+ * - * * +----------------------------+ * | Stored on RAM | * |----+--------+----+---------| @@ -122,6 +151,20 @@ enum nrf52_radio_crc_skipaddr_e * | | | * +-------+-------+ * + * For IEEE802154 mode packet layout is different: + * + * +--------------------------------------------------------------------+ + * | PHY protocol data unit (PPDU) | + * +--------------------+-----+---------+-------------------------------+ + * | Preamble sequence | SFD | Lenght | PHY payload | + * |--------------------+-----+---------+-------------------------------+ + * | 5 octets synchronization | 1 octet | Maximum 127 octets (PSDU) | + * | header (SHR) | (PHR) +-------------------------------+ + * | | | MAC protocol data unit (MPDU) | + * +--------------------------+---------+-------------------------------+ + * | Stored on RAM | + * +-----------------------------------------+ + * */ /* Radio packet configuration */ @@ -166,11 +209,49 @@ struct nrf52_radio_addr_s uint8_t a4; /* BASE[3] */ }; +#ifdef CONFIG_NRF52_HAVE_IEEE802154 + +/* IEEE 802.15.4 clear channel assessment control */ + +struct nrf52_radio_cca_s +{ + uint8_t mode; /* CCA mode of operation */ + uint8_t edthres; /* CCA energy busy threshold */ + uint8_t corrthres; /* CCA correlator busy threshold */ + uint8_t corrcnt; /* Limit for occurances above CCACORRTHRES */ +}; +#endif + /* NRF52 radio operations */ struct nrf52_radio_dev_s; struct nrf52_radio_ops_s { + /* Reset radio */ + + void (*reset)(struct nrf52_radio_dev_s *dev); + + /* Put register value */ + + void (*putreg)(struct nrf52_radio_dev_s *dev, uint32_t offset, + uint32_t value); + + /* Get register value */ + + uint32_t (*getreg)(struct nrf52_radio_dev_s *dev, uint32_t offset); + + /* Enable interrupts */ + + void (*inten)(struct nrf52_radio_dev_s *dev, uint32_t irq); + + /* Disable interrupts */ + + void (*intclr)(struct nrf52_radio_dev_s *dev, uint32_t irq); + + /* Configure shorts */ + + void (*shorts)(struct nrf52_radio_dev_s *dev, uint32_t irq); + /* Turn-on/turn-off radio power */ int (*power)(struct nrf52_radio_dev_s *dev, bool state); @@ -185,7 +266,7 @@ struct nrf52_radio_ops_s /* Get RSSI sample */ - int (*rssi_get)(struct nrf52_radio_dev_s *dev, int *rssi); + int (*rssi_get)(struct nrf52_radio_dev_s *dev, int8_t *rssi); /* Set TX power */ @@ -214,19 +295,24 @@ struct nrf52_radio_ops_s int (*addr_set)(struct nrf52_radio_dev_s *dev, uint8_t i, struct nrf52_radio_addr_s *addr); - /* Read packet */ + /* Dump radio registers */ + + void (*dumpregs)(struct nrf52_radio_dev_s *dev); - int (*read)(struct nrf52_radio_dev_s *dev, - uint8_t *buf, int len); +#ifdef CONFIG_NRF52_HAVE_IEEE802154 + /* IEEE 802.15.4 start of frame delimiter */ - /* Write packet */ + void (*sfd_set)(struct nrf52_radio_dev_s *dev, uint8_t sfd); - int (*write)(struct nrf52_radio_dev_s *dev, - uint8_t *buf, int len); + /* IEEE 802.15.4 energy detect level */ - /* Dump radio registers */ + void (*edcnt_set)(struct nrf52_radio_dev_s *dev, uint32_t edcnt); - void (*dumpregs)(struct nrf52_radio_dev_s *dev); + /* IEEE 802.15.4 clear channel assessment control */ + + void (*cca_cfg)(struct nrf52_radio_dev_s *dev, + struct nrf52_radio_cca_s *cca); +#endif }; /* NRF52 radio board specific data */ @@ -247,18 +333,10 @@ struct nrf52_radio_dev_s uint32_t base; /* Radio base */ uint32_t irq; /* Radio IRQ number */ uint8_t mode; /* Radio mode */ - uint8_t state; /* Radio state */ struct nrf52_radio_pktcfg_s pktcfg; /* Current packet */ - uint16_t rxbuf_len; /* RX buffer length */ - uint16_t txbuf_len; /* TX buffer length */ - uint8_t *rxbuf; /* RX buffer */ - uint8_t *txbuf; /* TX buffer */ mutex_t lock; /* Mutual exclusion mutex */ - sem_t sem_isr; /* Interrupt wait semaphore */ uint16_t tifs; /* Interframe spacing time */ uint8_t txpower; /* TX power */ - uint8_t txaddr; /* TX address */ - uint8_t rxaddr; /* RX addresses */ struct nrf52_radio_addr_s addr[NRF52_RADIO_LOGICAL_ADDRESS_MAX]; }; diff --git a/arch/arm/src/nrf52/nrf52_radio_ieee802154.h b/arch/arm/src/nrf52/nrf52_radio_ieee802154.h new file mode 100644 index 0000000000000..7160378a50efd --- /dev/null +++ b/arch/arm/src/nrf52/nrf52_radio_ieee802154.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * arch/arm/src/nrf52/nrf52_radio_ieee802154.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF52_NRF52_RADIO_IEEE802154_H +#define __ARCH_ARM_SRC_NRF52_NRF52_RADIO_IEEE802154_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nrf52_radio.h" + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_radioi8_register + * + * Description: + * Register NRF52 radio in IEEE802154 mode + * + ****************************************************************************/ + +struct ieee802154_radio_s * +nrf52_radioi8_register(struct nrf52_radio_board_s *board); + +#endif /* __ARCH_ARM_SRC_NRF52_NRF52_RADIO_IEEE802154_H */ diff --git a/arch/arm/src/nrf52/nrf52_rtc.h b/arch/arm/src/nrf52/nrf52_rtc.h index 8814b9e2040c8..38ed737c38824 100644 --- a/arch/arm/src/nrf52/nrf52_rtc.h +++ b/arch/arm/src/nrf52/nrf52_rtc.h @@ -27,6 +27,8 @@ #include +#include + #include /**************************************************************************** @@ -78,12 +80,12 @@ enum nrf52_rtc_cc_e enum nrf52_rtc_evt_e { - NRF52_RTC_EVT_TICK = 0, - NRF52_RTC_EVT_OVRFLW = 1, - NRF52_RTC_EVT_COMPARE0 = 2, - NRF52_RTC_EVT_COMPARE1 = 3, - NRF52_RTC_EVT_COMPARE2 = 4, - NRF52_RTC_EVT_COMPARE3 = 5, + NRF52_RTC_EVT_COMPARE0 = 0, + NRF52_RTC_EVT_COMPARE1 = 1, + NRF52_RTC_EVT_COMPARE2 = 2, + NRF52_RTC_EVT_COMPARE3 = 3, + NRF52_RTC_EVT_TICK = 4, + NRF52_RTC_EVT_OVRFLW = 5, }; /* NRF52 RTC device */ diff --git a/arch/arm/src/nrf53/nrf53_rtc.h b/arch/arm/src/nrf53/nrf53_rtc.h index b086e2972d93d..7a4a8015e0cb9 100644 --- a/arch/arm/src/nrf53/nrf53_rtc.h +++ b/arch/arm/src/nrf53/nrf53_rtc.h @@ -78,12 +78,12 @@ enum nrf53_rtc_cc_e enum nrf53_rtc_evt_e { - NRF53_RTC_EVT_TICK = 0, - NRF53_RTC_EVT_OVRFLW = 1, - NRF53_RTC_EVT_COMPARE0 = 2, - NRF53_RTC_EVT_COMPARE1 = 3, - NRF53_RTC_EVT_COMPARE2 = 4, - NRF53_RTC_EVT_COMPARE3 = 5, + NRF53_RTC_EVT_COMPARE0 = 0, + NRF53_RTC_EVT_COMPARE1 = 1, + NRF53_RTC_EVT_COMPARE2 = 2, + NRF53_RTC_EVT_COMPARE3 = 3, + NRF53_RTC_EVT_TICK = 4, + NRF53_RTC_EVT_OVRFLW = 5, }; /* NRF53 RTC device */ diff --git a/arch/arm/src/nrf91/nrf91_rtc.h b/arch/arm/src/nrf91/nrf91_rtc.h index acbbe02b523e3..6f1f422ddb5a5 100644 --- a/arch/arm/src/nrf91/nrf91_rtc.h +++ b/arch/arm/src/nrf91/nrf91_rtc.h @@ -78,12 +78,12 @@ enum nrf91_rtc_cc_e enum nrf91_rtc_evt_e { - NRF91_RTC_EVT_TICK = 0, - NRF91_RTC_EVT_OVRFLW = 1, - NRF91_RTC_EVT_COMPARE0 = 2, - NRF91_RTC_EVT_COMPARE1 = 3, - NRF91_RTC_EVT_COMPARE2 = 4, - NRF91_RTC_EVT_COMPARE3 = 5, + NRF91_RTC_EVT_COMPARE0 = 0, + NRF91_RTC_EVT_COMPARE1 = 1, + NRF91_RTC_EVT_COMPARE2 = 2, + NRF91_RTC_EVT_COMPARE3 = 3, + NRF91_RTC_EVT_TICK = 4, + NRF91_RTC_EVT_OVRFLW = 5, }; /* NRF91 RTC device */ diff --git a/arch/arm/src/stm32/stm32_pwm.c b/arch/arm/src/stm32/stm32_pwm.c index df937654cdec2..8e69373cc51c1 100644 --- a/arch/arm/src/stm32/stm32_pwm.c +++ b/arch/arm/src/stm32/stm32_pwm.c @@ -4463,6 +4463,13 @@ static int pwm_stop(struct pwm_lowerhalf_s *dev) outputs = pwm_outputs_from_channels(priv); ret = pwm_outputs_enable(dev, outputs, false); + /* Clear all channels */ + + pwm_putreg(priv, STM32_GTIM_CCR1_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR2_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR3_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR4_OFFSET, 0); + leave_critical_section(flags); pwm_dumpregs(dev, "After stop"); diff --git a/arch/arm/src/stm32f7/stm32_pwm.c b/arch/arm/src/stm32f7/stm32_pwm.c index fb88fcc9aed09..d1d3d76bc2708 100644 --- a/arch/arm/src/stm32f7/stm32_pwm.c +++ b/arch/arm/src/stm32f7/stm32_pwm.c @@ -4007,6 +4007,13 @@ static int pwm_stop(struct pwm_lowerhalf_s *dev) outputs = pwm_outputs_from_channels(priv); ret = pwm_outputs_enable(dev, outputs, false); + /* Clear all channels */ + + pwm_putreg(priv, STM32_GTIM_CCR1_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR2_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR3_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR4_OFFSET, 0); + leave_critical_section(flags); pwm_dumpregs(dev, "After stop"); diff --git a/arch/arm/src/stm32h7/stm32_pwm.c b/arch/arm/src/stm32h7/stm32_pwm.c index e6da7c99f2de4..d6f682ecccb71 100644 --- a/arch/arm/src/stm32h7/stm32_pwm.c +++ b/arch/arm/src/stm32h7/stm32_pwm.c @@ -4227,6 +4227,14 @@ static int pwm_stop(struct pwm_lowerhalf_s *dev) regval &= ~resetbit; putreg32(regval, regaddr); + + /* Clear all channels */ + + pwm_putreg(priv, STM32_GTIM_CCR1_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR2_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR3_OFFSET, 0); + pwm_putreg(priv, STM32_GTIM_CCR4_OFFSET, 0); + leave_critical_section(flags); pwminfo("regaddr: %08" PRIx32 " resetbit: %08" PRIx32 "\n", diff --git a/arch/risc-v/src/k230/k230_hart.c b/arch/risc-v/src/k230/k230_hart.c index ce3e353379ad1..8dca18b708d0b 100644 --- a/arch/risc-v/src/k230/k230_hart.c +++ b/arch/risc-v/src/k230/k230_hart.c @@ -61,6 +61,8 @@ #define RISCV_PMBT_EN (1 << 62) +/* K230 cache flush instructions */ + #define K230_DAT_SYNC_B ".long 0x0ff0000f\n" #define K230_INS_SYNC_B ".long 0x0000100f\n .long 0x0220000f\n" #define K230_I_IALL ".long 0x0100000b\n" @@ -70,12 +72,27 @@ #define ASM __asm__ __volatile__ +/* Hart reset control bits and delays */ + +#define RESET_DONE_BIT (1 << 12) +#define RESET_RQST_BIT (1 << 0) +#define RESET_DONE_ENW (1 << (12 + 16)) +#define RESET_RQST_ENW (1 << (0 + 16)) + +#define RESET_WAIT_USEC 100 + /**************************************************************************** - * Private Functions + * Private Variables ****************************************************************************/ #if !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) +static bool g_big = false; /* true if running on big core */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + /**************************************************************************** * Name: hart_cleanup * Description: from cleanup_before_linux() in K230 U-Boot @@ -99,25 +116,9 @@ static void k230_hart_cleanup(void) ASM(K230_INS_SYNC_B); } -#endif /* !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) */ - /**************************************************************************** * Public Functions ****************************************************************************/ -#if !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) - -/**************************************************************************** - * Name: k230_hart_on_big() - * Description: returns true if running on big core - ****************************************************************************/ - -int k230_hart_is_big(void) -{ - #define MISA_VECTOR_BIT ('V'-'A') - #define MISA_VECOTR_MASK ( 1 << MISA_VECTOR_BIT ) - - return (READ_CSR(CSR_MISA) & MISA_VECOTR_MASK); -} /**************************************************************************** * Name: k230_hart_init() @@ -126,7 +127,10 @@ int k230_hart_is_big(void) void k230_hart_init(void) { - bool big = k230_hart_is_big(); +#define MISA_VECTOR_BIT ('V'-'A') +#define MISA_VECOTR_MASK (1 << MISA_VECTOR_BIT) + + g_big = (READ_CSR(CSR_MISA) & MISA_VECOTR_MASK); k230_hart_cleanup(); @@ -134,73 +138,68 @@ void k230_hart_init(void) WRITE_CSR(CSR_MHCR, MHCR); WRITE_CSR(CSR_MCOR, MCOR); WRITE_CSR(CSR_MSMPR, MSMPR); - WRITE_CSR(CSR_MCCR2, big ? MCCR2_BIG : MCCR2); - WRITE_CSR(CSR_MHINT, big ? MHINT_BIG : MHINT); + WRITE_CSR(CSR_MCCR2, g_big ? MCCR2_BIG : MCCR2); + WRITE_CSR(CSR_MHINT, g_big ? MHINT_BIG : MHINT); #ifdef RISCV_PBMT SET_CSR(CSR_MENVCFG, MENVCFG_PBMT); #endif } -/* Hart reset control bits */ - -#define CORE_DONE_BIT (1 << 12) -#define CORE_REST_BIT (1 << 0) -#define CORE_DONE_ENW (1 << (12 + 16)) -#define CORE_REST_ENW (1 << (0 + 16)) +/**************************************************************************** + * Name: k230_hart_on_big() + * Description: returns true if running on big core + ****************************************************************************/ -#define RESET_DELAY_US 200 +bool k230_hart_is_big(void) +{ + return g_big; +} /**************************************************************************** * Name: k230_hart_big_stop() - * Description: stop big core + * Description: stop big core, can run in S-mode ****************************************************************************/ void k230_hart_big_stop(void) { - volatile uint32_t *rctl = (uint32_t *)K230_CPU1_RESET; - - /* 0x10001000 clear DONE */ - - *rctl = CORE_DONE_BIT | CORE_DONE_ENW; - up_udelay(RESET_DELAY_US); + if (k230_hart_is_big()) return; /* 0x10001 set RESET */ - *rctl = CORE_REST_BIT | CORE_REST_ENW; - up_udelay(RESET_DELAY_US); + putreg32(RESET_RQST_BIT | RESET_RQST_ENW, K230_CPU1_RESET); + up_udelay(RESET_WAIT_USEC); + sinfo("reg: %x\n", getreg32(K230_CPU1_RESET)); } /**************************************************************************** * Name: k230_hart_big_boot() - * Description: start big core from given address + * Description: start big core from given address, can run in S-mode ****************************************************************************/ void k230_hart_big_boot(uintptr_t addr) { - volatile uint32_t *bctl = (uint32_t *)K230_CPU1_BOOTA; - volatile uint32_t *rctl = (uint32_t *)K230_CPU1_RESET; - if (k230_hart_is_big()) return; /* learned from U-Boot baremetal and RTT sysctl_reset_cpu */ - if (addr) *bctl = (uint32_t)addr; + if (addr) putreg32(addr, K230_CPU1_BOOTA); + sinfo("addr=%lx\n", addr); - /* 0x10001000 clear DONE */ + /* 0x10001000 clear DONE bit */ - *rctl = CORE_DONE_BIT | CORE_DONE_ENW; - up_udelay(RESET_DELAY_US); + putreg32(RESET_DONE_BIT | RESET_DONE_ENW, K230_CPU1_RESET); + up_udelay(RESET_WAIT_USEC); - /* 0x10001 set RESET */ + /* 0x10001 set RQST bit */ - *rctl = CORE_REST_BIT | CORE_REST_ENW; - up_udelay(RESET_DELAY_US); + putreg32(RESET_RQST_BIT | RESET_RQST_ENW, K230_CPU1_RESET); + up_udelay(RESET_WAIT_USEC); - /* 0x10000 clear RESET */ + /* 0x10000 clear RQST bit */ - *rctl = CORE_REST_ENW; - up_udelay(RESET_DELAY_US); + putreg32(RESET_RQST_ENW, K230_CPU1_RESET); + up_udelay(RESET_WAIT_USEC); } #endif /* !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) */ @@ -216,7 +215,7 @@ void sbi_late_initialize(void) { /* delegate K230 plic enable to S-mode */ - *((volatile uint32_t *)K230_PLIC_CTRL) = 1; + putreg32(1, K230_PLIC_CTRL); k230_hart_init(); } #endif diff --git a/arch/risc-v/src/k230/k230_hart.h b/arch/risc-v/src/k230/k230_hart.h index 0c8aeff4390f6..76e0950c55bf3 100644 --- a/arch/risc-v/src/k230/k230_hart.h +++ b/arch/risc-v/src/k230/k230_hart.h @@ -32,13 +32,11 @@ #ifndef __ASSEMBLY__ #if !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) -void k230_hart_init(void); /* M-mode initialization */ -int k230_hart_is_big(void); /* check if on big core */ - -#endif /* !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) */ - -void k230_hart_big_boot(uintptr_t boot); /* turn on big core w/ boot addr */ +void k230_hart_init(void); /* M-mode initialization */ +bool k230_hart_is_big(void); /* true if on big core */ +void k230_hart_big_boot(uintptr_t addr); /* turn on big core w/ boot addr */ void k230_hart_big_stop(void); /* turn off big core */ +#endif /* !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) */ #endif /* __ASSEMBLY__ */ #endif /* __ARCH_RISCV_SRC_K230_K230_HART_H */ diff --git a/boards/Kconfig b/boards/Kconfig index 5fed6ec4c0aaa..fe94e4ba1a97f 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -3650,6 +3650,15 @@ endif if ARCH_BOARD_NRF52840_DK source "boards/arm/nrf52/nrf52840-dk/Kconfig" endif +if ARCH_BOARD_THINGY52 +source "boards/arm/nrf52/thingy52/Kconfig" +endif +if ARCH_BOARD_THINGY91_NRF52 +source "boards/arm/nrf52/thingy91-nrf52/Kconfig" +endif +if ARCH_BOARD_NRF9160_DK_NRF52 +source "boards/arm/nrf52/nrf9160-dk-nrf52/Kconfig" +endif if ARCH_BOARD_NUTINY_NUC120 source "boards/arm/nuc1xx/nutiny-nuc120/Kconfig" endif diff --git a/boards/arm/nrf52/common/include/nrf52_ieee802154.h b/boards/arm/nrf52/common/include/nrf52_ieee802154.h new file mode 100644 index 0000000000000..187348bf9eb6a --- /dev/null +++ b/boards/arm/nrf52/common/include/nrf52_ieee802154.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * boards/arm/nrf52/common/include/nrf52_ieee802154.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_IEEE802154_H +#define __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_IEEE802154_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_ieee802154_initialize + * + * Description: + * Initialize IEEE802154 network. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NRF52_RADIO_IEEE802154 +int nrf52_ieee802154_initialize(void); +#endif + +#endif /* __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_IEEE802154_H */ diff --git a/boards/arm/nrf52/common/include/nrf52_mrf24j40.h b/boards/arm/nrf52/common/include/nrf52_mrf24j40.h new file mode 100644 index 0000000000000..cde0af36881c9 --- /dev/null +++ b/boards/arm/nrf52/common/include/nrf52_mrf24j40.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * boards/arm/nrf52/common/include/nrf52_mrf24j40.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_MRF24J40_H +#define __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_MRF24J40_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct nrf52_mrf24j40_s +{ + struct mrf24j40_lower_s dev; + xcpt_t handler; + void *arg; + uint32_t intcfg; + uint8_t spidev; +}; + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_mrf24j40_devsetup + * + * Description: + * Initialize one the MRF24J40 device in one mikroBUS slot + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_IEEE802154_MRF24J40 +int nrf52_mrf24j40_devsetup(struct nrf52_mrf24j40_s *priv); +#endif + +#endif /* __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_MRF24J40_H */ diff --git a/boards/arm/nrf52/common/src/CMakeLists.txt b/boards/arm/nrf52/common/src/CMakeLists.txt index 7c3d75b759068..1900c31e32e45 100644 --- a/boards/arm/nrf52/common/src/CMakeLists.txt +++ b/boards/arm/nrf52/common/src/CMakeLists.txt @@ -36,6 +36,18 @@ if(CONFIG_ARCH_BOARD_COMMON) list(APPEND SRCS nrf52_lsm9ds1.c) endif() + if(CONFIG_NRF52_RADIO_IEEE802154) + list(APPEND SRCS nrf52_ieee802154.c) + endif() + + if(CONFIG_IEEE802154_MRF24J40) + list(APPEND SRCS nrf52_mrf24j40.c) + endif() + + if(CONFIG_BOARDCTL_RESET) + list(APPEND SRCS nrf52_reset.c) + endif() + target_sources(board PRIVATE ${SRCS}) endif() diff --git a/boards/arm/nrf52/common/src/Make.defs b/boards/arm/nrf52/common/src/Make.defs index 07994dc14a707..3d3b75db0ae69 100644 --- a/boards/arm/nrf52/common/src/Make.defs +++ b/boards/arm/nrf52/common/src/Make.defs @@ -36,6 +36,18 @@ ifeq ($(CONFIG_SENSORS_LSM9DS1),y) CSRCS += nrf52_lsm9ds1.c endif +ifeq ($(CONFIG_NRF52_RADIO_IEEE802154),y) +CSRCS += nrf52_ieee802154.c +endif + +ifeq ($(CONFIG_IEEE802154_MRF24J40),y) +CSRCS += nrf52_mrf24j40.c +endif + +ifeq ($(CONFIG_BOARDCTL_RESET),y) +CSRCS += nrf52_reset.c +endif + DEPPATH += --dep-path src VPATH += :src CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src diff --git a/boards/arm/nrf52/common/src/nrf52_ieee802154.c b/boards/arm/nrf52/common/src/nrf52_ieee802154.c new file mode 100644 index 0000000000000..d2dcedd086162 --- /dev/null +++ b/boards/arm/nrf52/common/src/nrf52_ieee802154.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * boards/arm/nrf52/common/src/nrf52_ieee802154.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nrf52_radio_ieee802154.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_ieee802154_initialize + * + * Description: + * Initialize the IEEE 802.15.4 network. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int nrf52_ieee802154_initialize(void) +{ + struct ieee802154_radio_s *radio; + MACHANDLE mac; + int ret; + + /* Initialize and register the SPI MRF24J40 device */ + + radio = nrf52_radioi8_register(NULL); + if (radio == NULL) + { + wlerr("ERROR: Failed to initialize radio\n"); + return -ENODEV; + } + + /* Create a 802.15.4 MAC device from a 802.15.4 compatible radio device. */ + + mac = mac802154_create(radio); + if (mac == NULL) + { + wlerr("ERROR: Failed to initialize IEEE802.15.4 MAC\n"); + return -ENODEV; + } + +#ifdef CONFIG_IEEE802154_NETDEV + /* Use the IEEE802.15.4 MAC interface instance to create a 6LoWPAN + * network interface by wrapping the MAC intrface instance in a + * network device driver via mac802154dev_register(). + */ + + ret = mac802154netdev_register(mac); + if (ret < 0) + { + wlerr("ERROR: Failed to register the MAC network driver wpan%d: %d\n", + 0, ret); + return ret; + } +#endif + +#ifdef CONFIG_IEEE802154_MACDEV + /* If want to call these APIs from userspace, you have to wrap the MAC + * interface in a character device viamac802154dev_register(). + */ + + ret = mac802154dev_register(mac, 0); + if (ret < 0) + { + wlerr("ERROR:"); + wlerr(" Failed to register the MAC character driver /dev/ieee%d: %d\n", + 0, ret); + return ret; + } +#endif + + UNUSED(ret); + return OK; +} diff --git a/boards/arm/nrf52/common/src/nrf52_mrf24j40.c b/boards/arm/nrf52/common/src/nrf52_mrf24j40.c new file mode 100644 index 0000000000000..dcfbf40840f34 --- /dev/null +++ b/boards/arm/nrf52/common/src/nrf52_mrf24j40.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * boards/arm/nrf52/common/src/nrf52_mrf24j40.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "nrf52_gpio.h" +#include "nrf52_spi.h" + +#include "nrf52_mrf24j40.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_DRIVERS_WIRELESS +# error Wireless support requires CONFIG_DRIVERS_WIRELESS +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_mrf24j40_devsetup + * + * Description: + * Initialize one the MRF24J40 device in one mikroBUS slot + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int nrf52_mrf24j40_devsetup(struct nrf52_mrf24j40_s *priv) +{ + struct ieee802154_radio_s *radio; + MACHANDLE mac; + struct spi_dev_s *spi; + int ret; + + /* Configure pins */ + + nrf52_gpio_config(priv->intcfg); + + /* Initialize the SPI bus and get an instance of the SPI interface */ + + spi = nrf52_spibus_initialize(priv->spidev); + if (spi == NULL) + { + wlerr("Failed to initialize SPI bus %d\n", priv->spidev); + return -ENODEV; + } + + /* Initialize and register the SPI MRF24J40 device */ + + radio = mrf24j40_init(spi, &priv->dev); + if (radio == NULL) + { + wlerr("Failed to initialize SPI bus %d\n", priv->spidev); + return -ENODEV; + } + + /* Create a 802.15.4 MAC device from a 802.15.4 compatible radio device. */ + + mac = mac802154_create(radio); + if (mac == NULL) + { + wlerr("Failed to initialize IEEE802.15.4 MAC\n"); + return -ENODEV; + } + +#ifdef CONFIG_IEEE802154_NETDEV + /* Use the IEEE802.15.4 MAC interface instance to create a 6LoWPAN + * network interface by wrapping the MAC intrface instance in a + * network device driver via mac802154dev_register(). + */ + + ret = mac802154netdev_register(mac); + if (ret < 0) + { + wlerr("Failed to register the MAC network driver wpan%d: %d\n", + 0, ret); + return ret; + } +#endif + +#ifdef CONFIG_IEEE802154_MACDEV + /* If want to call these APIs from userspace, you have to wrap the MAC + * interface in a character device viamac802154dev_register(). + */ + + ret = mac802154dev_register(mac, 0); + if (ret < 0) + { + wlerr("Failed to register the MAC character driver /dev/ieee%d: %d\n", + 0, ret); + return ret; + } +#endif + + UNUSED(ret); + return OK; +} diff --git a/boards/arm/nrf52/common/src/nrf52_reset.c b/boards/arm/nrf52/common/src/nrf52_reset.c new file mode 100644 index 0000000000000..b701315f27e2f --- /dev/null +++ b/boards/arm/nrf52/common/src/nrf52_reset.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * boards/arm/nrf52/common/src/nrf52_reset.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_BOARDCTL_RESET + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_reset + * + * Description: + * Reset board. Support for this function is required by board-level + * logic if CONFIG_BOARDCTL_RESET is selected. + * + * Input Parameters: + * status - Status information provided with the reset event. This + * meaning of this status information is board-specific. If not + * used by a board, the value zero may be provided in calls to + * board_reset(). + * + * Returned Value: + * If this function returns, then it was not possible to power-off the + * board due to some constraints. The return value int this case is a + * board-specific reason for the failure to shutdown. + * + ****************************************************************************/ + +int board_reset(int status) +{ + up_systemreset(); + return 0; +} + +#endif /* CONFIG_BOARDCTL_RESET */ diff --git a/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_6lowpan/defconfig b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_6lowpan/defconfig new file mode 100644 index 0000000000000..30404ce4c5463 --- /dev/null +++ b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_6lowpan/defconfig @@ -0,0 +1 @@ +TODO \ No newline at end of file diff --git a/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_mac/defconfig b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_mac/defconfig new file mode 100644 index 0000000000000..e82c9d06fff20 --- /dev/null +++ b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_mac/defconfig @@ -0,0 +1,64 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf52832-dk" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF52832_DK=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52832=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_MRF24J40=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MM_REGIONS=2 +CONFIG_NDEBUG=y +CONFIG_NRF52_GPIOTE=y +CONFIG_NRF52_SPI0_MASTER=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_PROMPT_STRING="nsh-mrf> " +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=65535 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SPI=y +CONFIG_STACK_COLORATION=y +CONFIG_STACK_USAGE=y +CONFIG_START_DAY=26 +CONFIG_START_MONTH=3 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_starhub/defconfig b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_starhub/defconfig new file mode 100644 index 0000000000000..30404ce4c5463 --- /dev/null +++ b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_starhub/defconfig @@ -0,0 +1 @@ +TODO \ No newline at end of file diff --git a/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_starpoint/defconfig b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_starpoint/defconfig new file mode 100644 index 0000000000000..30404ce4c5463 --- /dev/null +++ b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_starpoint/defconfig @@ -0,0 +1 @@ +TODO \ No newline at end of file diff --git a/boards/arm/nrf52/nrf52832-dk/include/board.h b/boards/arm/nrf52/nrf52832-dk/include/board.h index b77688958215c..092a3a0e10bd5 100644 --- a/boards/arm/nrf52/nrf52832-dk/include/board.h +++ b/boards/arm/nrf52/nrf52832-dk/include/board.h @@ -107,4 +107,16 @@ #define BOARD_UART0_RX_PIN (GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(8)) #define BOARD_UART0_TX_PIN (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(6)) +/* SPI Pins *****************************************************************/ + +/* SPI0 - Arduino PINs + * SPI0_SCK - P0.25 (P13) + * SPI0_MISO - P0.24 (D12) + * SPI0_MOSI - P0.23 (D11) + */ + +#define BOARD_SPI0_SCK_PIN (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(25)) +#define BOARD_SPI0_MISO_PIN (GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(24)) +#define BOARD_SPI0_MOSI_PIN (GPIO_OUTPUT | GPIO_PORT0 | GPIO_PIN(23)) + #endif /* __BOARDS_ARM_NRF52_NRF52832_DK_INCLUDE_BOARD_H */ diff --git a/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt b/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt index 7e61a0d0a9e85..689f7b52bf217 100644 --- a/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt +++ b/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt @@ -34,6 +34,14 @@ if(CONFIG_ARCH_BUTTONS) list(APPEND SRCS nrf52_buttons.c) endif() +if(CONFIG_NRF52_SPI_MASTER) + list(APPEND SRCS nrf52_spi.c) +endif() + +if(CONFIG_IEEE802154_MRF24J40) + list(APPEND SRCS nrf52_mrf24j40.c) +endif() + target_sources(board PRIVATE ${SRCS}) if(CONFIG_ARCH_BOARD_COMMON) diff --git a/boards/arm/nrf52/nrf52832-dk/src/Make.defs b/boards/arm/nrf52/nrf52832-dk/src/Make.defs index 7e4e6508fab84..5d5ddc27ee04e 100644 --- a/boards/arm/nrf52/nrf52832-dk/src/Make.defs +++ b/boards/arm/nrf52/nrf52832-dk/src/Make.defs @@ -36,6 +36,14 @@ ifeq ($(CONFIG_ARCH_BUTTONS),y) CSRCS += nrf52_buttons.c endif +ifeq ($(CONFIG_NRF52_SPI_MASTER),y) +CSRCS += nrf52_spi.c +endif + +ifeq ($(CONFIG_IEEE802154_MRF24J40),y) +CSRCS += nrf52_mrf24j40.c +endif + DEPPATH += --dep-path board VPATH += :board CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h b/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h index bdf5c8f0ad79d..c857ac3e5d524 100644 --- a/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h +++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h @@ -64,6 +64,16 @@ #define GPIO_BUTTON3 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN(15)) #define GPIO_BUTTON4 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN(16)) +/* GPIO definitions *********************************************************/ + +/* MRF24J40 pins + * CS - P0.11 + * INT - P0.12 + */ + +#define GPIO_MRF24J40_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(11)) +#define GPIO_MRF24J40_INT (GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(12)) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -94,5 +104,33 @@ int nrf52_bringup(void); +/**************************************************************************** + * Name: nrf52_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the nrf52840-dk board. + * + ****************************************************************************/ + +#ifdef CONFIG_NRF52_SPI_MASTER +void nrf52_spidev_initialize(void); +#endif + +/**************************************************************************** + * Name: nrf52_mrf24j40_initialize + * + * Description: + * Initialize the MRF24J40 device. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_IEEE802154_MRF24J40 +int nrf52_mrf24j40_initialize(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_NRF52_NRF52832_DK_SRC_NRF52832_DK_H */ diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c index a23cf76ca90c1..aeaf57d6305f9 100644 --- a/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c +++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c @@ -54,6 +54,12 @@ void nrf52_board_initialize(void) #ifdef CONFIG_ARCH_LEDS board_autoled_initialize(); #endif + +#ifdef CONFIG_NRF52_SPI_MASTER + /* Configure SPI chip selects */ + + nrf52_spidev_initialize(); +#endif } /**************************************************************************** diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c index 3526a9f93066c..aca8f50019c28 100644 --- a/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c +++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c @@ -53,6 +53,10 @@ # include "nrf52_sdc.h" #endif +#ifdef CONFIG_IEEE802154_MRF24J40 +# include "nrf52_mrf24j40.h" +#endif + #include "nrf52832-dk.h" /**************************************************************************** @@ -152,6 +156,17 @@ int nrf52_bringup(void) } #endif /* CONFIG_MTD */ +#ifdef CONFIG_IEEE802154_MRF24J40 + /* Configure MRF24J40 wireless */ + + ret = nrf52_mrf24j40_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: nrf52_mrf24j40_initialize() failed: %d\n", + ret); + } +#endif + UNUSED(ret); return OK; } diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_mrf24j40.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_mrf24j40.c new file mode 100644 index 0000000000000..0d9d308e52b7e --- /dev/null +++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_mrf24j40.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * boards/arm/nrf52/nrf52832-dk/src/nrf52_mrf24j40.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "nrf52_gpio.h" +#include "nrf52_gpiote.h" +#include "nrf52_spi.h" + +#include "nrf52_mrf24j40.h" + +#include "nrf52832-dk.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_NRF52_SPI0_MASTER +# error this driver requires CONFIG_NRF52_SPI0_MASTER +#endif + +#define NRF52_MRF24J40_SPI (0) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* IRQ/GPIO access callbacks. These operations all hidden behind callbacks + * to isolate the MRF24J40 driver from differences in GPIO interrupt handling + * varying boards and MCUs. + * + * irq_attach - Attach the MRF24J40 interrupt handler to the GPIO + * interrupt + * irq_enable - Enable or disable the GPIO interrupt + */ + +static int nrf52_attach_irq(const struct mrf24j40_lower_s *lower, + xcpt_t handler, void *arg); +static void nrf52_enable_irq(const struct mrf24j40_lower_s *lower, + bool state); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* A reference to a structure of this type must be passed to the MRF24J40 + * driver. This structure provides information about the configuration + * of the MRF24J40 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied + * by the driver and is presumed to persist while the driver is active. The + * memory must be writable because, under certain circumstances, the driver + * may modify frequency or X plate resistance values. + */ + +static struct nrf52_mrf24j40_s g_mrf24j40_priv = +{ + .dev.attach = nrf52_attach_irq, + .dev.enable = nrf52_enable_irq, + .handler = NULL, + .arg = NULL, + .intcfg = GPIO_MRF24J40_INT, + .spidev = NRF52_MRF24J40_SPI, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_attach_irq + * + * Description: + * Attach the MRF24J40 interrupt handler to the GPIO interrupt. + * + ****************************************************************************/ + +static int nrf52_attach_irq(const struct mrf24j40_lower_s *lower, + xcpt_t handler, void *arg) +{ + struct nrf52_mrf24j40_s *priv = (struct nrf52_mrf24j40_s *)lower; + + DEBUGASSERT(priv != NULL); + + /* Just save the handler for use when the interrupt is enabled */ + + priv->handler = handler; + priv->arg = arg; + return OK; +} + +/**************************************************************************** + * Name: nrf52_enable_irq + * + * Description: + * Enable or disable the GPIO interrupt + * + ****************************************************************************/ + +static void nrf52_enable_irq(const struct mrf24j40_lower_s *lower, + bool state) +{ + struct nrf52_mrf24j40_s *priv = (struct nrf52_mrf24j40_s *)lower; + + /* The caller should not attempt to enable interrupts if the handler + * has not yet been 'attached' + */ + + DEBUGASSERT(priv != NULL && (priv->handler != NULL || !state)); + + wlinfo("state:%d\n", (int)state); + + /* Attach and enable, or detach and disable */ + + if (state) + { + nrf52_gpiote_set_event(priv->intcfg, false, true, + priv->handler, priv->arg); + } + else + { + nrf52_gpiote_set_event(priv->intcfg, false, false, + priv->handler, priv->arg); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_mrf24j40_initialize + * + * Description: + * Initialize the MRF24J40 device. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int nrf52_mrf24j40_initialize(void) +{ + int ret; + + ret = nrf52_mrf24j40_devsetup(&g_mrf24j40_priv); + if (ret < 0) + { + wlerr("Failed to initialize mrf24j40: %d\n", ret); + } + + return ret; +} diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c new file mode 100644 index 0000000000000..7e8e6d3adfae3 --- /dev/null +++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "arm_internal.h" +#include "chip.h" +#include "nrf52_gpio.h" +#include "nrf52_spi.h" + +#include "nrf52832-dk.h" +#include + +#ifdef CONFIG_NRF52_SPI_MASTER + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf52_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the Nucleo-144 board. + * + ****************************************************************************/ + +void nrf52_spidev_initialize(void) +{ +#ifdef CONFIG_NRF52_SPI0_MASTER +# ifdef CONFIG_IEEE802154_MRF24J40 + /* Configure the SPI-based MRF24J40 chip select GPIO */ + + spiinfo("Configure GPIO for MRF24J40 SPI1/CS\n"); + + nrf52_gpio_config(GPIO_MRF24J40_CS); + nrf52_gpio_write(GPIO_MRF24J40_CS, true); +# endif +#endif +} + +/**************************************************************************** + * Name: nrf52_spi0/1/2/3/select and nrf52_spi0/1/2/3/status + * + * Description: + * The external functions, nrf52_spi0/1/2/3select and + * nrf52_spi0/1/2/3status must be provided by board-specific logic. + * They are implementations of the select and status methods of the SPI + * interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h). + * All other methods (including nrf52_spibus_initialize()) are provided + * by common NRF52 logic. To use this common SPI logic on your board: + * + * 1. Provide logic in nrf52_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide nrf52_spi0/1/2/3select() and nrf52_spi0/1/2/3status() + * functions in your board-specific logic. These functions will perform + * chip selection and status operations using GPIOs in the way your + * board is configured. + * 3. Add a calls to nrf52_spibus_initialize() in your low level + * application initialization logic + * 4. The handle returned by nrf52_spibus_initialize() may then be used to + * bind the SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +#ifdef CONFIG_NRF52_SPI0_MASTER +void nrf52_spi0select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %08lx CS: %s\n", + (unsigned long)devid, selected ? "assert" : "de-assert"); + + switch (devid) + { +#ifdef CONFIG_IEEE802154_MRF24J40 + case SPIDEV_IEEE802154(0): + { + spiinfo("MRF24J40 device %s\n", + selected ? "asserted" : "de-asserted"); + + /* Set the GPIO low to select and high to de-select */ + + nrf52_gpio_write(GPIO_MRF24J40_CS, !selected); + break; + } +#endif + + default: + { + break; + } + } +} + +uint8_t nrf52_spi0status(struct spi_dev_s *dev, uint32_t devid) +{ + uint8_t status = 0; + + switch (devid) + { +#ifdef CONFIG_IEEE802154_MRF24J40 + case SPIDEV_IEEE802154(0): + { + status |= SPI_STATUS_PRESENT; + break; + } +#endif + + default: + { + break; + } + } + + return status; +} +#endif + +#ifdef CONFIG_NRF52_SPI1_MASTER +void nrf52_spi1select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %08lx CS: %s\n", + (unsigned long)devid, selected ? "assert" : "de-assert"); +} + +uint8_t nrf52_spi1status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_nrf52_SPI2_MASTER +void nrf52_spi2select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %08lx CS: %s\n", + (unsigned long)devid, selected ? "assert" : "de-assert"); +} + +uint8_t nrf52_spi2status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#endif /* CONFIG_NRF52_SPI_MASTER */ diff --git a/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_6lowpan/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_6lowpan/defconfig new file mode 100644 index 0000000000000..a07cdea75e413 --- /dev/null +++ b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_6lowpan/defconfig @@ -0,0 +1,82 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf52840-dk" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF52840_DK=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXAMPLES_NETTEST=y +CONFIG_EXAMPLES_NETTEST_DEVNAME="wpan0" +CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_NETTEST_TARGET2=y +CONFIG_EXAMPLES_UDP=y +CONFIG_EXAMPLES_UDP_CLIENT_PORTNO=61617 +CONFIG_EXAMPLES_UDP_DEVNAME="wpan0" +CONFIG_EXAMPLES_UDP_IPv6=y +CONFIG_EXAMPLES_UDP_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_UDP_TARGET2=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_NETDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MAC802154_NTXDESC=36 +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDEV_HPWORK_THREAD=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETINIT_NETLOCAL=y +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_TELNETD=y +CONFIG_NET_6LOWPAN=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_IPv6=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_PROMPT_STRING="nsh-nrf52> " +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_TELNET_CLIENT=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_mac/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_mac/defconfig new file mode 100644 index 0000000000000..b73fd662e911c --- /dev/null +++ b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_mac/defconfig @@ -0,0 +1,71 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf52840-dk" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF52840_DK=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_PERF_EVENTS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_BUSFAULT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_HARDFAULT_ALERT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_USAGEFAULT=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXPERIMENTAL=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_IOB_DEBUG=y +CONFIG_MM_REGIONS=2 +CONFIG_NDEBUG=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME=y +CONFIG_NRF52_RADIO_IEEE802154_TRACE=y +CONFIG_NRF52_TIMER1=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_PROMPT_STRING="nsh-nrf52> " +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKSTACKSIZE=4096 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKSTACKSIZE=4096 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_CANARIES=y +CONFIG_STACK_COLORATION=y +CONFIG_STACK_USAGE=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_starhub/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_starhub/defconfig new file mode 100644 index 0000000000000..975cef0ed9318 --- /dev/null +++ b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_starhub/defconfig @@ -0,0 +1,74 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf52840-dk" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF52840_DK=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_BUSFAULT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_USAGEFAULT=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXPERIMENTAL=y +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_NETDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETDEV_TELNET=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETINIT_NETLOCAL=y +CONFIG_NETINIT_NOMAC=y +CONFIG_NET_6LOWPAN=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_IPv6=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STAR=y +CONFIG_NET_STARHUB=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_starpoint/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_starpoint/defconfig new file mode 100644 index 0000000000000..f59ac9034077f --- /dev/null +++ b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_starpoint/defconfig @@ -0,0 +1,83 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf52840-dk" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF52840_DK=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_BUSFAULT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_USAGEFAULT=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXAMPLES_NETTEST=y +CONFIG_EXAMPLES_NETTEST_DEVNAME="wpan0" +CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_NETTEST_TARGET2=y +CONFIG_EXAMPLES_UDP=y +CONFIG_EXAMPLES_UDP_CLIENT_PORTNO=61617 +CONFIG_EXAMPLES_UDP_DEVNAME="wpan0" +CONFIG_EXAMPLES_UDP_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_UDP_TARGET2=y +CONFIG_EXPERIMENTAL=y +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_NETDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETINIT_NETLOCAL=y +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_TELNETC=y +CONFIG_NETUTILS_TELNETD=y +CONFIG_NET_6LOWPAN=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_IPv6=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STAR=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf52840-dk/configs/nrfradio/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/nrfradio/defconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c index 4bc740ff011ba..26e8ea89ae135 100644 --- a/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c +++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c @@ -61,13 +61,17 @@ # include "nrf52_lsm9ds1.h" #endif +#ifdef CONFIG_NRF52_RADIO_IEEE802154 +# include "nrf52_ieee802154.h" +#endif + #include "nrf52840-dk.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#define NRF52_TIMER (1) +#define NRF52_TIMER (2) #define LMS9DS1_I2CBUS (0) /**************************************************************************** @@ -309,6 +313,15 @@ int nrf52_bringup(void) } #endif /* CONFIG_SENSORS_LSM6DSL */ +#ifdef CONFIG_NRF52_RADIO_IEEE802154 + ret = nrf52_ieee802154_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize IEE802154 radio: %d\n", + ret); + } +#endif + UNUSED(ret); return OK; } diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_6lowpan/defconfig b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_6lowpan/defconfig new file mode 100644 index 0000000000000..473979b0702c8 --- /dev/null +++ b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_6lowpan/defconfig @@ -0,0 +1,81 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf9160-dk-nrf52" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF9160_DK_NRF52=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXAMPLES_NETTEST=y +CONFIG_EXAMPLES_NETTEST_DEVNAME="wpan0" +CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_NETTEST_TARGET2=y +CONFIG_EXAMPLES_UDP=y +CONFIG_EXAMPLES_UDP_CLIENT_PORTNO=61617 +CONFIG_EXAMPLES_UDP_DEVNAME="wpan0" +CONFIG_EXAMPLES_UDP_IPv6=y +CONFIG_EXAMPLES_UDP_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_UDP_TARGET2=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_NETDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MAC802154_NTXDESC=36 +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDEV_HPWORK_THREAD=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETINIT_NETLOCAL=y +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_TELNETD=y +CONFIG_NET_6LOWPAN=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_IPv6=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_PROMPT_STRING="nsh-nrf91> " +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_TELNET_CLIENT=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_mac/defconfig b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_mac/defconfig new file mode 100644 index 0000000000000..14ba1142a32eb --- /dev/null +++ b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_mac/defconfig @@ -0,0 +1,64 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf9160-dk-nrf52" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF9160_DK_NRF52=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_PERF_EVENTS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_BUSFAULT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_USAGEFAULT=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXPERIMENTAL=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MM_REGIONS=2 +CONFIG_NDEBUG=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME=y +CONFIG_NRF52_RADIO_IEEE802154_TRACE=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_PROMPT_STRING="nsh-nrf91> " +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_STACK_USAGE=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_starhub/defconfig b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_starhub/defconfig new file mode 100644 index 0000000000000..d10a9c3079355 --- /dev/null +++ b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_starhub/defconfig @@ -0,0 +1,76 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf9160-dk-nrf52" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF9160_DK_NRF52=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_BUSFAULT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_USAGEFAULT=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXPERIMENTAL=y +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_NETDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETDEV_TELNET=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETINIT_NETLOCAL=y +CONFIG_NETINIT_NOMAC=y +CONFIG_NET_6LOWPAN=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_IPv6=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STAR=y +CONFIG_NET_STARHUB=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME=y +CONFIG_NRF52_RADIO_IEEE802154_TRACE=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_starpoint/defconfig b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_starpoint/defconfig new file mode 100644 index 0000000000000..3663b2d704db7 --- /dev/null +++ b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_starpoint/defconfig @@ -0,0 +1,85 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf9160-dk-nrf52" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_NRF9160_DK_NRF52=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_BUSFAULT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_USAGEFAULT=y +CONFIG_DRIVERS_IEEE802154=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXAMPLES_NETTEST=y +CONFIG_EXAMPLES_NETTEST_DEVNAME="wpan0" +CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_NETTEST_TARGET2=y +CONFIG_EXAMPLES_UDP=y +CONFIG_EXAMPLES_UDP_CLIENT_PORTNO=61617 +CONFIG_EXAMPLES_UDP_DEVNAME="wpan0" +CONFIG_EXAMPLES_UDP_SERVER_PORTNO=61616 +CONFIG_EXAMPLES_UDP_TARGET2=y +CONFIG_EXPERIMENTAL=y +CONFIG_IEEE802154_I8SAK=y +CONFIG_IEEE802154_MAC=y +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_NETDEV=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETINIT_NETLOCAL=y +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_TELNETC=y +CONFIG_NETUTILS_TELNETD=y +CONFIG_NET_6LOWPAN=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_IPv6=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STAR=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NRF52_HFCLK_XTAL=y +CONFIG_NRF52_RADIO=y +CONFIG_NRF52_RADIO_IEEE802154=y +CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME=y +CONFIG_NRF52_RADIO_IEEE802154_TRACE=y +CONFIG_NRF52_UART0=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_IEEE802154=y diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c index d5bb51e64471c..095fb9d4962d4 100644 --- a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c +++ b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c @@ -27,6 +27,14 @@ #include #include +#include + +#ifdef CONFIG_NRF52_RADIO_IEEE802154 +# include "nrf52_ieee802154.h" +#endif + +#include "nrf9160-dk-nrf52.h" + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -49,6 +57,26 @@ int nrf52_bringup(void) { int ret; +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, NRF52_PROCFS_MOUNTPOINT, "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to mount the PROC filesystem: %d\n", ret); + } +#endif /* CONFIG_FS_PROCFS */ + +#ifdef CONFIG_NRF52_RADIO_IEEE802154 + ret = nrf52_ieee802154_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize IEE802154 radio: %d\n", + ret); + } +#endif + UNUSED(ret); return OK; } diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h index 82fe34c862c52..95744c9424315 100644 --- a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h +++ b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h @@ -34,6 +34,18 @@ * Pre-processor Definitions ****************************************************************************/ +/* Configuration ************************************************************/ + +/* procfs File System */ + +#ifdef CONFIG_FS_PROCFS +# ifdef CONFIG_NSH_PROC_MOUNTPOINT +# define NRF52_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT +# else +# define NRF52_PROCFS_MOUNTPOINT "/proc" +# endif +#endif + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/boards/risc-v/k230/canmv230/scripts/ld-kernel.script b/boards/risc-v/k230/canmv230/scripts/ld-kernel.script index ccba5d210159e..cf673c7456b92 100644 --- a/boards/risc-v/k230/canmv230/scripts/ld-kernel.script +++ b/boards/risc-v/k230/canmv230/scripts/ld-kernel.script @@ -20,8 +20,8 @@ MEMORY { - kflash (rx) : ORIGIN = 0x08200000, LENGTH = 2048K /* w/ cache */ - ksram (rwx) : ORIGIN = 0x08400000, LENGTH = 2048K /* w/ cache */ + kflash (rx) : ORIGIN = 0x08200000, LENGTH = 1024K /* w/ cache */ + ksram (rwx) : ORIGIN = 0x08300000, LENGTH = 1024K /* w/ cache */ pgram (rwx) : ORIGIN = 0x08600000, LENGTH = 10M /* w/ cache */ } diff --git a/drivers/rpmsg/rpmsg_ping.c b/drivers/rpmsg/rpmsg_ping.c index fb8e2e739e50b..883392a4a2fea 100644 --- a/drivers/rpmsg/rpmsg_ping.c +++ b/drivers/rpmsg/rpmsg_ping.c @@ -188,7 +188,7 @@ static void rpmsg_ping_logout_rate(uint64_t len, clock_t avg) int rpmsg_ping(FAR struct rpmsg_endpoint *ept, FAR const struct rpmsg_ping_s *ping) { - clock_t min = UINT_MAX; + clock_t min = CLOCK_MAX; clock_t max = 0; uint64_t total = 0; uint32_t buf_len = 0; diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c index 6690eb2a24a20..ee31c0288656c 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c @@ -554,6 +554,12 @@ int mrf24j40_getattr(FAR struct ieee802154_radio_s *radio, } break; + case IEEE802154_ATTR_PHY_REGDUMP: + { + ret = mrf24j40_regdump(dev); + } + break; + default: ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; } diff --git a/include/debug.h b/include/debug.h index 94b5448b328c6..00ff5682634c1 100644 --- a/include/debug.h +++ b/include/debug.h @@ -938,6 +938,24 @@ # define pciinfo _none #endif +#ifdef CONFIG_DEBUG_RPMSG_ERROR +# define rpmsgerr _err +#else +# define rpmsgerr _none +#endif + +#ifdef CONFIG_DEBUG_RPMSG_WARN +# define rpmsgwarn _warn +#else +# define rpmsgwarn _none +#endif + +#ifdef CONFIG_DEBUG_RPMSG_INFO +# define rpmsginfo _info +#else +# define rpmsginfo _none +#endif + /* Buffer dumping macros do not depend on varargs */ #ifdef CONFIG_DEBUG_ERROR diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 9e2294c37f0bf..35f345ab23878 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -219,6 +219,7 @@ #define IEEE802154_MAX_PHY_PACKET_SIZE 127 #define IEEE802154_TURN_AROUND_TIME 12 /* symbol periods*/ +#define IEEE802154_SYMBOL_US 16 /* 16us */ /* IEEE 802.15.4 MAC constants */ @@ -251,6 +252,11 @@ #define IEEE802154_MAX_SIFS_FRAME_SIZE 18 #define IEEE802154_MIN_CAP_LENGTH 440 #define IEEE802154_UNIT_BACKOFF_PERIOD 20 +#define IEEE802154_LIFS_SYMBOLS 40 +#define IEEE802154_SIFS_SYMBOLS 12 +#define IEEE802154_ACKIFS_SYMBOLS 12 +#define IEEE802154_TIMESLOT_US (16 * 60) +#define IEEE802154_ACK_FRAME_SIZE 5 /* ACK length (FCF + Seq + FCS) */ /* IEEE 802.15.4 MAC PIB Attribute Defaults */ @@ -381,6 +387,7 @@ enum ieee802154_attr_e IEEE802154_ATTR_PHY_SYMBOL_DURATION, IEEE802154_ATTR_PHY_FCS_LEN, IEEE802154_ATTR_PHY_REGDUMP, + IEEE802154_ATTR_PHY_TRACEDUMP, /* MAC PIB Attributes */ diff --git a/libs/libxx/0001-libcxx-remove-mach-time-h.patch b/libs/libxx/0001-libcxx-remove-mach-time-h.patch new file mode 100644 index 0000000000000..7019bc6d563be --- /dev/null +++ b/libs/libxx/0001-libcxx-remove-mach-time-h.patch @@ -0,0 +1,13 @@ +--- libcxx/src/chrono.cpp ++++ libcxx/src/chrono.cpp +@@ -48,10 +48,6 @@ + # include + #endif + +-#if __has_include() +-# include +-#endif +- + #if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) + # pragma comment(lib, "rt") + #endif diff --git a/libs/libxx/libcxx.cmake b/libs/libxx/libcxx.cmake index b20dbf724d3d3..47b8c040e4ccf 100644 --- a/libs/libxx/libcxx.cmake +++ b/libs/libxx/libcxx.cmake @@ -43,7 +43,9 @@ if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/libcxx) patch -p1 -d ${CMAKE_CURRENT_LIST_DIR}/libcxx < ${CMAKE_CURRENT_LIST_DIR}/0001_fix_stdatomic_h_miss_typedef.patch && patch -p3 -d ${CMAKE_CURRENT_LIST_DIR}/libcxx < - ${CMAKE_CURRENT_LIST_DIR}/mbstate_t.patch + ${CMAKE_CURRENT_LIST_DIR}/mbstate_t.patch && patch -p1 -d + ${CMAKE_CURRENT_LIST_DIR}/libcxx < + ${CMAKE_CURRENT_LIST_DIR}/0001-libcxx-remove-mach-time-h.patch DOWNLOAD_NO_PROGRESS true TIMEOUT 30) diff --git a/libs/libxx/libcxx.defs b/libs/libxx/libcxx.defs index ed456f82dd89c..4f8bfd3ca6bc1 100644 --- a/libs/libxx/libcxx.defs +++ b/libs/libxx/libcxx.defs @@ -30,6 +30,7 @@ libcxx: libcxx-$(LIBCXX_VERSION).src.tar.xz --exclude libcxx-$(LIBCXX_VERSION).src/test/std/pstl $(Q) mv libcxx-$(LIBCXX_VERSION).src libcxx $(Q) patch -p2 < mbstate_t.patch + $(Q) patch -p0 < 0001-libcxx-remove-mach-time-h.patch $(Q) touch $@ endif diff --git a/tools/ci/testlist/sim-01.dat b/tools/ci/testlist/sim-01.dat index c0cd6266475be..36ee20c3e6862 100644 --- a/tools/ci/testlist/sim-01.dat +++ b/tools/ci/testlist/sim-01.dat @@ -36,9 +36,6 @@ # macOS matter compilation is not currently supported -Darwin,sim:matter -# macOS has trouble with sim:libcxxtest --Darwin,sim:libcxxtest - # Boards build by CMake CMake,sim:alsa CMake,sim:bluetooth diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index bf64dae181c78..9789570c9ca17 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -458,9 +458,9 @@ static void mac802154_notify_worker(FAR void *arg) * This function is called in the following scenarios: * - The MAC receives a START.request primitive * - Upon receiving the IEEE802154_SFEVENT_ENDOFACTIVE event from the - * this radio layer, the MAC checks the bf_update flag and if set - * calls function. The bf_update flag is set when various attributes - * that effect the beacon are updated. + * this radio layer, the MAC checks the beaconupdate flag and if set + * calls function. The beaconupdate flag is set when various + * attributes that effect the beacon are updated. * * Internal function used by various parts of the MAC layer. This function * uses the various MAC attributes to update the beacon frame. It loads @@ -778,8 +778,8 @@ static void mac802154_purge_worker(FAR void *arg) ****************************************************************************/ static int - mac802154_radiopoll(FAR const struct ieee802154_radiocb_s *radiocb, - bool gts, FAR struct ieee802154_txdesc_s **txdesc) +mac802154_radiopoll(FAR const struct ieee802154_radiocb_s *radiocb, + bool gts, FAR struct ieee802154_txdesc_s **txdesc) { FAR struct mac802154_radiocb_s *cb = (FAR struct mac802154_radiocb_s *)radiocb; diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index 43d08c39c2840..198c5e68a0686 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -146,7 +146,9 @@ int mac802154_req_associate(MACHANDLE mac, return ret; } - /* Get a uin16_t reference to the first two bytes. ie frame control field */ + /* Get a uint16_t reference to the first two bytes. ie frame control + * field + */ iob->io_data[0] = 0; iob->io_data[1] = 0; @@ -879,7 +881,7 @@ static void mac802154_assoctimeout(FAR void *arg) } /**************************************************************************** - * Name: mac802154_extract_assocrespj + * Name: mac802154_extract_assocresp * * Description: * Create and send a Data request command to extract the Association