22f6c87afc
Based on the 'Technical Reference Manual' for CC13x2/CC26x2 SimpleLink MCU family, the device contains factory pre-programmed 64-bit IEEE MAC address for 802.15.4 radio inside two FCFG 32-bit registers: 1. MAC_15_4_0: first 32-bit of the 64-bit IEEE MAC address 2. MAC_15_4_1: last 32-bit of the 64-bit IEEE MAC address The way current version of the driver setups the address results in incorrect bytes order (the address is reversed): uart:~$ ieee802154 get_ext_addr Extended address: AF:03:B7:25:00:4B:12:00 This fixes the problem in both drivers (also in the Sub-GHz version) which results in use of proper EUI-64 address: uart:~$ ieee802154 get_ext_addr Extended address: 00:12:4B:00:25:B7:03:AF IEEE MAC address was confirmed with UniFlash, nRF Sniffer for 802.15.4 and IEEE OUI database (00:12:4B is one of registered OUI for Texas Instruments). To prevent confusion in future, short notice about bytes order for 'mac' field in driver's data structures was also included. Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
932 lines
29 KiB
C
932 lines
29 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 */
|
|
#else
|
|
|
|
#if defined(CONFIG_SOC_CC1352R)
|
|
/* Radio register overrides for CC13x2R (note: CC26x2 does not support sub-GHz radio)
|
|
* from SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW),
|
|
* approximates SUN FSK PHY, 915 MHz band, operating mode #3.
|
|
*/
|
|
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 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,
|
|
(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(0x013F),
|
|
/* 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),
|
|
/* Set TXRX pin to 0 in RX and high impedance in idle/TX. */
|
|
HW_REG_OVERRIDE(0x60A8, 0x0401),
|
|
(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),
|
|
/* Set TXRX pin to 0 in RX/TX and high impedance in idle. */
|
|
HW_REG_OVERRIDE(0x60A8, 0x0001),
|
|
(uint32_t)0xFFFFFFFF
|
|
};
|
|
|
|
#else
|
|
#error "unsupported CC13xx SoC"
|
|
#endif /* CONFIG_SOC_CC1352x */
|
|
|
|
/* Radio setup command for CC13xx */
|
|
#if defined(CONFIG_SOC_CC1352R)
|
|
static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup = {
|
|
.commandNo = CMD_PROP_RADIO_DIV_SETUP,
|
|
#elif defined(CONFIG_SOC_CC1352P)
|
|
static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup = {
|
|
.commandNo = CMD_PROP_RADIO_DIV_SETUP_PA,
|
|
#endif /* CONFIG_SOC_CC1352x */
|
|
.condition.rule = COND_NEVER,
|
|
.modulation = {
|
|
.modType = 1, /* 2-GFSK - non-standard modulation */
|
|
.deviation = 200, /* +/- 200*250 = 50kHz deviation (modulation index 0.5) */
|
|
},
|
|
.symbolRate = {
|
|
.preScale = 15,
|
|
.rateWord = 131072, /* 200 kBit, see TRM, section 25.10.5.2, formula 15 */
|
|
},
|
|
.rxBw = 0x59, /* 310.8 kHz RX bandwidth, see TRM, section 25.10.5.2, table 25-183 */
|
|
.preamConf.nPreamBytes = 7, /* phyFskPreambleLength = 7 + 1, also see nSwBits below */
|
|
.formatConf = {
|
|
.nSwBits = 24, /* 24-bit (1 byte preamble + 16 bit SFD) */
|
|
.bMsbFirst = true,
|
|
.whitenMode = 7, /* Determine whitening and CRC from PHY header */
|
|
},
|
|
.config.biasMode = true, /* Rely on an external antenna biasing network. */
|
|
.txPower = 0x013f, /* 14 dBm, see TRM 25.3.3.2.16 */
|
|
.centerFreq = 906, /* Set channel page zero, channel 1 by default, see IEEE 802.15.4,
|
|
* section 10.1.3.3.
|
|
* TODO: Use compliant SUN PHY frequencies from channel page 9.
|
|
*/
|
|
.intFreq = 0x8000, /* Use default intermediate frequency. */
|
|
.loDivider = 5,
|
|
.pRegOverride = ieee802154_cc13xx_overrides_sub_ghz,
|
|
#if defined(CONFIG_SOC_CC1352P)
|
|
.pRegOverrideTxStd = rf_prop_overrides_tx_std,
|
|
.pRegOverrideTx20 = rf_prop_overrides_tx_20,
|
|
#endif /* CONFIG_SOC_CC1352P */
|
|
};
|
|
|
|
#endif /* CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_RADIO_SETUP */
|
|
|
|
/* 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 CONFIG_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 CONFIG_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);
|
|
|
|
/* See IEEE 802.15.4, section 10.1.3.3. */
|
|
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 (channel <= IEEE802154_SUB_GHZ_CHANNEL_MAX) {
|
|
*frequency = 906 + 2 * (channel - 1);
|
|
*fractFreq = 0;
|
|
} else {
|
|
*frequency = 0;
|
|
*fractFreq = 0;
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* TODO: This incorrectly mixes up legacy O-QPSK SubGHz PHY channel page zero
|
|
* frequency calculation with SUN FSK operating mode #3 PHY radio settings.
|
|
*
|
|
* The correct channel frequency calculation for this PHY is on channel page 9,
|
|
* using the formula ChanCenterFreq = ChanCenterFreq0 + channel * ChanSpacing.
|
|
*
|
|
* Assuming operating mode #3, the parameters for some frequently used bands
|
|
* on this channel page are:
|
|
* 863 MHz: ChanSpacing 0.2, TotalNumChan 35, ChanCenterFreq0 863.1
|
|
* 915 MHz: ChanSpacing 0.4, TotalNumChan 64, ChanCenterFreq0 902.4
|
|
*
|
|
* See IEEE 802.15.4, section 10.1.3.9.
|
|
*
|
|
* Setting the PHY, channel page, band and operating mode requires additional
|
|
* radio configuration settings.
|
|
*
|
|
* Making derived MAC/PHY PIB attributes available to L2 requires an additional
|
|
* attribute getter, see
|
|
* https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582.
|
|
*/
|
|
|
|
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_SUB_GHZ;
|
|
}
|
|
|
|
static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_EventMask events;
|
|
bool was_rx_on;
|
|
int ret;
|
|
|
|
drv_data->cmd_prop_cs.status = IDLE;
|
|
drv_data->cmd_prop_cs.pNextOp = NULL;
|
|
drv_data->cmd_prop_cs.condition.rule = COND_NEVER;
|
|
|
|
was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE;
|
|
|
|
ret = ieee802154_cc13xx_cc26xx_subg_stop(dev);
|
|
if (ret < 0) {
|
|
ret = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_cs, RF_PriorityNormal,
|
|
NULL, 0);
|
|
if (events != RF_EventLastCmdDone) {
|
|
LOG_DBG("Failed to request CCA: 0x%" PRIx64, events);
|
|
ret = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
switch (drv_data->cmd_prop_cs.status) {
|
|
case PROP_DONE_IDLE:
|
|
/* Do not re-enable RX when the channel is idle as
|
|
* this usually means we want to TX directly after
|
|
* and cannot afford any extra latency.
|
|
*/
|
|
return 0;
|
|
case PROP_DONE_BUSY:
|
|
case PROP_DONE_BUSYTIMEOUT:
|
|
ret = -EBUSY;
|
|
break;
|
|
default:
|
|
ret = -EIO;
|
|
}
|
|
|
|
out:
|
|
/* Re-enable RX if we found it on initially
|
|
* and the channel is busy (or another error
|
|
* occurred) as this usually means we back off
|
|
* and want to be able to receive packets in
|
|
* the meantime.
|
|
*/
|
|
if (was_rx_on) {
|
|
ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
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 events;
|
|
uint16_t freq, fract;
|
|
bool was_rx_on;
|
|
int ret;
|
|
|
|
if (!is_subghz(channel)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(channel, &freq, &fract);
|
|
if (ret < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE;
|
|
|
|
/* Abort FG and BG processes */
|
|
ret = ieee802154_cc13xx_cc26xx_subg_stop(dev);
|
|
if (ret) {
|
|
ret = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
/* 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;
|
|
events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
|
|
RF_PriorityNormal, NULL, 0);
|
|
if (events != RF_EventLastCmdDone) {
|
|
LOG_DBG("Failed to set frequency: 0x%" PRIx64, events);
|
|
ret = -EIO;
|
|
}
|
|
|
|
k_mutex_unlock(&drv_data->tx_mutex);
|
|
|
|
out:
|
|
/* Re-enable RX if we found it on initially. */
|
|
if (was_rx_on) {
|
|
ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
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.7.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 *buf)
|
|
{
|
|
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
|
|
RF_EventMask events;
|
|
int ret;
|
|
|
|
if (mode != IEEE802154_TX_MODE_DIRECT) {
|
|
/* For backwards compatibility we only log an error but do not bail. */
|
|
NET_ERR("TX mode %d not supported - sending directly instead.", mode);
|
|
}
|
|
|
|
k_mutex_lock(&drv_data->tx_mutex, K_FOREVER);
|
|
|
|
/* Prepend data with the SUN FSK PHY header,
|
|
* see IEEE 802.15.4, section 19.2.4.
|
|
*/
|
|
drv_data->tx_data[0] = buf->len + IEEE802154_FCS_LENGTH;
|
|
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 */
|
|
|
|
/* TODO: Zero-copy TX, see discussion in #49775. */
|
|
__ASSERT_NO_MSG(buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN <= CC13XX_CC26XX_TX_BUF_SIZE);
|
|
memcpy(&drv_data->tx_data[IEEE802154_PHY_SUN_FSK_PHR_LEN], buf->data, buf->len);
|
|
|
|
/* Set TX data */
|
|
drv_data->cmd_prop_tx_adv.pktLen = buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN;
|
|
drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data;
|
|
|
|
/* Reset command status */
|
|
drv_data->cmd_prop_tx_adv.status = IDLE;
|
|
drv_data->cmd_prop_tx_adv.pNextOp = NULL;
|
|
|
|
/* Abort FG and BG processes */
|
|
ret = ieee802154_cc13xx_cc26xx_subg_stop(dev);
|
|
if (ret < 0) {
|
|
ret = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_tx_adv,
|
|
RF_PriorityNormal, cmd_prop_tx_adv_callback, RF_EventLastCmdDone);
|
|
if ((events & RF_EventLastCmdDone) == 0) {
|
|
LOG_DBG("Failed to run command (%" PRIx64 ")", events);
|
|
ret = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) {
|
|
LOG_DBG("Transmit failed (0x%x)", drv_data->cmd_prop_tx_adv.status);
|
|
ret = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
(void)ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
k_mutex_unlock(&drv_data->tx_mutex);
|
|
return ret;
|
|
}
|
|
|
|
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--];
|
|
|
|
/* TODO: Configure firmware to include CRC in raw mode. */
|
|
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 (ieee802154_handle_ack(drv_data->iface, pkt) == NET_OK) {
|
|
net_pkt_unref(pkt);
|
|
continue;
|
|
}
|
|
|
|
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 */
|
|
return ieee802154_cc13xx_cc26xx_subg_rx(dev);
|
|
}
|
|
|
|
/**
|
|
* 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 for channel page zero. */
|
|
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;
|
|
|
|
/* TODO: 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);
|
|
}
|
|
|
|
sys_memcpy_swap(&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 events;
|
|
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;
|
|
|
|
events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
|
|
RF_PriorityNormal, NULL, 0);
|
|
if (events != RF_EventLastCmdDone) {
|
|
LOG_ERR("Failed to set frequency: 0x%" PRIx64, events);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_data = {
|
|
/* Common Radio Commands */
|
|
.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,
|
|
},
|
|
/* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0,
|
|
* see IEEE 802.15.4, section 19.2.3.2, table 19-2.
|
|
*/
|
|
.syncWord0 = 0x55904E,
|
|
.maxPktLen = IEEE802154_MAX_PHY_PACKET_SIZE,
|
|
/* PHR field format, see IEEE 802.15.4, section 19.2.4 */
|
|
.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,
|
|
},
|
|
|
|
/* TODO: Support correlation CCA modes, see section 10.2.8. */
|
|
.cmd_prop_cs = {
|
|
.commandNo = CMD_PROP_CS,
|
|
.condition.rule = COND_NEVER,
|
|
.csConf = {
|
|
/* CCA Mode 1: Energy above threshold, see section 10.2.8. */
|
|
.bEnaRssi = true,
|
|
/* Abort as soon as any energy above the ED threshold is detected. */
|
|
.busyOp = true,
|
|
/* Continue sensing until the timeout is reached. */
|
|
.idleOp = false,
|
|
},
|
|
.rssiThr = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CS_THRESHOLD,
|
|
.csEndTrigger.triggerType = TRIG_REL_START,
|
|
/* see IEEE 802.15.4, section 11.3, table 11-1 and section 10.2.8 */
|
|
.csEndTime = RF_convertUsToRatTicks(
|
|
IEEE802154_PHY_A_CCA_TIME *
|
|
IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US),
|
|
},
|
|
|
|
.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, see IEEE 802.15.4, section 19.2.4 */
|
|
.numHdrBits = 16,
|
|
.preTrigger.triggerType = TRIG_REL_START,
|
|
.preTrigger.pastTrig = true,
|
|
/* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0,
|
|
* see IEEE 802.15.4, section 19.2.3.2, table 19-2.
|
|
*/
|
|
.syncWord = 0x55904E,
|
|
},
|
|
};
|
|
|
|
#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
|