b224a099fd
The RSSI value in net_pkt (net_pkt_cb_ieee802154.rssi) was used inconsistently across drivers. Some drivers did cast a signed dBm value directly to net_pkt's unsigned byte value. Others were assigning the negative value of the signed dBm value and again others were offsetting and stretching the signed dBm value linearly onto the full unsigned byte range. This change standardizes net_pkt's rssi attribute to represent RSSI on the RX path as an unsigned integer ranging from 0 (–174 dBm) to 254 (80 dBm) and lets 255 represent an "unknown RSSI" (IEEE 802.15.4-2020, section 6.16.2.8). On the TX path the rssi attribute will always be zero. Out-of-range values will be truncated to max/min values. The change also introduces conversion functions to and from signed dBm values and introduces these consistently to all existing call sites. The "unknown RSSI" value is represented as INT16_MIN in this case. In some cases drivers had to be changed to calculate dBm values from internal hardware specific representations. The conversion functions are fully covered by unit tests. Fixes: #58494 Signed-off-by: Florian Grandel <fgrandel@code-for-humans.de>
900 lines
28 KiB
C
900 lines
28 KiB
C
/*
|
|
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT ti_cc13xx_cc26xx_ieee802154_subghz
|
|
|
|
#define LOG_LEVEL CONFIG_IEEE802154_DRIVER_LOG_LEVEL
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(ieee802154_cc13xx_cc26xx_subg);
|
|
|
|
#include <zephyr/device.h>
|
|
#include <errno.h>
|
|
#include <zephyr/sys/byteorder.h>
|
|
#include <zephyr/net/ieee802154_radio.h>
|
|
#include <zephyr/net/ieee802154.h>
|
|
#include <zephyr/net/net_pkt.h>
|
|
#include <zephyr/random/rand32.h>
|
|
#include <string.h>
|
|
#include <zephyr/sys/sys_io.h>
|
|
#include <zephyr/sys/crc.h>
|
|
|
|
#include <driverlib/rf_mailbox.h>
|
|
#include <driverlib/rf_prop_mailbox.h>
|
|
#include <driverlib/rfc.h>
|
|
#include <inc/hw_ccfg.h>
|
|
#include <inc/hw_fcfg1.h>
|
|
#include <rf_patches/rf_patch_cpe_multi_protocol.h>
|
|
|
|
#include <ti/drivers/rf/RF.h>
|
|
|
|
#include "ieee802154_cc13xx_cc26xx_subg.h"
|
|
|
|
static void ieee802154_cc13xx_cc26xx_subg_rx_done(
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data);
|
|
static void ieee802154_cc13xx_cc26xx_subg_data_init(
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data);
|
|
static int ieee802154_cc13xx_cc26xx_subg_stop(
|
|
const struct device *dev);
|
|
static int ieee802154_cc13xx_cc26xx_subg_stop_if(
|
|
const struct device *dev);
|
|
static int ieee802154_cc13xx_cc26xx_subg_rx(
|
|
const struct device *dev);
|
|
static void ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers(
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data);
|
|
|
|
#ifndef CMD_PROP_RADIO_DIV_SETUP_PA
|
|
/* workaround for older HAL TI SDK (less than 4.40) */
|
|
#define CMD_PROP_RADIO_DIV_SETUP_PA CMD_PROP_RADIO_DIV_SETUP
|
|
#endif
|
|
|
|
#if defined(CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_RADIO_SETUP)
|
|
/* User-defined CMD_PROP_RADIO_DIV_SETUP structures */
|
|
#if defined(CONFIG_SOC_CC1352R)
|
|
extern volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup;
|
|
#elif defined(CONFIG_SOC_CC1352P)
|
|
extern volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup;
|
|
#endif /* CONFIG_SOC_CC1352x, extern RADIO_DIV_SETUP */
|
|
|
|
#elif defined(CONFIG_SOC_CC1352R)
|
|
/* Radio values for CC13x2R (note: CC26x2 does not support sub-GHz radio) */
|
|
/* From SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW) */
|
|
static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = {
|
|
/* DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0x7 (DITHER_EN=0 and IPEAK=7). */
|
|
(uint32_t)0x00F788D3,
|
|
/* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
|
|
(uint32_t)0x4001405D,
|
|
/* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
|
|
(uint32_t)0x08141131,
|
|
/* Tx: Configure PA ramp time, PACTL2.RC=0x3 (in ADI0, set PACTL2[4:3]=0x3) */
|
|
ADI_2HALFREG_OVERRIDE(0, 16, 0x8, 0x8, 17, 0x1, 0x1),
|
|
/* Tx: Configure PA ramping, set wait time before turning off */
|
|
/* (0x1A ticks of 16/24 us = 17.3 us). */
|
|
HW_REG_OVERRIDE(0x6028, 0x001A),
|
|
/* Rx: Set AGC reference level to 0x16 (default: 0x2E) */
|
|
HW_REG_OVERRIDE(0x609C, 0x0016),
|
|
/* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2), */
|
|
/* trimmed for external bias and differential configuration */
|
|
(uint32_t)0x000188A3,
|
|
/* Rx: Set anti-aliasing filter bandwidth to 0x8 (in ADI0, set IFAMPCTL3[7:4]=0x8) */
|
|
ADI_HALFREG_OVERRIDE(0, 61, 0xF, 0x8),
|
|
/* Tx: Set PA trim to max to maximize its output power (in ADI0, set PACTL0=0xF8) */
|
|
ADI_REG_OVERRIDE(0, 12, 0xF8),
|
|
(uint32_t)0xFFFFFFFF
|
|
};
|
|
|
|
/* Radio setup command for CC1312R / CC1352R */
|
|
static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup = {
|
|
.commandNo = CMD_PROP_RADIO_DIV_SETUP,
|
|
.condition.rule = COND_NEVER,
|
|
.modulation.modType = 1, /* FSK */
|
|
.modulation.deviation = 200,
|
|
.symbolRate.preScale = 15,
|
|
.symbolRate.rateWord = 131072,
|
|
.rxBw = 0x59, /* 310.8 kHz */
|
|
.preamConf.nPreamBytes = 7,
|
|
.formatConf.nSwBits = 24, /* 24-bit of syncword */
|
|
.formatConf.bMsbFirst = true,
|
|
.formatConf.whitenMode = 7,
|
|
.config.biasMode = true,
|
|
.formatConf.bMsbFirst = true,
|
|
.txPower = 0x013f, /* from Smart RF Studio */
|
|
.centerFreq = 915,
|
|
.intFreq = 0x0999,
|
|
.loDivider = 5,
|
|
.pRegOverride = ieee802154_cc13xx_overrides_sub_ghz,
|
|
};
|
|
|
|
/* Radio values for CC13X2P */
|
|
#elif defined(CONFIG_SOC_CC1352P)
|
|
/* CC1352P overrides from SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW) */
|
|
static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = {
|
|
/* Tx: Configure PA ramp time, PACTL2.RC=0x3 (in ADI0, set PACTL2[4:3]=0x1) */
|
|
ADI_2HALFREG_OVERRIDE(0, 16, 0x8, 0x8, 17, 0x1, 0x0),
|
|
/* Rx: Set AGC reference level to 0x16 (default: 0x2E) */
|
|
HW_REG_OVERRIDE(0x609C, 0x0016),
|
|
/* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2), trimmed */
|
|
/* for external bias and differential configuration */
|
|
(uint32_t)0x000188A3,
|
|
/* Rx: Set anti-aliasing filter bandwidth to 0x6 (in ADI0, set IFAMPCTL3[7:4]=0x8) */
|
|
ADI_HALFREG_OVERRIDE(0, 61, 0xF, 0x8),
|
|
/* override_prop_common_sub1g.xml */
|
|
/* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
|
|
(uint32_t)0x4001405D,
|
|
/* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
|
|
(uint32_t)0x08141131,
|
|
/* override_prop_common.xml */
|
|
/* DC/DC regulator: In Tx with 14 dBm PA setting, use DCDCCTL5[3:0]=0xF */
|
|
/* (DITHER_EN=1 and IPEAK=7). In Rx, use default settings. */
|
|
(uint32_t)0x00F788D3,
|
|
/* TX power override */
|
|
/* Tx: Set PA trim to max to maximize its output power (in ADI0, set PACTL0=0xF8) */
|
|
ADI_REG_OVERRIDE(0, 12, 0xF8),
|
|
(uint32_t)0xFFFFFFFF
|
|
};
|
|
static uint32_t rf_prop_overrides_tx_std[] = {
|
|
/* The TX Power element should always be the first in the list */
|
|
TX_STD_POWER_OVERRIDE(0xB224),
|
|
/* The ANADIV radio parameter based on the LO divider (0) and front-end (0) settings */
|
|
(uint32_t)0x11310703,
|
|
/* override_phy_tx_pa_ramp_genfsk_std.xml */
|
|
/* Tx: Configure PA ramping, set wait time before turning off */
|
|
/* (0x1A ticks of 16/24 us = 17.3 us). */
|
|
HW_REG_OVERRIDE(0x6028, 0x001A),
|
|
(uint32_t)0xFFFFFFFF
|
|
};
|
|
static uint32_t rf_prop_overrides_tx_20[] = {
|
|
/* The TX Power element should always be the first in the list */
|
|
TX20_POWER_OVERRIDE(0x001B8ED2),
|
|
/* The ANADIV radio parameter based on the LO divider (0) and front-end (0) settings */
|
|
(uint32_t)0x11C10703,
|
|
/* override_phy_tx_pa_ramp_genfsk_hpa.xml */
|
|
/* Tx: Configure PA ramping, set wait time before turning off */
|
|
/* (0x1F ticks of 16/24 us = 20.3 us). */
|
|
HW_REG_OVERRIDE(0x6028, 0x001F),
|
|
(uint32_t)0xFFFFFFFF
|
|
};
|
|
|
|
/* Radio setup command for CC1312P / CC1352P */
|
|
static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup = {
|
|
.commandNo = CMD_PROP_RADIO_DIV_SETUP_PA,
|
|
.condition.rule = COND_NEVER,
|
|
.modulation.modType = 1, /* FSK */
|
|
.modulation.deviation = 200,
|
|
.symbolRate.preScale = 15,
|
|
.symbolRate.rateWord = 131072,
|
|
.rxBw = 0x59, /* 310.8 kHz */
|
|
.preamConf.nPreamBytes = 7,
|
|
.formatConf.nSwBits = 24, /* 24-bit of syncword */
|
|
.formatConf.bMsbFirst = true,
|
|
.formatConf.whitenMode = 7,
|
|
.config.biasMode = true,
|
|
.formatConf.bMsbFirst = true,
|
|
.txPower = 0x013f, /* from Smart RF Studio */
|
|
.centerFreq = 915,
|
|
.intFreq = 0x0C00,
|
|
.loDivider = 5,
|
|
.pRegOverride = ieee802154_cc13xx_overrides_sub_ghz,
|
|
.pRegOverrideTxStd = rf_prop_overrides_tx_std,
|
|
.pRegOverrideTx20 = rf_prop_overrides_tx_20,
|
|
};
|
|
#endif /* CONFIG_SOC_CC1352x, default CMD_PROP_RADIO_DIV_SETUP structures */
|
|
|
|
/* Sub GHz power tables */
|
|
#if defined(CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_POWER_TABLE)
|
|
extern RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[];
|
|
|
|
#elif defined(CONFIG_SOC_CC1352R)
|
|
static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = {
|
|
{ -20, RF_TxPowerTable_DEFAULT_PA_ENTRY(0, 3, 0, 2) },
|
|
{ -15, RF_TxPowerTable_DEFAULT_PA_ENTRY(1, 3, 0, 3) },
|
|
{ -10, RF_TxPowerTable_DEFAULT_PA_ENTRY(2, 3, 0, 5) },
|
|
{ -5, RF_TxPowerTable_DEFAULT_PA_ENTRY(4, 3, 0, 5) },
|
|
{ 0, RF_TxPowerTable_DEFAULT_PA_ENTRY(8, 3, 0, 8) },
|
|
{ 1, RF_TxPowerTable_DEFAULT_PA_ENTRY(9, 3, 0, 9) },
|
|
{ 2, RF_TxPowerTable_DEFAULT_PA_ENTRY(10, 3, 0, 9) },
|
|
{ 3, RF_TxPowerTable_DEFAULT_PA_ENTRY(11, 3, 0, 10) },
|
|
{ 4, RF_TxPowerTable_DEFAULT_PA_ENTRY(13, 3, 0, 11) },
|
|
{ 5, RF_TxPowerTable_DEFAULT_PA_ENTRY(14, 3, 0, 14) },
|
|
{ 6, RF_TxPowerTable_DEFAULT_PA_ENTRY(17, 3, 0, 16) },
|
|
{ 7, RF_TxPowerTable_DEFAULT_PA_ENTRY(20, 3, 0, 19) },
|
|
{ 8, RF_TxPowerTable_DEFAULT_PA_ENTRY(24, 3, 0, 22) },
|
|
{ 9, RF_TxPowerTable_DEFAULT_PA_ENTRY(28, 3, 0, 31) },
|
|
{ 10, RF_TxPowerTable_DEFAULT_PA_ENTRY(18, 2, 0, 31) },
|
|
{ 11, RF_TxPowerTable_DEFAULT_PA_ENTRY(26, 2, 0, 51) },
|
|
{ 12, RF_TxPowerTable_DEFAULT_PA_ENTRY(16, 0, 0, 82) },
|
|
{ 13, RF_TxPowerTable_DEFAULT_PA_ENTRY(36, 0, 0, 89) },
|
|
#ifdef CC13X2_CC26X2_BOOST_MODE
|
|
{ 14, RF_TxPowerTable_DEFAULT_PA_ENTRY(63, 0, 1, 0) },
|
|
#endif
|
|
RF_TxPowerTable_TERMINATION_ENTRY
|
|
};
|
|
#elif defined(CONFIG_SOC_CC1352P)
|
|
/* Sub GHz power table */
|
|
static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = {
|
|
{ -20, RF_TxPowerTable_DEFAULT_PA_ENTRY(0, 3, 0, 2) },
|
|
{ -15, RF_TxPowerTable_DEFAULT_PA_ENTRY(1, 3, 0, 3) },
|
|
{ -10, RF_TxPowerTable_DEFAULT_PA_ENTRY(2, 3, 0, 5) },
|
|
{ -5, RF_TxPowerTable_DEFAULT_PA_ENTRY(4, 3, 0, 5) },
|
|
{ 0, RF_TxPowerTable_DEFAULT_PA_ENTRY(8, 3, 0, 8) },
|
|
{ 1, RF_TxPowerTable_DEFAULT_PA_ENTRY(9, 3, 0, 9) },
|
|
{ 2, RF_TxPowerTable_DEFAULT_PA_ENTRY(10, 3, 0, 9) },
|
|
{ 3, RF_TxPowerTable_DEFAULT_PA_ENTRY(11, 3, 0, 10) },
|
|
{ 4, RF_TxPowerTable_DEFAULT_PA_ENTRY(13, 3, 0, 11) },
|
|
{ 5, RF_TxPowerTable_DEFAULT_PA_ENTRY(14, 3, 0, 14) },
|
|
{ 6, RF_TxPowerTable_DEFAULT_PA_ENTRY(17, 3, 0, 16) },
|
|
{ 7, RF_TxPowerTable_DEFAULT_PA_ENTRY(20, 3, 0, 19) },
|
|
{ 8, RF_TxPowerTable_DEFAULT_PA_ENTRY(24, 3, 0, 22) },
|
|
{ 9, RF_TxPowerTable_DEFAULT_PA_ENTRY(28, 3, 0, 31) },
|
|
{ 10, RF_TxPowerTable_DEFAULT_PA_ENTRY(18, 2, 0, 31) },
|
|
{ 11, RF_TxPowerTable_DEFAULT_PA_ENTRY(26, 2, 0, 51) },
|
|
{ 12, RF_TxPowerTable_DEFAULT_PA_ENTRY(16, 0, 0, 82) },
|
|
{ 13, RF_TxPowerTable_DEFAULT_PA_ENTRY(36, 0, 0, 89) },
|
|
#ifdef CC13X2_CC26X2_BOOST_MODE
|
|
{ 14, RF_TxPowerTable_DEFAULT_PA_ENTRY(63, 0, 1, 0) },
|
|
#endif
|
|
{ 15, RF_TxPowerTable_HIGH_PA_ENTRY(18, 0, 0, 36, 0) },
|
|
{ 16, RF_TxPowerTable_HIGH_PA_ENTRY(24, 0, 0, 43, 0) },
|
|
{ 17, RF_TxPowerTable_HIGH_PA_ENTRY(28, 0, 0, 51, 2) },
|
|
{ 18, RF_TxPowerTable_HIGH_PA_ENTRY(34, 0, 0, 64, 4) },
|
|
{ 19, RF_TxPowerTable_HIGH_PA_ENTRY(15, 3, 0, 36, 4) },
|
|
{ 20, RF_TxPowerTable_HIGH_PA_ENTRY(18, 3, 0, 71, 27) },
|
|
RF_TxPowerTable_TERMINATION_ENTRY
|
|
};
|
|
#endif /* CONFIG_SOC_CC1352x power table */
|
|
|
|
/** RF patches to use (note: RF core keeps a pointer to this, so no stack). */
|
|
static RF_Mode rf_mode = {
|
|
.rfMode = RF_MODE_MULTIPLE,
|
|
.cpePatchFxn = &rf_patch_cpe_multi_protocol,
|
|
};
|
|
|
|
|
|
static inline int ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(
|
|
uint16_t channel, uint16_t *frequency, uint16_t *fractFreq)
|
|
{
|
|
__ASSERT_NO_MSG(frequency != NULL);
|
|
__ASSERT_NO_MSG(fractFreq != NULL);
|
|
|
|
if (channel == IEEE802154_SUB_GHZ_CHANNEL_MIN) {
|
|
*frequency = 868;
|
|
/*
|
|
* uint16_t fractional part of 868.3 MHz
|
|
* equivalent to (0.3 * 1000 * BIT(16)) / 1000, rounded up
|
|
*/
|
|
*fractFreq = 0x4ccd;
|
|
} else if (1 <= channel && channel <= IEEE802154_SUB_GHZ_CHANNEL_MAX) {
|
|
*frequency = 906 + 2 * (channel - 1);
|
|
*fractFreq = 0;
|
|
} else if (IEEE802154_2_4_GHZ_CHANNEL_MIN <= channel
|
|
&& channel <= IEEE802154_2_4_GHZ_CHANNEL_MAX) {
|
|
*frequency = 2405 + 5 * (channel - IEEE802154_2_4_GHZ_CHANNEL_MIN);
|
|
*fractFreq = 0;
|
|
} else {
|
|
*frequency = 0;
|
|
*fractFreq = 0;
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline bool is_subghz(uint16_t channel)
|
|
{
|
|
return (channel <= IEEE802154_SUB_GHZ_CHANNEL_MAX);
|
|
}
|
|
|
|
static void cmd_prop_tx_adv_callback(RF_Handle h, RF_CmdHandle ch,
|
|
RF_EventMask e)
|
|
{
|
|
const struct device *const dev = DEVICE_DT_INST_GET(0);
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_Op *op = RF_getCmdOp(h, ch);
|
|
|
|
LOG_DBG("ch: %u cmd: %04x cs st: %04x tx st: %04x e: 0x%" PRIx64, ch,
|
|
op->commandNo, op->status, drv_data->cmd_prop_tx_adv.status, e);
|
|
}
|
|
|
|
static void cmd_prop_rx_adv_callback(RF_Handle h, RF_CmdHandle ch,
|
|
RF_EventMask e)
|
|
{
|
|
const struct device *const dev = DEVICE_DT_INST_GET(0);
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_Op *op = RF_getCmdOp(h, ch);
|
|
|
|
LOG_DBG("ch: %u cmd: %04x st: %04x e: 0x%" PRIx64, ch,
|
|
op->commandNo, op->status, e);
|
|
|
|
if (e & RF_EventRxEntryDone) {
|
|
ieee802154_cc13xx_cc26xx_subg_rx_done(drv_data);
|
|
}
|
|
|
|
if (op->status == PROP_ERROR_RXBUF
|
|
|| op->status == PROP_ERROR_RXFULL
|
|
|| op->status == PROP_ERROR_RXOVF) {
|
|
LOG_DBG("RX Error %x", op->status);
|
|
/* Restart RX */
|
|
(void)ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
}
|
|
}
|
|
|
|
static void client_error_callback(RF_Handle h, RF_CmdHandle ch,
|
|
RF_EventMask e)
|
|
{
|
|
ARG_UNUSED(h);
|
|
ARG_UNUSED(ch);
|
|
LOG_DBG("e: 0x%" PRIx64, e);
|
|
}
|
|
|
|
static void client_event_callback(RF_Handle h, RF_ClientEvent event,
|
|
void *arg)
|
|
{
|
|
ARG_UNUSED(h);
|
|
LOG_DBG("event: %d arg: %p", event, arg);
|
|
}
|
|
|
|
static enum ieee802154_hw_caps
|
|
ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device *dev)
|
|
{
|
|
/* TODO: enable IEEE802154_HW_FILTER */
|
|
return IEEE802154_HW_FCS | IEEE802154_HW_CSMA
|
|
| IEEE802154_HW_SUB_GHZ;
|
|
}
|
|
|
|
static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_Stat status;
|
|
|
|
drv_data->cmd_prop_cs.status = IDLE;
|
|
drv_data->cmd_prop_cs.pNextOp = NULL;
|
|
drv_data->cmd_prop_cs.condition.rule = COND_NEVER;
|
|
|
|
status = RF_runImmediateCmd(drv_data->rf_handle,
|
|
(uint32_t *)&drv_data->cmd_prop_cs);
|
|
if (status != RF_StatSuccess) {
|
|
LOG_ERR("Failed to request CCA (0x%x)", status);
|
|
return -EIO;
|
|
}
|
|
|
|
switch (drv_data->cmd_prop_cs.status) {
|
|
case PROP_DONE_OK:
|
|
return 0;
|
|
case PROP_DONE_BUSY:
|
|
return -EBUSY;
|
|
default:
|
|
return -EIO;
|
|
}
|
|
}
|
|
|
|
static int ieee802154_cc13xx_cc26xx_subg_rx(const struct device *dev)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_CmdHandle cmd_handle;
|
|
|
|
/* Set all RX entries to empty */
|
|
ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers(drv_data);
|
|
|
|
drv_data->cmd_prop_rx_adv.status = IDLE;
|
|
cmd_handle = RF_postCmd(drv_data->rf_handle,
|
|
(RF_Op *)&drv_data->cmd_prop_rx_adv, RF_PriorityNormal,
|
|
cmd_prop_rx_adv_callback, RF_EventRxEntryDone);
|
|
if (cmd_handle < 0) {
|
|
LOG_DBG("Failed to post RX command (%d)", cmd_handle);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ieee802154_cc13xx_cc26xx_subg_set_channel(
|
|
const struct device *dev, uint16_t channel)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_EventMask reason;
|
|
uint16_t freq, fract;
|
|
int r;
|
|
|
|
if (!is_subghz(channel)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
r = ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(
|
|
channel, &freq, &fract);
|
|
if (r < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Abort FG and BG processes */
|
|
if (ieee802154_cc13xx_cc26xx_subg_stop(dev) < 0) {
|
|
return -EIO;
|
|
}
|
|
|
|
/* Block TX while changing channel */
|
|
k_mutex_lock(&drv_data->tx_mutex, K_FOREVER);
|
|
|
|
/* Set the frequency */
|
|
drv_data->cmd_fs.status = IDLE;
|
|
drv_data->cmd_fs.frequency = freq;
|
|
drv_data->cmd_fs.fractFreq = fract;
|
|
reason = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
|
|
RF_PriorityNormal, NULL, 0);
|
|
if (reason != RF_EventLastCmdDone) {
|
|
LOG_DBG("Failed to set frequency: 0x%" PRIx64, reason);
|
|
r = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
/* Run BG receive process on requested channel */
|
|
r = ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
|
|
out:
|
|
k_mutex_unlock(&drv_data->tx_mutex);
|
|
return r;
|
|
}
|
|
|
|
static int
|
|
ieee802154_cc13xx_cc26xx_subg_filter(const struct device *dev, bool set,
|
|
enum ieee802154_filter_type type,
|
|
const struct ieee802154_filter *filter)
|
|
{
|
|
ARG_UNUSED(dev);
|
|
ARG_UNUSED(set);
|
|
ARG_UNUSED(type);
|
|
ARG_UNUSED(filter);
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
static int ieee802154_cc13xx_cc26xx_subg_set_txpower(
|
|
const struct device *dev, int16_t dbm)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_Stat status;
|
|
|
|
RF_TxPowerTable_Value power_table_value = RF_TxPowerTable_findValue(
|
|
(RF_TxPowerTable_Entry *)ieee802154_cc13xx_subg_power_table, dbm);
|
|
|
|
if (power_table_value.rawValue == RF_TxPowerTable_INVALID_VALUE) {
|
|
LOG_DBG("RF_TxPowerTable_findValue() failed");
|
|
return -EINVAL;
|
|
}
|
|
|
|
status = RF_setTxPower(drv_data->rf_handle, power_table_value);
|
|
if (status != RF_StatSuccess) {
|
|
LOG_DBG("RF_setTxPower() failed: %d", status);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* See IEEE 802.15.4 section 6.2.5.1 and TRM section 25.5.4.3 */
|
|
static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev,
|
|
enum ieee802154_tx_mode mode,
|
|
struct net_pkt *pkt,
|
|
struct net_buf *frag)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
int retry = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_RADIO_TX_RETRIES;
|
|
RF_EventMask reason;
|
|
int r;
|
|
|
|
if (mode != IEEE802154_TX_MODE_CSMA_CA) {
|
|
NET_ERR("TX mode %d not supported", mode);
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
k_mutex_lock(&drv_data->tx_mutex, K_FOREVER);
|
|
|
|
/* Prepend data with the SUN FSK PHY header */
|
|
drv_data->tx_data[0] = frag->len + IEEE802154_SUN_PHY_FSK_PHR_LEN;
|
|
/* 20.2.2 PHR field format. 802.15.4-2015 */
|
|
drv_data->tx_data[1] = 0;
|
|
drv_data->tx_data[1] |= BIT(3); /* FCS Type: 2-octet FCS */
|
|
drv_data->tx_data[1] |= BIT(4); /* DW: Enable Data Whitening */
|
|
memcpy(&drv_data->tx_data[IEEE802154_SUN_PHY_FSK_PHR_LEN],
|
|
frag->data, frag->len);
|
|
|
|
/* Chain commands */
|
|
drv_data->cmd_prop_cs.pNextOp =
|
|
(rfc_radioOp_t *) &drv_data->cmd_prop_tx_adv;
|
|
drv_data->cmd_prop_cs.condition.rule = COND_STOP_ON_TRUE;
|
|
|
|
/* Set TX data */
|
|
drv_data->cmd_prop_tx_adv.pktLen = frag->len
|
|
+ IEEE802154_SUN_PHY_FSK_PHR_LEN;
|
|
drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data;
|
|
|
|
/* Abort FG and BG processes */
|
|
r = ieee802154_cc13xx_cc26xx_subg_stop(dev);
|
|
if (r < 0) {
|
|
r = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
do {
|
|
/* Reset command status */
|
|
drv_data->cmd_prop_cs.status = IDLE;
|
|
drv_data->cmd_prop_tx_adv.status = IDLE;
|
|
|
|
reason = RF_runCmd(drv_data->rf_handle,
|
|
(RF_Op *)&drv_data->cmd_prop_cs,
|
|
RF_PriorityNormal, cmd_prop_tx_adv_callback,
|
|
RF_EventLastCmdDone);
|
|
if ((reason & RF_EventLastCmdDone) == 0) {
|
|
LOG_DBG("Failed to run command (%" PRIx64 ")", reason);
|
|
r = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
if (drv_data->cmd_prop_cs.status != PROP_DONE_IDLE) {
|
|
LOG_DBG("Channel access failure (0x%x)",
|
|
drv_data->cmd_prop_cs.status);
|
|
/* Collision Avoidance is a WIP
|
|
* Currently, we just wait a random amount of us in the
|
|
* range [0,256) but k_busy_wait() is fairly inaccurate in
|
|
* practice. Future revisions may attempt to use the RAdio
|
|
* Timer (RAT) to measure this somewhat more precisely.
|
|
*/
|
|
k_busy_wait(sys_rand32_get() & 0xff);
|
|
continue;
|
|
}
|
|
|
|
if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) {
|
|
LOG_DBG("Transmit failed (0x%x)",
|
|
drv_data->cmd_prop_tx_adv.status);
|
|
continue;
|
|
}
|
|
|
|
/* TODO: handle RX acknowledgment */
|
|
r = 0;
|
|
goto out;
|
|
|
|
} while (retry-- > 0);
|
|
|
|
LOG_DBG("Failed to TX");
|
|
r = -EIO;
|
|
|
|
out:
|
|
(void)ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
k_mutex_unlock(&drv_data->tx_mutex);
|
|
return r;
|
|
}
|
|
|
|
static void ieee802154_cc13xx_cc26xx_subg_rx_done(
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
|
|
{
|
|
struct net_pkt *pkt;
|
|
uint8_t len;
|
|
int8_t rssi, status;
|
|
uint8_t *sdu;
|
|
|
|
for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) {
|
|
if (drv_data->rx_entry[i].status == DATA_ENTRY_FINISHED) {
|
|
len = drv_data->rx_data[i][0];
|
|
sdu = drv_data->rx_data[i] + 1;
|
|
status = drv_data->rx_data[i][len--];
|
|
rssi = drv_data->rx_data[i][len--];
|
|
|
|
if (IS_ENABLED(CONFIG_IEEE802154_RAW_MODE) && len > 0) {
|
|
/* append CRC-16/CCITT */
|
|
uint16_t crc = 0;
|
|
|
|
crc = crc16_ccitt(0, sdu, len);
|
|
sdu[len++] = crc;
|
|
sdu[len++] = crc >> 8;
|
|
}
|
|
|
|
LOG_DBG("Received: len = %u, rssi = %d status = %u",
|
|
len, rssi, status);
|
|
|
|
pkt = net_pkt_rx_alloc_with_buffer(
|
|
drv_data->iface, len, AF_UNSPEC, 0, K_NO_WAIT);
|
|
if (!pkt) {
|
|
LOG_WRN("Cannot allocate packet");
|
|
continue;
|
|
}
|
|
|
|
if (net_pkt_write(pkt, sdu, len)) {
|
|
LOG_WRN("Cannot write packet");
|
|
net_pkt_unref(pkt);
|
|
continue;
|
|
}
|
|
|
|
drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
|
|
|
|
/* TODO determine LQI in PROP mode */
|
|
net_pkt_set_ieee802154_lqi(pkt, 0xff);
|
|
net_pkt_set_ieee802154_rssi_dbm(pkt,
|
|
rssi == CC13XX_CC26XX_INVALID_RSSI
|
|
? IEEE802154_MAC_RSSI_DBM_UNDEFINED
|
|
: rssi);
|
|
|
|
if (net_recv_data(drv_data->iface, pkt)) {
|
|
LOG_WRN("Packet dropped");
|
|
net_pkt_unref(pkt);
|
|
}
|
|
|
|
} else if (drv_data->rx_entry[i].status ==
|
|
DATA_ENTRY_UNFINISHED) {
|
|
LOG_WRN("Frame not finished");
|
|
drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int ieee802154_cc13xx_cc26xx_subg_start(const struct device *dev)
|
|
{
|
|
/* Start RX */
|
|
(void)ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Flushes / stops all radio commands in RF queue.
|
|
*/
|
|
static int ieee802154_cc13xx_cc26xx_subg_stop(const struct device *dev)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_Stat status;
|
|
|
|
status = RF_flushCmd(drv_data->rf_handle, RF_CMDHANDLE_FLUSH_ALL, 0);
|
|
if (!(status == RF_StatCmdDoneSuccess
|
|
|| status == RF_StatSuccess
|
|
|| status == RF_StatRadioInactiveError
|
|
|| status == RF_StatInvalidParamsError)) {
|
|
LOG_DBG("Failed to abort radio operations (%d)", status);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Stops the sub-GHz interface and yields the radio (tells RF module to power
|
|
* down).
|
|
*/
|
|
static int ieee802154_cc13xx_cc26xx_subg_stop_if(const struct device *dev)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
int ret;
|
|
|
|
ret = ieee802154_cc13xx_cc26xx_subg_stop(dev);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
|
|
/* power down radio */
|
|
RF_yield(drv_data->rf_handle);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ieee802154_cc13xx_cc26xx_subg_configure(const struct device *dev,
|
|
enum ieee802154_config_type type,
|
|
const struct ieee802154_config *config)
|
|
{
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
uint16_t ieee802154_cc13xx_cc26xx_subg_get_subg_channel_count(
|
|
const struct device *dev)
|
|
{
|
|
ARG_UNUSED(dev);
|
|
|
|
/* IEEE 802.15.4 SubGHz channels range from 0 to 10*/
|
|
return 11;
|
|
}
|
|
|
|
static void ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers(
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
|
|
{
|
|
for (size_t i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; ++i) {
|
|
memset(&drv_data->rx_entry[i], 0, sizeof(drv_data->rx_entry[i]));
|
|
|
|
if (i < CC13XX_CC26XX_NUM_RX_BUF - 1) {
|
|
drv_data->rx_entry[i].pNextEntry =
|
|
(uint8_t *) &drv_data->rx_entry[i + 1];
|
|
} else {
|
|
drv_data->rx_entry[i].pNextEntry =
|
|
(uint8_t *) &drv_data->rx_entry[0];
|
|
}
|
|
|
|
drv_data->rx_entry[i].config.type = DATA_ENTRY_TYPE_PTR;
|
|
drv_data->rx_entry[i].config.lenSz = 1;
|
|
drv_data->rx_entry[i].length = sizeof(drv_data->rx_data[0]);
|
|
drv_data->rx_entry[i].pData = drv_data->rx_data[i];
|
|
}
|
|
|
|
drv_data->rx_queue.pCurrEntry = (uint8_t *)&drv_data->rx_entry[0];
|
|
drv_data->rx_queue.pLastEntry = NULL;
|
|
}
|
|
|
|
static void ieee802154_cc13xx_cc26xx_subg_data_init(
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
|
|
{
|
|
uint8_t *mac;
|
|
|
|
/* FIXME do multi-protocol devices need more than one IEEE MAC? */
|
|
if (sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_0) != 0xFFFFFFFF &&
|
|
sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_1) != 0xFFFFFFFF) {
|
|
mac = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_MAC_0);
|
|
} else {
|
|
mac = (uint8_t *)(FCFG1_BASE + FCFG1_O_MAC_15_4_0);
|
|
}
|
|
|
|
memcpy(&drv_data->mac, mac, sizeof(drv_data->mac));
|
|
|
|
/* Setup circular RX queue (TRM 25.3.2.7) */
|
|
ieee802154_cc13xx_cc26xx_subg_setup_rx_buffers(drv_data);
|
|
|
|
k_mutex_init(&drv_data->tx_mutex);
|
|
}
|
|
|
|
static void ieee802154_cc13xx_cc26xx_subg_iface_init(struct net_if *iface)
|
|
{
|
|
const struct device *dev = net_if_get_device(iface);
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
|
|
net_if_set_link_addr(iface, drv_data->mac, sizeof(drv_data->mac),
|
|
NET_LINK_IEEE802154);
|
|
|
|
drv_data->iface = iface;
|
|
|
|
ieee802154_init(iface);
|
|
}
|
|
|
|
static struct ieee802154_radio_api
|
|
ieee802154_cc13xx_cc26xx_subg_radio_api = {
|
|
.iface_api.init = ieee802154_cc13xx_cc26xx_subg_iface_init,
|
|
|
|
.get_capabilities = ieee802154_cc13xx_cc26xx_subg_get_capabilities,
|
|
.cca = ieee802154_cc13xx_cc26xx_subg_cca,
|
|
.set_channel = ieee802154_cc13xx_cc26xx_subg_set_channel,
|
|
.filter = ieee802154_cc13xx_cc26xx_subg_filter,
|
|
.set_txpower = ieee802154_cc13xx_cc26xx_subg_set_txpower,
|
|
.tx = ieee802154_cc13xx_cc26xx_subg_tx,
|
|
.start = ieee802154_cc13xx_cc26xx_subg_start,
|
|
.stop = ieee802154_cc13xx_cc26xx_subg_stop_if,
|
|
.configure = ieee802154_cc13xx_cc26xx_subg_configure,
|
|
.get_subg_channel_count =
|
|
ieee802154_cc13xx_cc26xx_subg_get_subg_channel_count,
|
|
};
|
|
|
|
static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev)
|
|
{
|
|
RF_Params rf_params;
|
|
RF_EventMask reason;
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
|
|
/* Initialize driver data */
|
|
ieee802154_cc13xx_cc26xx_subg_data_init(drv_data);
|
|
|
|
/* Setup radio */
|
|
RF_Params_init(&rf_params);
|
|
rf_params.pErrCb = client_error_callback;
|
|
rf_params.pClientEventCb = client_event_callback;
|
|
|
|
drv_data->rf_handle = RF_open(&drv_data->rf_object,
|
|
&rf_mode, (RF_RadioSetup *)&ieee802154_cc13xx_subg_radio_div_setup,
|
|
&rf_params);
|
|
if (drv_data->rf_handle == NULL) {
|
|
LOG_ERR("RF_open() failed");
|
|
return -EIO;
|
|
}
|
|
|
|
/*
|
|
* Run CMD_FS with frequency 0 to ensure RF_currClient is not NULL.
|
|
* RF_currClient is a static variable in the TI RF Driver library.
|
|
* If this is not done, then even CMD_ABORT fails.
|
|
*/
|
|
drv_data->cmd_fs.status = IDLE;
|
|
drv_data->cmd_fs.pNextOp = NULL;
|
|
drv_data->cmd_fs.condition.rule = COND_NEVER;
|
|
drv_data->cmd_fs.synthConf.bTxMode = false;
|
|
drv_data->cmd_fs.frequency = 0;
|
|
drv_data->cmd_fs.fractFreq = 0;
|
|
|
|
reason = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
|
|
RF_PriorityNormal, NULL, 0);
|
|
if (reason != RF_EventLastCmdDone) {
|
|
LOG_ERR("Failed to set frequency: 0x%" PRIx64, reason);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct ieee802154_cc13xx_cc26xx_subg_data
|
|
ieee802154_cc13xx_cc26xx_subg_data = {
|
|
.cmd_set_tx_power = {
|
|
.commandNo = CMD_SET_TX_POWER
|
|
},
|
|
|
|
/* Common Radio Commands */
|
|
.cmd_clear_rx = {
|
|
.commandNo = CMD_CLEAR_RX,
|
|
.pQueue = &ieee802154_cc13xx_cc26xx_subg_data.rx_queue,
|
|
},
|
|
|
|
.cmd_fs = {
|
|
.commandNo = CMD_FS,
|
|
.condition.rule = COND_NEVER,
|
|
},
|
|
|
|
.cmd_prop_rx_adv = {
|
|
.commandNo = CMD_PROP_RX_ADV,
|
|
.condition.rule = COND_NEVER,
|
|
.pktConf = {
|
|
.bRepeatOk = true,
|
|
.bRepeatNok = true,
|
|
.bUseCrc = true,
|
|
.filterOp = true,
|
|
},
|
|
.rxConf = {
|
|
.bAutoFlushIgnored = true,
|
|
.bAutoFlushCrcErr = true,
|
|
.bAppendRssi = true,
|
|
.bAppendStatus = true,
|
|
},
|
|
/* Preamble & SFD for 2-FSK SUN PHY. 802.15.4-2015, 20.2.1 */
|
|
.syncWord0 = 0x0055904E,
|
|
.maxPktLen = IEEE802154_MAX_PHY_PACKET_SIZE,
|
|
.hdrConf = {
|
|
.numHdrBits = 16,
|
|
.numLenBits = 11,
|
|
},
|
|
.lenOffset = -4,
|
|
.endTrigger.triggerType = TRIG_NEVER,
|
|
.pQueue = &ieee802154_cc13xx_cc26xx_subg_data.rx_queue,
|
|
.pOutput =
|
|
(uint8_t *) &ieee802154_cc13xx_cc26xx_subg_data
|
|
.cmd_prop_rx_adv_output,
|
|
},
|
|
|
|
.cmd_prop_cs = {
|
|
.commandNo = CMD_PROP_CS,
|
|
.startTrigger.pastTrig = true,
|
|
.condition.rule = COND_NEVER,
|
|
.csConf.bEnaRssi = true,
|
|
.csConf.busyOp = true,
|
|
.csConf.idleOp = true,
|
|
.rssiThr = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CS_THRESHOLD,
|
|
.corrPeriod = 640, /* Filler, used for correlation only */
|
|
.corrConfig.numCorrInv = 0x03,
|
|
.csEndTrigger.triggerType = TRIG_REL_START,
|
|
/* 8 symbol periods. 802.15.4-2015 Table 11.1 */
|
|
.csEndTime = 5000,
|
|
},
|
|
|
|
.cmd_prop_tx_adv = {
|
|
.commandNo = CMD_PROP_TX_ADV,
|
|
.startTrigger.triggerType = TRIG_NOW,
|
|
.startTrigger.pastTrig = true,
|
|
.condition.rule = COND_NEVER,
|
|
.pktConf.bUseCrc = true,
|
|
/* PHR field format. 802.15.4-2015, 20.2.2 */
|
|
.numHdrBits = 16,
|
|
.preTrigger.triggerType = TRIG_REL_START,
|
|
.preTrigger.pastTrig = true,
|
|
/* Preamble & SFD for 2-FSK SUN PHY. 802.15.4-2015, 20.2.1 */
|
|
.syncWord = 0x0055904E,
|
|
},
|
|
};
|
|
|
|
#if defined(CONFIG_NET_L2_IEEE802154_SUB_GHZ)
|
|
NET_DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_subg_init, NULL,
|
|
&ieee802154_cc13xx_cc26xx_subg_data, NULL,
|
|
CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO,
|
|
&ieee802154_cc13xx_cc26xx_subg_radio_api,
|
|
IEEE802154_L2, NET_L2_GET_CTX_TYPE(IEEE802154_L2),
|
|
IEEE802154_MTU);
|
|
#else
|
|
DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_subg_init, NULL,
|
|
&ieee802154_cc13xx_cc26xx_subg_data, NULL, POST_KERNEL,
|
|
CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO,
|
|
&ieee802154_cc13xx_cc26xx_subg_radio_api);
|
|
#endif
|