blob: 28956ce75e28ad57c888cefb15d1b5277e4b7755 [file] [log] [blame]
/****************************************************************************
* arch/arm/src/nrf52/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 <nuttx/config.h>
#include <debug.h>
#include <string.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mutex.h>
#include <nuttx/wqueue.h>
#include <nuttx/mm/iob.h>
#include "nrf52_ieee802154_trace.h"
#include "nrf52_ieee802154_priv.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;
/* TODO: should we add txdelayed to queue ? */
if (dev->radio->state.csma_busy)
{
return -EBUSY;
}
/* 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;
}