drivers: ieee802154: introduce channel pages
Replaces the previous approach to define bands via hardware capabilities by the standard conforming concept of channel pages. In the short term this allows us to correctly calculate the PHY specific symbol rate and several parameters that directly depend from the symbol rate and were previously not being correctly calculated for some of the drivers whose channel pages could not be represented previously: * We now support sub-nanosecond precision symbol rates for UWB. Rounding errors are being minimized by switching from a divide-then-multiply approach to a multiply-then-divide approach. * UWB HRP: symbol rate depends on channel page specific preamble symbol rate which again requires the pulse repetition value to be known * Several MAC timings are being corrected based on the now correctly calculated symbol rates, namely aTurnaroundTime, aUnitBackoffPeriod, aBaseSuperframeDuration. In the long term, this change unlocks such highly promising functional areas as UWB ranging and SUN-PHY channel hopping in the SubG area (plus of course any other PHY specific feature). Signed-off-by: Florian Grandel <fgrandel@code-for-humans.de>
This commit is contained in:
parent
7c00b81705
commit
a12a6ab5b9
29 changed files with 1052 additions and 369 deletions
|
|
@ -200,6 +200,23 @@ Drivers and Sensors
|
|||
|
||||
* IEEE 802.15.4
|
||||
|
||||
* A new mandatory method attr_get() was introduced into ieee802154_radio_api.
|
||||
Drivers need to implement at least
|
||||
IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES and
|
||||
IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES.
|
||||
* The hardware capabilities IEEE802154_HW_2_4_GHZ and IEEE802154_HW_SUB_GHZ
|
||||
were removed as they were not aligned with the standard and some already
|
||||
existing drivers couldn't properly express their channel page and channel
|
||||
range (notably SUN FSK and HRP UWB drivers). The capabilities were replaced
|
||||
by the standard conforming new driver attribute
|
||||
IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES that fits all in-tree drivers.
|
||||
* The method get_subg_channel_count() was removed from ieee802154_radio_api.
|
||||
This method could not properly express the channel range of existing drivers
|
||||
(notably SUN FSK drivers that implement channel pages > 0 and may not have
|
||||
zero-based channel ranges or UWB drivers that could not be represented at
|
||||
all). The method was replaced by the new driver attribute
|
||||
IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES that fits all in-tree drivers.
|
||||
|
||||
* Interrupt Controller
|
||||
|
||||
* GIC: Architecture version selection is now based on the device tree
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ menuconfig IEEE802154_CC1200
|
|||
bool "TI CC1200 Driver support"
|
||||
default y
|
||||
depends on DT_HAS_TI_CC1200_ENABLED
|
||||
select NET_L2_IEEE802154_SUB_GHZ
|
||||
|
||||
if IEEE802154_CC1200
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ menuconfig IEEE802154_CC13XX_CC26XX_SUB_GHZ
|
|||
bool "TI CC13xx / CC26xx IEEE 802.15.4g driver support"
|
||||
default y
|
||||
depends on DT_HAS_TI_CC13XX_CC26XX_IEEE802154_SUBGHZ_ENABLED
|
||||
select NET_L2_IEEE802154_SUB_GHZ if NET_L2_IEEE802154
|
||||
|
||||
if IEEE802154_CC13XX_CC26XX_SUB_GHZ
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ menuconfig IEEE802154_RF2XX
|
|||
depends on DT_HAS_ATMEL_RF2XX_ENABLED
|
||||
select SPI
|
||||
select GPIO
|
||||
select NET_L2_IEEE802154_SUB_GHZ if NET_L2_IEEE802154
|
||||
|
||||
if IEEE802154_RF2XX
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
|||
|
||||
|
||||
/* B91 data structure */
|
||||
static struct b91_data data;
|
||||
static struct b91_data data;
|
||||
|
||||
/* Set filter PAN ID */
|
||||
static int b91_set_pan_id(uint16_t pan_id)
|
||||
|
|
@ -403,7 +403,7 @@ static enum ieee802154_hw_caps b91_get_capabilities(const struct device *dev)
|
|||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER |
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK;
|
||||
}
|
||||
|
||||
|
|
@ -428,10 +428,14 @@ static int b91_set_channel(const struct device *dev, uint16_t channel)
|
|||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (channel < 11 || channel > 26) {
|
||||
if (channel > 26) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (channel < 11) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (data.current_channel != channel) {
|
||||
data.current_channel = channel;
|
||||
rf_set_chn(B91_LOGIC_CHANNEL_TO_PHYSICAL(channel));
|
||||
|
|
@ -585,6 +589,20 @@ static int b91_configure(const struct device *dev,
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
/* API implementation: attr_get */
|
||||
static int b91_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
/* IEEE802154 driver APIs structure */
|
||||
static struct ieee802154_radio_api b91_radio_api = {
|
||||
.iface_api.init = b91_iface_init,
|
||||
|
|
@ -598,6 +616,7 @@ static struct ieee802154_radio_api b91_radio_api = {
|
|||
.tx = b91_tx,
|
||||
.ed_scan = b91_ed_scan,
|
||||
.configure = b91_configure,
|
||||
.attr_get = b91_attr_get,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ out:
|
|||
*******************/
|
||||
static enum ieee802154_hw_caps cc1200_get_capabilities(const struct device *dev)
|
||||
{
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_SUB_GHZ;
|
||||
return IEEE802154_HW_FCS;
|
||||
}
|
||||
|
||||
static int cc1200_cca(const struct device *dev)
|
||||
|
|
@ -703,11 +703,19 @@ static int cc1200_stop(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t cc1200_get_channel_count(const struct device *dev)
|
||||
{
|
||||
struct cc1200_context *cc1200 = dev->data;
|
||||
/* driver-allocated attribute memory - constant across all driver instances as
|
||||
* this driver's channel range is configured via a global KConfig setting.
|
||||
*/
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 0, IEEE802154_CC1200_CHANNEL_LIMIT);
|
||||
|
||||
return cc1200->rf_settings->channel_limit;
|
||||
static int cc1200_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
/******************
|
||||
|
|
@ -812,7 +820,7 @@ static struct ieee802154_radio_api cc1200_radio_api = {
|
|||
.tx = cc1200_tx,
|
||||
.start = cc1200_start,
|
||||
.stop = cc1200_stop,
|
||||
.get_subg_channel_count = cc1200_get_channel_count,
|
||||
.attr_get = cc1200_attr_get,
|
||||
};
|
||||
|
||||
NET_DEVICE_DT_INST_DEFINE(0, cc1200_init, NULL, &cc1200_context_data,
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ static void client_event_callback(RF_Handle h, RF_ClientEvent event, void *arg)
|
|||
static enum ieee802154_hw_caps
|
||||
ieee802154_cc13xx_cc26xx_get_capabilities(const struct device *dev)
|
||||
{
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER |
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_CSMA |
|
||||
IEEE802154_HW_RETRANSMISSION;
|
||||
}
|
||||
|
|
@ -155,17 +155,17 @@ static inline int ieee802154_cc13xx_cc26xx_channel_to_frequency(
|
|||
__ASSERT_NO_MSG(frequency != NULL);
|
||||
__ASSERT_NO_MSG(fractFreq != NULL);
|
||||
|
||||
if (channel >= IEEE802154_2_4_GHZ_CHANNEL_MIN
|
||||
&& channel <= IEEE802154_2_4_GHZ_CHANNEL_MAX) {
|
||||
*frequency = 2405 + 5 * (channel - IEEE802154_2_4_GHZ_CHANNEL_MIN);
|
||||
/* See IEEE 802.15.4-2020, section 10.1.3.3. */
|
||||
if (channel >= 11 && channel <= 26) {
|
||||
*frequency = 2405 + 5 * (channel - 11);
|
||||
*fractFreq = 0;
|
||||
return 0;
|
||||
} else {
|
||||
/* TODO: Support sub-GHz for CC13xx rather than having separate drivers */
|
||||
*frequency = 0;
|
||||
*fractFreq = 0;
|
||||
return -EINVAL;
|
||||
return channel < 11 ? -ENOTSUP : -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee802154_cc13xx_cc26xx_set_channel(const struct device *dev,
|
||||
|
|
@ -508,6 +508,18 @@ ieee802154_cc13xx_cc26xx_configure(const struct device *dev,
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
static int ieee802154_cc13xx_cc26xx_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
static void ieee802154_cc13xx_cc26xx_data_init(const struct device *dev)
|
||||
{
|
||||
|
|
@ -570,6 +582,7 @@ static struct ieee802154_radio_api ieee802154_cc13xx_cc26xx_radio_api = {
|
|||
.start = ieee802154_cc13xx_cc26xx_start,
|
||||
.stop = ieee802154_cc13xx_cc26xx_stop_if,
|
||||
.configure = ieee802154_cc13xx_cc26xx_configure,
|
||||
.attr_get = ieee802154_cc13xx_cc26xx_attr_get,
|
||||
};
|
||||
|
||||
/** RF patches to use (note: RF core keeps a pointer to this, so no stack). */
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
/* For O-QPSK the physical and MAC timing symbol rates are the same, see section 12.3.3. */
|
||||
#define IEEE802154_2450MHZ_OQPSK_SYMBOLS_PER_SECOND \
|
||||
IEEE802154_PHY_SYMBOLS_PER_SECOND(IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US)
|
||||
IEEE802154_PHY_SYMBOLS_PER_SECOND(IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS)
|
||||
|
||||
/* PHY PIB attribute phyCcaMode - CCA Mode 3: Carrier sense with energy above threshold, see
|
||||
* section 11.3, table 11-2 and section 10.2.8
|
||||
|
|
|
|||
|
|
@ -263,25 +263,26 @@ static inline int ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(
|
|||
__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) {
|
||||
/* See IEEE 802.15.4-2020, section 10.1.3.3. */
|
||||
if (channel == 0) {
|
||||
*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) {
|
||||
} else if (channel <= 10) {
|
||||
*frequency = 906 + 2 * (channel - 1);
|
||||
*fractFreq = 0;
|
||||
} else {
|
||||
*frequency = 0;
|
||||
*fractFreq = 0;
|
||||
return -EINVAL;
|
||||
return channel <= 26 ? -ENOTSUP : -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.
|
||||
/* TODO: This incorrectly mixes up legacy BPSK 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.
|
||||
|
|
@ -299,16 +300,15 @@ static inline int ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(
|
|||
* 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.
|
||||
*
|
||||
* We resolve this bug right now by basing all timing on SUN FSK
|
||||
* parameters while maintaining the channel/channel page assignment of a
|
||||
* BPSK PHY.
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -362,7 +362,7 @@ 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;
|
||||
return IEEE802154_HW_FCS;
|
||||
}
|
||||
|
||||
static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev)
|
||||
|
|
@ -449,13 +449,9 @@ static int ieee802154_cc13xx_cc26xx_subg_set_channel(
|
|||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE;
|
||||
|
|
@ -590,6 +586,20 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 0, 10);
|
||||
|
||||
static int ieee802154_cc13xx_cc26xx_subg_attr_get(const struct device *dev,
|
||||
enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
static void ieee802154_cc13xx_cc26xx_subg_rx_done(
|
||||
struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
|
||||
{
|
||||
|
|
@ -711,15 +721,6 @@ ieee802154_cc13xx_cc26xx_subg_configure(const struct device *dev,
|
|||
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)
|
||||
{
|
||||
|
|
@ -791,8 +792,7 @@ static struct ieee802154_radio_api
|
|||
.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,
|
||||
.attr_get = ieee802154_cc13xx_cc26xx_subg_attr_get,
|
||||
};
|
||||
|
||||
static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev)
|
||||
|
|
@ -896,7 +896,7 @@ static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_d
|
|||
/* 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),
|
||||
IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS),
|
||||
},
|
||||
|
||||
.cmd_prop_tx_adv = {
|
||||
|
|
@ -916,7 +916,7 @@ static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_d
|
|||
},
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_L2_IEEE802154_SUB_GHZ)
|
||||
#if defined(CONFIG_NET_L2_IEEE802154)
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@ out:
|
|||
static enum ieee802154_hw_caps cc2520_get_capabilities(const struct device *dev)
|
||||
{
|
||||
/* TODO: Add support for IEEE802154_HW_PROMISC */
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER |
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_RX_TX_ACK;
|
||||
}
|
||||
|
||||
|
|
@ -686,10 +686,14 @@ static int cc2520_set_channel(const struct device *dev, uint16_t channel)
|
|||
{
|
||||
LOG_DBG("%u", channel);
|
||||
|
||||
if (channel < 11 || channel > 26) {
|
||||
if (channel > 26) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (channel < 11) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* See chapter 16 */
|
||||
channel = 11 + (channel - 11) * 5U;
|
||||
|
||||
|
|
@ -878,6 +882,19 @@ static int cc2520_stop(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
static int cc2520_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
/******************
|
||||
* Initialization *
|
||||
*****************/
|
||||
|
|
@ -1048,6 +1065,7 @@ static struct ieee802154_radio_api cc2520_radio_api = {
|
|||
.start = cc2520_start,
|
||||
.stop = cc2520_stop,
|
||||
.tx = cc2520_tx,
|
||||
.attr_get = cc2520_attr_get,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_IEEE802154_RAW_MODE)
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ LOG_MODULE_REGISTER(dw1000, LOG_LEVEL_INF);
|
|||
#define DW1000_RX_ANT_DLY 16450
|
||||
|
||||
/* SHR Symbol Duration in ns */
|
||||
#define UWB_PHY_TPSYM_PRF64 1017.63
|
||||
#define UWB_PHY_TPSYM_PRF16 993.59
|
||||
#define UWB_PHY_TPSYM_PRF64 IEEE802154_PHY_HRP_UWB_PRF64_TPSYM_SYMBOL_PERIOD_NS
|
||||
#define UWB_PHY_TPSYM_PRF16 IEEE802154_PHY_HRP_UWB_PRF16_TPSYM_SYMBOL_PERIOD_NS
|
||||
|
||||
#define UWB_PHY_NUMOF_SYM_SHR_SFD 8
|
||||
|
||||
|
|
@ -624,9 +624,8 @@ static void dwt_gpio_callback(const struct device *dev,
|
|||
|
||||
static enum ieee802154_hw_caps dwt_get_capabilities(const struct device *dev)
|
||||
{
|
||||
/* TODO: Add channel page attribute with channel page four. */
|
||||
/* TODO: Implement HW-supported AUTOACK + frame pending bit handling. */
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER |
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_TXTIME;
|
||||
}
|
||||
|
||||
|
|
@ -684,6 +683,14 @@ static int dwt_set_channel(const struct device *dev, uint16_t channel)
|
|||
struct dwt_context *ctx = dev->data;
|
||||
struct dwt_phy_config *rf_cfg = &ctx->rf_cfg;
|
||||
|
||||
if (channel > 15) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (channel == 0 || channel == 6 || channel > 7) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
rf_cfg->channel = channel;
|
||||
LOG_INF("Set channel %u", channel);
|
||||
|
||||
|
|
@ -940,6 +947,46 @@ static int dwt_configure(const struct device *dev,
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
static const struct {
|
||||
const struct ieee802154_phy_channel_range phy_channel_range[2];
|
||||
const struct ieee802154_phy_supported_channels phy_supported_channels;
|
||||
} drv_attr = {
|
||||
.phy_channel_range = {
|
||||
{ .from_channel = 1, .to_channel = 5 },
|
||||
{ .from_channel = 7, .to_channel = 7 },
|
||||
},
|
||||
.phy_supported_channels = {
|
||||
.ranges = drv_attr.phy_channel_range,
|
||||
.num_ranges = 2U,
|
||||
},
|
||||
};
|
||||
|
||||
static int dwt_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
if (ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_FOUR_HRP_UWB,
|
||||
&drv_attr.phy_supported_channels, value) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (attr) {
|
||||
case IEEE802154_ATTR_PHY_HRP_UWB_SUPPORTED_PRFS: {
|
||||
struct dwt_context *ctx = dev->data;
|
||||
struct dwt_phy_config *rf_cfg = &ctx->rf_cfg;
|
||||
|
||||
value->phy_hrp_uwb_supported_nominal_prfs =
|
||||
rf_cfg->prf == DWT_PRF_64M ? IEEE802154_PHY_HRP_UWB_NOMINAL_64_M
|
||||
: IEEE802154_PHY_HRP_UWB_NOMINAL_16_M;
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note, the DW_RESET pin should not be driven high externally.
|
||||
*/
|
||||
|
|
@ -1633,6 +1680,7 @@ static struct ieee802154_radio_api dwt_radio_api = {
|
|||
.configure = dwt_configure,
|
||||
.ed_scan = dwt_ed,
|
||||
.tx = dwt_tx,
|
||||
.attr_get = dwt_attr_get,
|
||||
};
|
||||
|
||||
#define DWT_PSDU_LENGTH (127 - DWT_FCS_LENGTH)
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ static void kw41z_tmr3_disable(void)
|
|||
|
||||
static enum ieee802154_hw_caps kw41z_get_capabilities(const struct device *dev)
|
||||
{
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER |
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK;
|
||||
}
|
||||
|
||||
|
|
@ -385,7 +385,7 @@ static int kw41z_cca(const struct device *dev)
|
|||
static int kw41z_set_channel(const struct device *dev, uint16_t channel)
|
||||
{
|
||||
if (channel < 11 || channel > 26) {
|
||||
return -EINVAL;
|
||||
return channel < 11 ? -ENOTSUP : -EINVAL;
|
||||
}
|
||||
|
||||
ZLL->CHANNEL_NUM0 = channel;
|
||||
|
|
@ -1078,6 +1078,19 @@ static int kw41z_configure(const struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
static int kw41z_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
static struct ieee802154_radio_api kw41z_radio_api = {
|
||||
.iface_api.init = kw41z_iface_init,
|
||||
|
||||
|
|
@ -1090,6 +1103,7 @@ static struct ieee802154_radio_api kw41z_radio_api = {
|
|||
.stop = kw41z_stop,
|
||||
.tx = kw41z_tx,
|
||||
.configure = kw41z_configure,
|
||||
.attr_get = kw41z_attr_get,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_L2_IEEE802154)
|
||||
|
|
|
|||
|
|
@ -854,7 +854,7 @@ static int mcr20a_set_cca_mode(const struct device *dev, uint8_t mode)
|
|||
|
||||
static enum ieee802154_hw_caps mcr20a_get_capabilities(const struct device *dev)
|
||||
{
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK |
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_TX_RX_ACK |
|
||||
IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_FILTER;
|
||||
}
|
||||
|
||||
|
|
@ -916,7 +916,7 @@ static int mcr20a_set_channel(const struct device *dev, uint16_t channel)
|
|||
|
||||
if (channel < 11 || channel > 26) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
return channel < 11 ? -ENOTSUP : -EINVAL;
|
||||
}
|
||||
|
||||
k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER);
|
||||
|
|
@ -1265,6 +1265,19 @@ error:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
static int mcr20a_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
static int mcr20a_update_overwrites(const struct device *dev)
|
||||
{
|
||||
if (!write_reg_overwrite_ver(dev, overwrites_direct[0].data)) {
|
||||
|
|
@ -1447,6 +1460,7 @@ static struct ieee802154_radio_api mcr20a_radio_api = {
|
|||
.start = mcr20a_start,
|
||||
.stop = mcr20a_stop,
|
||||
.tx = mcr20a_tx,
|
||||
.attr_get = mcr20a_attr_get,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_IEEE802154_RAW_MODE)
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@ static void nrf5_get_capabilities_at_boot(void)
|
|||
IEEE802154_HW_PROMISC |
|
||||
IEEE802154_HW_FILTER |
|
||||
((caps & NRF_802154_CAPABILITY_CSMA) ? IEEE802154_HW_CSMA : 0UL) |
|
||||
IEEE802154_HW_2_4_GHZ |
|
||||
IEEE802154_HW_TX_RX_ACK |
|
||||
IEEE802154_HW_RX_TX_ACK |
|
||||
IEEE802154_HW_ENERGY_SCAN |
|
||||
|
|
@ -270,7 +269,7 @@ static int nrf5_set_channel(const struct device *dev, uint16_t channel)
|
|||
LOG_DBG("%u", channel);
|
||||
|
||||
if (channel < 11 || channel > 26) {
|
||||
return -EINVAL;
|
||||
return channel < 11 ? -ENOTSUP : -EINVAL;
|
||||
}
|
||||
|
||||
nrf_802154_channel_set(channel);
|
||||
|
|
@ -954,12 +953,20 @@ static int nrf5_configure(const struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
static int nrf5_attr_get(const struct device *dev,
|
||||
enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(value);
|
||||
|
||||
if (ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch ((uint32_t)attr) {
|
||||
#if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA)
|
||||
|
|
|
|||
|
|
@ -141,11 +141,11 @@ static void rf2xx_set_rssi_base(const struct device *dev, uint16_t channel)
|
|||
struct rf2xx_context *ctx = dev->data;
|
||||
int8_t base;
|
||||
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
|
||||
if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) {
|
||||
base = channel == 0
|
||||
? RF2XX_RSSI_BPSK_20
|
||||
: RF2XX_RSSI_BPSK_40;
|
||||
} else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) {
|
||||
} else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) {
|
||||
base = channel == 0
|
||||
? RF2XX_RSSI_OQPSK_SIN_RC_100
|
||||
: RF2XX_RSSI_OQPSK_SIN_250;
|
||||
|
|
@ -364,8 +364,6 @@ static inline uint8_t *get_mac(const struct device *dev)
|
|||
|
||||
static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
|
||||
LOG_DBG("HW Caps");
|
||||
|
||||
return IEEE802154_HW_FCS |
|
||||
|
|
@ -374,10 +372,7 @@ static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev)
|
|||
IEEE802154_HW_CSMA |
|
||||
IEEE802154_HW_RETRANSMISSION |
|
||||
IEEE802154_HW_TX_RX_ACK |
|
||||
IEEE802154_HW_RX_TX_ACK |
|
||||
(ctx->trx_model == RF2XX_TRX_MODEL_212
|
||||
? IEEE802154_HW_SUB_GHZ
|
||||
: IEEE802154_HW_2_4_GHZ);
|
||||
IEEE802154_HW_RX_TX_ACK;
|
||||
}
|
||||
|
||||
static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channel)
|
||||
|
|
@ -386,11 +381,11 @@ static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channe
|
|||
uint8_t reg;
|
||||
uint8_t cc_mask;
|
||||
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
|
||||
if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) {
|
||||
cc_mask = channel == 0
|
||||
? RF2XX_CC_BPSK_20
|
||||
: RF2XX_CC_BPSK_40;
|
||||
} else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) {
|
||||
} else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) {
|
||||
cc_mask = channel == 0
|
||||
? RF2XX_CC_OQPSK_SIN_RC_100
|
||||
: RF2XX_CC_OQPSK_SIN_250;
|
||||
|
|
@ -404,13 +399,14 @@ static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channe
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rf2xx_configure_trx_path(const struct device *dev)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
uint8_t reg;
|
||||
uint8_t gc_tx_offset;
|
||||
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
|
||||
if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) {
|
||||
gc_tx_offset = 0x03;
|
||||
} else {
|
||||
gc_tx_offset = 0x02;
|
||||
|
|
@ -440,24 +436,26 @@ static int rf2xx_set_channel(const struct device *dev, uint16_t channel)
|
|||
LOG_DBG("Set Channel %d", channel);
|
||||
|
||||
if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
|
||||
if ((ctx->cc_page == RF2XX_TRX_CC_PAGE_0
|
||||
|| ctx->cc_page == RF2XX_TRX_CC_PAGE_2)
|
||||
if ((ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915
|
||||
|| ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915)
|
||||
&& channel > 10) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
return channel > 26 ? -EINVAL : -ENOTSUP;
|
||||
}
|
||||
if (ctx->cc_page == RF2XX_TRX_CC_PAGE_5 && channel > 3) {
|
||||
if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780 &&
|
||||
channel > 3) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
return channel > 7 ? -EINVAL : -ENOTSUP;
|
||||
}
|
||||
|
||||
rf2xx_configure_sub_channel(dev, channel);
|
||||
rf2xx_configure_trx_path(dev);
|
||||
rf2xx_set_rssi_base(dev, channel);
|
||||
} else {
|
||||
/* 2.4G O-QPSK, channel page zero */
|
||||
if (channel < 11 || channel > 26) {
|
||||
LOG_ERR("Unsupported channel %u", channel);
|
||||
return -EINVAL;
|
||||
return channel < 11 ? -ENOTSUP : -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -830,11 +828,23 @@ int rf2xx_configure(const struct device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint16_t rf2xx_get_subgiga_channel_count(const struct device *dev)
|
||||
static int rf2xx_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
struct rf2xx_context *ctx = dev->data;
|
||||
|
||||
return ctx->cc_page == RF2XX_TRX_CC_PAGE_5 ? 4 : 11;
|
||||
switch (attr) {
|
||||
case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES:
|
||||
value->phy_supported_channel_pages = ctx->cc_page;
|
||||
return 0;
|
||||
|
||||
case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES:
|
||||
value->phy_supported_channels = &ctx->cc_channels;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
static int power_on_and_setup(const struct device *dev)
|
||||
|
|
@ -1049,6 +1059,25 @@ static void rf2xx_iface_init(struct net_if *iface)
|
|||
|
||||
ctx->iface = iface;
|
||||
|
||||
if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
|
||||
if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915 ||
|
||||
ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) {
|
||||
ctx->cc_range.from_channel = 0U;
|
||||
ctx->cc_range.to_channel = 10U;
|
||||
} else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780) {
|
||||
ctx->cc_range.from_channel = 0U;
|
||||
ctx->cc_range.to_channel = 3U;
|
||||
} else {
|
||||
__ASSERT(false, "Unsupported channel page %u.", ctx->cc_page);
|
||||
}
|
||||
} else {
|
||||
__ASSERT(ctx->cc_page ==
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
"Unsupported channel page %u.", ctx->cc_page);
|
||||
ctx->cc_range.from_channel = 11U;
|
||||
ctx->cc_range.to_channel = 26U;
|
||||
}
|
||||
|
||||
ieee802154_init(iface);
|
||||
}
|
||||
|
||||
|
|
@ -1064,7 +1093,7 @@ static struct ieee802154_radio_api rf2xx_radio_api = {
|
|||
.start = rf2xx_start,
|
||||
.stop = rf2xx_stop,
|
||||
.configure = rf2xx_configure,
|
||||
.get_subg_channel_count = rf2xx_get_subgiga_channel_count,
|
||||
.attr_get = rf2xx_attr_get,
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_IEEE802154_RAW_MODE)
|
||||
|
|
@ -1113,7 +1142,11 @@ static struct ieee802154_radio_api rf2xx_radio_api = {
|
|||
#define IEEE802154_RF2XX_DEVICE_DATA(n) \
|
||||
static struct rf2xx_context rf2xx_ctx_data_##n = { \
|
||||
.mac_addr = { DRV_INST_LOCAL_MAC_ADDRESS(n) }, \
|
||||
.cc_page = DT_INST_ENUM_IDX_OR(n, channel_page, 0), \
|
||||
.cc_page = BIT(DT_INST_ENUM_IDX_OR(n, channel_page, 0)),\
|
||||
.cc_channels = { \
|
||||
.ranges = &rf2xx_ctx_data_##n.cc_range, \
|
||||
.num_ranges = 1U, \
|
||||
} \
|
||||
}
|
||||
|
||||
#define IEEE802154_RF2XX_RAW_DEVICE_INIT(n) \
|
||||
|
|
|
|||
|
|
@ -74,12 +74,6 @@ enum rf2xx_trx_model_t {
|
|||
RF2XX_TRX_MODEL_233 = 0x0B,
|
||||
};
|
||||
|
||||
enum rf2xx_trx_channel_page_t {
|
||||
RF2XX_TRX_CC_PAGE_0 = 0x00,
|
||||
RF2XX_TRX_CC_PAGE_2 = 0x02,
|
||||
RF2XX_TRX_CC_PAGE_5 = 0x05,
|
||||
};
|
||||
|
||||
struct rf2xx_config {
|
||||
struct gpio_dt_spec irq_gpio;
|
||||
struct gpio_dt_spec reset_gpio;
|
||||
|
|
@ -112,7 +106,12 @@ struct rf2xx_context {
|
|||
struct k_sem trx_tx_sync;
|
||||
|
||||
enum rf2xx_trx_model_t trx_model;
|
||||
enum rf2xx_trx_channel_page_t cc_page;
|
||||
|
||||
/* PHY specific driver attributes */
|
||||
enum ieee802154_phy_channel_page cc_page;
|
||||
struct ieee802154_phy_channel_range cc_range;
|
||||
struct ieee802154_phy_supported_channels cc_channels;
|
||||
|
||||
enum rf2xx_trx_state_trac_t trx_trac;
|
||||
|
||||
enum ieee802154_tx_mode tx_mode;
|
||||
|
|
|
|||
|
|
@ -181,9 +181,7 @@ done:
|
|||
|
||||
static enum ieee802154_hw_caps upipe_get_capabilities(const struct device *dev)
|
||||
{
|
||||
return IEEE802154_HW_FCS |
|
||||
IEEE802154_HW_2_4_GHZ |
|
||||
IEEE802154_HW_FILTER;
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_FILTER;
|
||||
}
|
||||
|
||||
static int upipe_cca(const struct device *dev)
|
||||
|
|
@ -329,6 +327,20 @@ static int upipe_stop(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
/* API implementation: attr_get */
|
||||
static int upipe_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
static int upipe_init(const struct device *dev)
|
||||
{
|
||||
struct upipe_context *upipe = dev->data;
|
||||
|
|
@ -391,6 +403,7 @@ static struct ieee802154_radio_api upipe_radio_api = {
|
|||
.tx = upipe_tx,
|
||||
.start = upipe_start,
|
||||
.stop = upipe_stop,
|
||||
.attr_get = upipe_attr_get,
|
||||
};
|
||||
|
||||
NET_DEVICE_DT_INST_DEFINE(0, upipe_init, NULL, &upipe_context_data, NULL,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
struct cc1200_rf_registers_set {
|
||||
uint32_t chan_center_freq0;
|
||||
uint16_t channel_limit;
|
||||
/* to fit in uint16_t, spacing is a multiple of 100 Hz,
|
||||
* 12.5KHz for instance will be 125.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -52,14 +52,6 @@ extern "C" {
|
|||
#define IEEE802154_SHORT_ADDRESS_NOT_ASSOCIATED IEEE802154_BROADCAST_ADDRESS
|
||||
#define IEEE802154_PAN_ID_NOT_ASSOCIATED IEEE802154_BROADCAST_PAN_ID
|
||||
|
||||
/* MAC PIB attribute aUnitBackoffPeriod, see section 8.4.2, table 8-93, in symbol periods, valid for
|
||||
* all PHYs except SUN PHY in the 920 MHz band.
|
||||
*/
|
||||
#define IEEE802154_A_UNIT_BACKOFF_PERIOD(turnaround_time) \
|
||||
(turnaround_time + IEEE802154_PHY_A_CCA_TIME)
|
||||
#define IEEE802154_A_UNIT_BACKOFF_PERIOD_US(turnaround_time, symbol_period) \
|
||||
(IEEE802154_A_UNIT_BACKOFF_PERIOD(turnaround_time) * symbol_period)
|
||||
|
||||
struct ieee802154_security_ctx {
|
||||
uint32_t frame_counter;
|
||||
struct cipher_ctx enc;
|
||||
|
|
|
|||
|
|
@ -212,10 +212,7 @@ enum net_event_ieee802154_cmd {
|
|||
#define IEEE802154_IS_CHAN_UNSCANNED(_channel_set, _chan) \
|
||||
(!IEEE802154_IS_CHAN_SCANNED(_channel_set, _chan))
|
||||
|
||||
/* Useful define to request all 16 channels of channel page zero
|
||||
* in the 2450 MHz band to be scanned, from 11 to 26 included.
|
||||
*/
|
||||
#define IEEE802154_ALL_CHANNELS (0x03FFFC00)
|
||||
#define IEEE802154_ALL_CHANNELS UINT32_MAX
|
||||
|
||||
/**
|
||||
* @brief Scanning parameters
|
||||
|
|
|
|||
|
|
@ -31,72 +31,311 @@ extern "C" {
|
|||
* @{
|
||||
*/
|
||||
|
||||
/* See section 6.1: "Some of the timing parameters in definition of the MAC are in units of PHY
|
||||
* symbols. For PHYs that have multiple symbol periods, the duration to be used for the MAC
|
||||
* parameters is defined in that PHY clause."
|
||||
/**
|
||||
* MAC functional description (section 6)
|
||||
*/
|
||||
#define IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US 20U /* see section 19.1, table 19-1 */
|
||||
#define IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US 16U /* see section 12.3.3 */
|
||||
|
||||
/* TODO: Get PHY-specific symbol period from radio API. Requires an attribute getter, see
|
||||
* https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582.
|
||||
* For now we assume PHYs that current drivers actually implement.
|
||||
/**
|
||||
* The symbol period (and therefore symbol rate) is defined in section 6.1: "Some
|
||||
* of the timing parameters in definition of the MAC are in units of PHY symbols.
|
||||
* For PHYs that have multiple symbol periods, the duration to be used for the
|
||||
* MAC parameters is defined in that PHY clause."
|
||||
*
|
||||
* This is not necessarily the true physical symbol period, so take care to use
|
||||
* this macro only when either the symbol period used for MAC timing is the same
|
||||
* as the physical symbol period or if you actually mean the MAC timing symbol
|
||||
* period.
|
||||
*
|
||||
* PHY specific symbol periods are defined in PHY specific sections below.
|
||||
*/
|
||||
#define IEEE802154_PHY_SYMBOL_PERIOD_US(is_subg_phy) \
|
||||
((is_subg_phy) ? IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US \
|
||||
: IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US)
|
||||
#define IEEE802154_PHY_SYMBOLS_PER_SECOND(symbol_period_ns) (NSEC_PER_SEC / symbol_period_ns)
|
||||
|
||||
/* The inverse of the symbol period as defined in section 6.1. This is not necessarily the true
|
||||
* physical symbol period, so take care to use this macro only when either the symbol period used
|
||||
* for MAC timing is the same as the physical symbol period or if you actually mean the MAC timing
|
||||
* symbol period.
|
||||
/**
|
||||
* MAC services (section 8)
|
||||
*/
|
||||
#define IEEE802154_PHY_SYMBOLS_PER_SECOND(symbol_period) (USEC_PER_SEC / symbol_period)
|
||||
|
||||
/* in bytes, see section 19.2.4 */
|
||||
#define IEEE802154_PHY_SUN_FSK_PHR_LEN 2
|
||||
/**
|
||||
* The number of PHY symbols forming a superframe slot when the superframe order
|
||||
* is equal to zero, see sections 8.4.2, table 8-93, aBaseSlotDuration and
|
||||
* section 6.2.1.
|
||||
*/
|
||||
#define IEEE802154_MAC_A_BASE_SLOT_DURATION 60U
|
||||
|
||||
/* Default PHY PIB attribute aTurnaroundTime, in PHY symbols, see section 11.3, table 11-1. */
|
||||
/**
|
||||
* The number of slots contained in any superframe, see section 8.4.2,
|
||||
* table 8-93, aNumSuperframeSlots.
|
||||
*/
|
||||
#define IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS 16U
|
||||
|
||||
/**
|
||||
* The number of PHY symbols forming a superframe when the superframe order is
|
||||
* equal to zero, see section 8.4.2, table 8-93, aBaseSuperframeDuration.
|
||||
*/
|
||||
#define IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION \
|
||||
(IEEE802154_MAC_A_BASE_SLOT_DURATION * IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS)
|
||||
|
||||
/**
|
||||
* MAC PIB attribute aUnitBackoffPeriod, see section 8.4.2, table 8-93, in symbol
|
||||
* periods, valid for all PHYs except SUN PHY in the 920 MHz band.
|
||||
*/
|
||||
#define IEEE802154_MAC_A_UNIT_BACKOFF_PERIOD(turnaround_time) \
|
||||
(turnaround_time + IEEE802154_PHY_A_CCA_TIME)
|
||||
|
||||
/**
|
||||
* Default macResponseWaitTime in multiples of aBaseSuperframeDuration as
|
||||
* defined in section 8.4.3.1, table 8-94.
|
||||
*/
|
||||
#define IEEE802154_MAC_RESPONSE_WAIT_TIME_DEFAULT 32U
|
||||
|
||||
/**
|
||||
* General PHY requirements (section 10)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief PHY channel pages, see section 10.1.3
|
||||
*
|
||||
* @details A device driver must support the mandatory channel pages, frequency
|
||||
* bands and channels of at least one IEEE 802.15.4 PHY.
|
||||
*
|
||||
* Channel page and number assignments have developed over several versions of
|
||||
* the standard and are not particularly well documented. Therefore some notes
|
||||
* about peculiarities of channel pages and channel numbering:
|
||||
* - The 2006 version of the standard had a read-only phyChannelsSupported PHY
|
||||
* PIB attribute that represented channel page/number combinations as a
|
||||
* bitmap. This attribute was removed in later versions of the standard as the
|
||||
* number of channels increased beyond what could be represented by a bit map.
|
||||
* That's the reason why we chose to represent supported channels as a
|
||||
* combination of channel pages and ranges instead.
|
||||
* - In the 2020 version of the standard, 13 channel pages are explicitly
|
||||
* defined, but up to 32 pages could in principle be supported. This was a
|
||||
* hard requirement in the 2006 standard. In later standards it is implicit
|
||||
* from field specifications, e.g. the MAC PIB attribute macChannelPage
|
||||
* (section 8.4.3.4, table 8-100) or channel page fields used in the SRM
|
||||
* protocol (see section 8.2.26.5).
|
||||
* - ASK PHY (channel page one) was deprecated in the 2015 version of the
|
||||
* standard. The 2020 version of the standard is a bit ambivalent whether
|
||||
* channel page one disappeared as well or should be interpreted as O-QPSK now
|
||||
* (see section 10.1.3.3). We resolve this ambivalence by deprecating channel
|
||||
* page one.
|
||||
* - For some PHYs the standard doesn't clearly specify a channel page, namely
|
||||
* the GFSK, RS-GFSK, CMB and TASK PHYs. These are all rather new and left out
|
||||
* in our list as long as no driver wants to implement them.
|
||||
*
|
||||
* @warning The bit numbers are not arbitrary but represent the channel
|
||||
* page numbers as defined by the standard. Therefore do not change the
|
||||
* bit numbering.
|
||||
*/
|
||||
enum ieee802154_phy_channel_page {
|
||||
/**
|
||||
* Channel page zero supports the 2.4G channels of the O-QPSK PHY and
|
||||
* all channels from the BPSK PHYs initially defined in the 2003
|
||||
* editions of the standard. For channel page zero, 16 channels are
|
||||
* available in the 2450 MHz band (channels 11-26, O-QPSK), 10 in the
|
||||
* 915 MHz band (channels 1-10, BPSK), and 1 in the 868 MHz band
|
||||
* (channel 0, BPSK).
|
||||
*
|
||||
* You can retrieve the channels supported by a specific driver on this
|
||||
* page via IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES attribute.
|
||||
*
|
||||
* see section 10.1.3.3
|
||||
*/
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915 = BIT(0),
|
||||
|
||||
/** Formerly ASK PHY - deprecated in IEEE 802.15.4-2015 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_ONE_DEPRECATED = BIT(1),
|
||||
|
||||
/** O-QPSK PHY - 868 MHz and 915 MHz bands, see section 10.1.3.3 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915 = BIT(2),
|
||||
|
||||
/** CSS PHY - 2450 MHz band, see section 10.1.3.4 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_THREE_CSS = BIT(3),
|
||||
|
||||
/** UWB PHY - SubG, low and high bands, see section 10.1.3.5 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_FOUR_HRP_UWB = BIT(4),
|
||||
|
||||
/** O-QPSK PHY - 780 MHz band, see section 10.1.3.2 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780 = BIT(5),
|
||||
|
||||
/** reserved - not currently assigned */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_SIX_RESERVED = BIT(6),
|
||||
|
||||
/** MSK PHY - 780 MHz and 2450 MHz bands, see sections 10.1.3.6, 10.1.3.7 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_SEVEN_MSK = BIT(7),
|
||||
|
||||
/** LRP UWB PHY, see sections 10.1.3.8 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_EIGHT_LRP_UWB = BIT(8),
|
||||
|
||||
/**
|
||||
* SUN FSK/OFDM/O-QPSK PHYs - predefined bands, operating modes and
|
||||
* channels, see sections 10.1.3.9
|
||||
*/
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED = BIT(9),
|
||||
|
||||
/**
|
||||
* SUN FSK/OFDM/O-QPSK PHYs - generic modulation and channel
|
||||
* description, see sections 10.1.3.9, 7.4.4.11
|
||||
*/
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_TEN_SUN_FSK_GENERIC = BIT(10),
|
||||
|
||||
/** O-QPSK PHY - 2380 MHz band, see section 10.1.3.10 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_ELEVEN_OQPSK_2380 = BIT(11),
|
||||
|
||||
/** LECIM DSSS/FSK PHYs, see section 10.1.3.11 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWELVE_LECIM = BIT(12),
|
||||
|
||||
/** RCC PHY, see section 10.1.3.12 */
|
||||
IEEE802154_ATTR_PHY_CHANNEL_PAGE_THIRTEEN_RCC = BIT(13),
|
||||
};
|
||||
|
||||
struct ieee802154_phy_channel_range {
|
||||
uint16_t from_channel;
|
||||
uint16_t to_channel;
|
||||
};
|
||||
|
||||
struct ieee802154_phy_supported_channels {
|
||||
/**
|
||||
* @brief Pointer to an array of channel range structures.
|
||||
*
|
||||
* @warning The pointer must be stable and valid throughout the life of
|
||||
* the interface.
|
||||
*/
|
||||
const struct ieee802154_phy_channel_range *const ranges;
|
||||
|
||||
/** @brief The number of currently available channel ranges. */
|
||||
const uint8_t num_ranges;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocate memory for the supported channels driver attribute with a
|
||||
* single channel range constant across all driver instances. This is what most
|
||||
* IEEE 802.15.4 drivers need.
|
||||
*
|
||||
* @details Example usage:
|
||||
*
|
||||
* @code{.c}
|
||||
* IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
* @endcode
|
||||
*
|
||||
* The attribute may then be referenced like this:
|
||||
*
|
||||
* @code{.c}
|
||||
* ... &drv_attr.phy_supported_channels ...
|
||||
* @endcode
|
||||
*
|
||||
* See @ref ieee802154_attr_get_channel_page_and_range() for a further shortcut
|
||||
* that can be combined with this macro.
|
||||
*
|
||||
* @param drv_attr name of the local static variable to be declared for the
|
||||
* local attributes structure
|
||||
* @param from the first channel to be supported
|
||||
* @param to the last channel to be supported
|
||||
*/
|
||||
#define IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, from, to) \
|
||||
static const struct { \
|
||||
const struct ieee802154_phy_channel_range phy_channel_range; \
|
||||
const struct ieee802154_phy_supported_channels phy_supported_channels; \
|
||||
} drv_attr = { \
|
||||
.phy_channel_range = {.from_channel = (from), .to_channel = (to)}, \
|
||||
.phy_supported_channels = \
|
||||
{ \
|
||||
.ranges = &drv_attr.phy_channel_range, \
|
||||
.num_ranges = 1U, \
|
||||
}, \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PHY services (section 11)
|
||||
*/
|
||||
|
||||
/* Default PHY PIB attribute aTurnaroundTime, in PHY symbols,
|
||||
* see section 11.3, table 11-1.
|
||||
*/
|
||||
#define IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT 12U
|
||||
|
||||
/* PHY PIB attribute aTurnaroundTime for SUN, RS-GFSK, TVWS, and LECIM FSK PHY,
|
||||
* in PHY symbols, see section 11.3, table 11-1.
|
||||
*/
|
||||
#define IEEE802154_PHY_A_TURNAROUND_TIME_1MS(symbol_period) \
|
||||
DIV_ROUND_UP(USEC_PER_MSEC, symbol_period)
|
||||
|
||||
/* TODO: Get PHY-specific turnaround time from radio API, see
|
||||
* https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582.
|
||||
* For now we assume PHYs that current drivers actually implement.
|
||||
*/
|
||||
#define IEEE802154_PHY_A_TURNAROUND_TIME(is_subg_phy) \
|
||||
((is_subg_phy) ? IEEE802154_PHY_A_TURNAROUND_TIME_1MS( \
|
||||
IEEE802154_PHY_SYMBOL_PERIOD_US(is_subg_phy)) \
|
||||
: IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT)
|
||||
#define IEEE802154_PHY_A_TURNAROUND_TIME_1MS(symbol_period_ns) \
|
||||
DIV_ROUND_UP(NSEC_PER_MSEC, symbol_period_ns)
|
||||
|
||||
/* PHY PIB attribute aCcaTime, in PHY symbols, all PHYs except for SUN O-QPSK,
|
||||
* see section 11.3, table 11-1.
|
||||
*/
|
||||
#define IEEE802154_PHY_A_CCA_TIME 8U
|
||||
|
||||
|
||||
/**
|
||||
* @brief IEEE 802.15.4 Channel assignments
|
||||
*
|
||||
* Channel numbering for 868 MHz, 915 MHz, and 2450 MHz bands (channel page zero).
|
||||
*
|
||||
* - Channel 0 is for 868.3 MHz.
|
||||
* - Channels 1-10 are for 906 to 924 MHz with 2 MHz channel spacing.
|
||||
* - Channels 11-26 are for 2405 to 2530 MHz with 5 MHz channel spacing.
|
||||
*
|
||||
* For more information, please refer to section 10.1.3.
|
||||
* Q-OPSK PHY (section 12)
|
||||
*/
|
||||
enum ieee802154_channel {
|
||||
IEEE802154_SUB_GHZ_CHANNEL_MIN = 0,
|
||||
IEEE802154_SUB_GHZ_CHANNEL_MAX = 10,
|
||||
IEEE802154_2_4_GHZ_CHANNEL_MIN = 11,
|
||||
IEEE802154_2_4_GHZ_CHANNEL_MAX = 26,
|
||||
|
||||
/* Symbol periods, section 12.3.3 */
|
||||
#define IEEE802154_PHY_OQPSK_868MHZ_SYMBOL_PERIOD_NS 40000LL
|
||||
#define IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS 16000LL
|
||||
|
||||
|
||||
/**
|
||||
* BPSK PHY (section 13)
|
||||
*/
|
||||
|
||||
/* Symbol periods, section 13.3.3 */
|
||||
#define IEEE802154_PHY_BPSK_868MHZ_SYMBOL_PERIOD_NS 50000LL
|
||||
#define IEEE802154_PHY_BPSK_915MHZ_SYMBOL_PERIOD_NS 25000LL
|
||||
|
||||
|
||||
/**
|
||||
* HRP UWB PHY (section 15)
|
||||
*/
|
||||
|
||||
/* For HRP UWB the symbol period is derived from the preamble symbol period
|
||||
* (T_psym), see section 11.3, table 11-1 and section 15.2.5, table 15-4
|
||||
* (confirmed in IEEE 802.15.4z, section 15.1). Choosing among those periods
|
||||
* cannot be done based on channel page and channel alone. The mean pulse
|
||||
* repetition frequency must also be known, see the 'UwbPrf' parameter of the
|
||||
* MCPS-DATA.request primitive (section 8.3.2, table 8-88) and the preamble
|
||||
* parameters for HRP-ERDEV length 91 codes (IEEE 802.15.4z, section 15.2.6.2,
|
||||
* table 15-7b).
|
||||
*/
|
||||
#define IEEE802154_PHY_HRP_UWB_PRF4_TPSYM_SYMBOL_PERIOD_NS 3974.36F
|
||||
#define IEEE802154_PHY_HRP_UWB_PRF16_TPSYM_SYMBOL_PERIOD_NS 993.59F
|
||||
#define IEEE802154_PHY_HRP_UWB_PRF64_TPSYM_SYMBOL_PERIOD_NS 1017.63F
|
||||
#define IEEE802154_PHY_HRP_UWB_ERDEV_TPSYM_SYMBOL_PERIOD_NS 729.17F
|
||||
|
||||
/** @brief represents the nominal pulse rate frequency of an HRP UWB PHY */
|
||||
enum ieee802154_phy_hrp_uwb_nominal_prf {
|
||||
/* standard modes, see section 8.3.2, table 8-88. */
|
||||
IEEE802154_PHY_HRP_UWB_PRF_OFF = 0,
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_4_M = BIT(0),
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_16_M = BIT(1),
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_64_M = BIT(2),
|
||||
/* enhanced ranging device (ERDEV) modes not specified in table 8-88,
|
||||
* see IEEE 802.15.4z, section 15.1, section 15.2.6.2, table 15-7b,
|
||||
* section 15.3.4.2 and section 15.3.4.3.
|
||||
*/
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_64_M_BPRF = BIT(3),
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_128_M_HPRF = BIT(4),
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_256_M_HPRF = BIT(5),
|
||||
};
|
||||
|
||||
#define IEEE802154_PHY_HRP_UWB_RDEV \
|
||||
(IEEE802154_PHY_HRP_UWB_NOMINAL_4_M | IEEE802154_PHY_HRP_UWB_NOMINAL_16_M | \
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_64_M)
|
||||
|
||||
#define IEEE802154_PHY_HRP_UWB_ERDEV \
|
||||
(IEEE802154_PHY_HRP_UWB_NOMINAL_64_M_BPRF | IEEE802154_PHY_HRP_UWB_NOMINAL_128_M_HPRF | \
|
||||
IEEE802154_PHY_HRP_UWB_NOMINAL_256_M_HPRF)
|
||||
|
||||
|
||||
/**
|
||||
* SUN FSK PHY (section 19)
|
||||
*/
|
||||
|
||||
/* symbol periods, section 19.1, table 19-1 */
|
||||
#define IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS 20000LL
|
||||
|
||||
/* in bytes, see section 19.2.4 */
|
||||
#define IEEE802154_PHY_SUN_FSK_PHR_LEN 2
|
||||
|
||||
/**
|
||||
* IEEE 802.15.4 driver capabilities
|
||||
*
|
||||
|
|
@ -112,28 +351,10 @@ enum ieee802154_hw_caps {
|
|||
*
|
||||
* The following capabilities describe features of the underlying radio
|
||||
* hardware (PHY/L1).
|
||||
*
|
||||
* Note: A device driver must support the mandatory channel pages,
|
||||
* frequency bands and channels of at least one IEEE 802.15.4 PHY.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 2.4Ghz radio supported
|
||||
*
|
||||
* TODO: Replace with channel page attribute.
|
||||
*/
|
||||
IEEE802154_HW_2_4_GHZ = BIT(0),
|
||||
|
||||
/**
|
||||
* Sub-GHz radio supported
|
||||
*
|
||||
* TODO: Replace with channel page attribute.
|
||||
*/
|
||||
IEEE802154_HW_SUB_GHZ = BIT(1),
|
||||
|
||||
/** Energy detection (ED) supported (optional) */
|
||||
IEEE802154_HW_ENERGY_SCAN = BIT(2),
|
||||
|
||||
IEEE802154_HW_ENERGY_SCAN = BIT(0),
|
||||
|
||||
/*
|
||||
* MAC offloading capabilities (optional)
|
||||
|
|
@ -151,37 +372,37 @@ enum ieee802154_hw_caps {
|
|||
*/
|
||||
|
||||
/** Frame checksum verification supported */
|
||||
IEEE802154_HW_FCS = BIT(3),
|
||||
IEEE802154_HW_FCS = BIT(1),
|
||||
|
||||
/** Filtering of PAN ID, extended and short address supported */
|
||||
IEEE802154_HW_FILTER = BIT(4),
|
||||
IEEE802154_HW_FILTER = BIT(2),
|
||||
|
||||
/** Promiscuous mode supported */
|
||||
IEEE802154_HW_PROMISC = BIT(5),
|
||||
IEEE802154_HW_PROMISC = BIT(3),
|
||||
|
||||
/** CSMA-CA procedure supported on TX */
|
||||
IEEE802154_HW_CSMA = BIT(6),
|
||||
IEEE802154_HW_CSMA = BIT(4),
|
||||
|
||||
/** Waits for ACK on TX if AR bit is set in TX pkt */
|
||||
IEEE802154_HW_TX_RX_ACK = BIT(7),
|
||||
IEEE802154_HW_TX_RX_ACK = BIT(5),
|
||||
|
||||
/** Supports retransmission on TX ACK timeout */
|
||||
IEEE802154_HW_RETRANSMISSION = BIT(8),
|
||||
IEEE802154_HW_RETRANSMISSION = BIT(6),
|
||||
|
||||
/** Sends ACK on RX if AR bit is set in RX pkt */
|
||||
IEEE802154_HW_RX_TX_ACK = BIT(9),
|
||||
IEEE802154_HW_RX_TX_ACK = BIT(7),
|
||||
|
||||
/** TX at specified time supported */
|
||||
IEEE802154_HW_TXTIME = BIT(10),
|
||||
IEEE802154_HW_TXTIME = BIT(8),
|
||||
|
||||
/** TX directly from sleep supported */
|
||||
IEEE802154_HW_SLEEP_TO_TX = BIT(11),
|
||||
IEEE802154_HW_SLEEP_TO_TX = BIT(9),
|
||||
|
||||
/** Timed RX window scheduling supported */
|
||||
IEEE802154_HW_RXTIME = BIT(12),
|
||||
IEEE802154_HW_RXTIME = BIT(10),
|
||||
|
||||
/** TX security supported (key management, encryption and authentication) */
|
||||
IEEE802154_HW_TX_SEC = BIT(13),
|
||||
IEEE802154_HW_TX_SEC = BIT(11),
|
||||
|
||||
/* Note: Update also IEEE802154_HW_CAPS_BITS_COMMON_COUNT when changing
|
||||
* the ieee802154_hw_caps type.
|
||||
|
|
@ -189,7 +410,7 @@ enum ieee802154_hw_caps {
|
|||
};
|
||||
|
||||
/** @brief Number of bits used by ieee802154_hw_caps type. */
|
||||
#define IEEE802154_HW_CAPS_BITS_COMMON_COUNT (14)
|
||||
#define IEEE802154_HW_CAPS_BITS_COMMON_COUNT (12)
|
||||
|
||||
/** @brief This and higher values are specific to the protocol- or driver-specific extensions. */
|
||||
#define IEEE802154_HW_CAPS_BITS_PRIV_START IEEE802154_HW_CAPS_BITS_COMMON_COUNT
|
||||
|
|
@ -502,10 +723,32 @@ struct ieee802154_config {
|
|||
* details.
|
||||
*/
|
||||
enum ieee802154_attr {
|
||||
/**
|
||||
* Retrieves a bit field with supported channel pages. This attribute
|
||||
* SHALL be implemented by all drivers.
|
||||
*/
|
||||
IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES,
|
||||
|
||||
/**
|
||||
* Retrieves a pointer to the array of supported channel ranges within
|
||||
* the currently configured channel page. This attribute SHALL be
|
||||
* implemented by all drivers.
|
||||
*/
|
||||
IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES,
|
||||
|
||||
/**
|
||||
* Retrieves a bit field with supported HRP UWB nominal pulse repetition
|
||||
* frequencies. This attribute SHALL be implemented by all devices that
|
||||
* support channel page four (HRP UWB).
|
||||
*/
|
||||
IEEE802154_ATTR_PHY_HRP_UWB_SUPPORTED_PRFS,
|
||||
|
||||
/** Number of attributes defined in ieee802154_attr. */
|
||||
IEEE802154_ATTR_COMMON_COUNT,
|
||||
|
||||
/** This and higher values are specific to the protocol- or driver-specific extensions. */
|
||||
/** This and higher values are specific to the protocol- or
|
||||
* driver-specific extensions.
|
||||
*/
|
||||
IEEE802154_ATTR_PRIV_START = IEEE802154_ATTR_COMMON_COUNT,
|
||||
};
|
||||
|
||||
|
|
@ -519,21 +762,121 @@ enum ieee802154_attr {
|
|||
* configuration data that originate from L2.
|
||||
*
|
||||
* @note To keep this union reasonably small, any attribute requiring a large
|
||||
* memory area, SHALL be provided pointing to memory allocated from the driver's
|
||||
* stack. Clients that need to persist the attribute value SHALL therefore copy
|
||||
* such memory before returning control to the driver.
|
||||
* memory area, SHALL be provided pointing to stable memory allocated by the
|
||||
* driver.
|
||||
*/
|
||||
struct ieee802154_attr_value {
|
||||
union {
|
||||
/* TODO: Please remove when first attribute is added. */
|
||||
uint8_t dummy;
|
||||
|
||||
/* TODO: Add driver specific PHY attributes (symbol rate,
|
||||
* aTurnaroundTime, aCcaTime, channels, channel pages, etc.)
|
||||
/**
|
||||
* @brief A bit field that represents the supported channel
|
||||
* pages, see ieee802154_phy_channel_page.
|
||||
*
|
||||
* @note To keep the API extensible as required by the standard,
|
||||
* we model supported pages as a bitmap to support drivers that
|
||||
* implement runtime switching between multiple channel pages.
|
||||
*
|
||||
* @note Currently none of the Zephyr drivers implements more
|
||||
* than one channel page at runtime, therefore only one bit will
|
||||
* be set and we consider the current channel page (see the PHY
|
||||
* PIB attribute phyCurrentPage, section 11.3, table 11-2) to be
|
||||
* read-only, fixed and "well known" via the supported channel
|
||||
* pages attribute.
|
||||
*
|
||||
* TODO: Implement configuration of phyCurrentPage once drivers
|
||||
* need to support channel page switching at runtime.
|
||||
*/
|
||||
uint32_t phy_supported_channel_pages;
|
||||
|
||||
/**
|
||||
* @brief Pointer to a structure representing channel ranges
|
||||
* currently available on the selected channel page.
|
||||
*
|
||||
* @warning The pointer must be stable and valid throughout the
|
||||
* life of the interface.
|
||||
*
|
||||
* @details The selected channel page corresponds to the
|
||||
* phyCurrentPage PHY PIB attribute, see the description of
|
||||
* phy_supported_channel_pages above. Currently it can be
|
||||
* retrieved via the IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES
|
||||
* attribute.
|
||||
*
|
||||
* Most drivers will expose a single channel page with a single,
|
||||
* often zero-based, fixed channel range.
|
||||
*
|
||||
* Some notable exceptions:
|
||||
* * The legacy channel page (zero) exposes ranges in different
|
||||
* bands and even PHYs that are usually not implemented by a
|
||||
* single driver.
|
||||
* * SUN and LECIM PHYs specify a large number of bands and
|
||||
* operating modes on a single page with overlapping channel
|
||||
* ranges each. Some of these ranges are not zero-based or
|
||||
* contain "holes". This explains why several ranges may be
|
||||
* necessary to represent all available channels.
|
||||
* * UWB PHYs often support partial channel ranges on the same
|
||||
* channel page depending on the supported bands.
|
||||
*
|
||||
* In these cases, drivers may expose custom configuration
|
||||
* attributes (Kconfig, devicetree, runtime, ...) that allow
|
||||
* switching between sub-ranges within the same channel page
|
||||
* (e.g. switching between SubG and 2.4G bands on channel page
|
||||
* zero or switching between multiple operating modes in the SUN
|
||||
* or LECIM PHYs.
|
||||
*/
|
||||
const struct ieee802154_phy_supported_channels *phy_supported_channels;
|
||||
|
||||
/**
|
||||
* @brief A bit field representing supported HRP UWB pulse
|
||||
* repetition frequencies (PRF), see enum
|
||||
* ieee802154_phy_hrp_uwb_nominal_prf.
|
||||
*
|
||||
* @note Currently none of the Zephyr HRP UWB drivers implements
|
||||
* more than one nominal PRF at runtime, therefore only one bit
|
||||
* will be set and we consider the current PRF (UwbPrf,
|
||||
* MCPS-DATA.request, section 8.3.2, table 8-88) to be
|
||||
* read-only, fixed and "well known" via the supported PRF
|
||||
* attribute.
|
||||
*
|
||||
* TODO: Allow the PRF to be configured for each TX call once
|
||||
* drivers need to support PRF switching at runtime.
|
||||
*/
|
||||
uint32_t phy_hrp_uwb_supported_nominal_prfs;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper function to handle channel page and rank to be called from
|
||||
* drivers' attr_get() implementation. This only applies to drivers with a
|
||||
* single channel page.
|
||||
*
|
||||
* @param attr The attribute to be retrieved.
|
||||
* @param phy_supported_channel_page The driver's unique channel page.
|
||||
* @param phy_supported_channels Pointer to the structure that contains the
|
||||
* driver's channel range or ranges.
|
||||
* @param value The pointer to the value struct provided by the user.
|
||||
*
|
||||
* @retval 0 if the attribute could be resolved
|
||||
* @retval -ENOENT if the attribute could not be resolved
|
||||
*/
|
||||
static inline int ieee802154_attr_get_channel_page_and_range(
|
||||
enum ieee802154_attr attr,
|
||||
const enum ieee802154_phy_channel_page phy_supported_channel_page,
|
||||
const struct ieee802154_phy_supported_channels *phy_supported_channels,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
switch (attr) {
|
||||
case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES:
|
||||
value->phy_supported_channel_pages = phy_supported_channel_page;
|
||||
return 0;
|
||||
|
||||
case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES:
|
||||
value->phy_supported_channels = phy_supported_channels;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IEEE 802.15.4 driver interface API.
|
||||
*
|
||||
|
|
@ -592,7 +935,8 @@ struct ieee802154_radio_api {
|
|||
*
|
||||
* @retval 0 channel was successfully set
|
||||
* @retval -EINVAL The given channel is not within the range of valid
|
||||
* channels of the driver's current channel page.
|
||||
* channels of the driver's current channel page, see the
|
||||
* IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES driver attribute.
|
||||
* @retval -ENOTSUP The given channel is within the range of valid
|
||||
* channels of the driver's current channel page but unsupported by the
|
||||
* current driver.
|
||||
|
|
@ -734,18 +1078,6 @@ struct ieee802154_radio_api {
|
|||
enum ieee802154_config_type type,
|
||||
const struct ieee802154_config *config);
|
||||
|
||||
/**
|
||||
* @brief Get the available amount of Sub-GHz channels.
|
||||
*
|
||||
* TODO: Replace with a combination of channel page and channel
|
||||
* attributes.
|
||||
*
|
||||
* @param dev pointer to radio device
|
||||
*
|
||||
* @return number of available channels in the sub-gigahertz band
|
||||
*/
|
||||
uint16_t (*get_subg_channel_count)(const struct device *dev);
|
||||
|
||||
/**
|
||||
* @brief Run an energy detection scan.
|
||||
*
|
||||
|
|
@ -819,7 +1151,8 @@ struct ieee802154_radio_api {
|
|||
* member.
|
||||
*
|
||||
* @retval -ENOENT The driver does not provide the requested attribute.
|
||||
* The value structure has does not been updated with attribute data.
|
||||
* The value structure has not been updated with attribute data. The
|
||||
* content of the value attribute is undefined.
|
||||
*/
|
||||
int (*attr_get)(const struct device *dev,
|
||||
enum ieee802154_attr attr,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ zephyr_library_compile_definitions_ifdef(
|
|||
zephyr_library_sources(
|
||||
ieee802154.c
|
||||
ieee802154_frame.c
|
||||
ieee802154_utils.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(
|
||||
|
|
|
|||
|
|
@ -14,22 +14,6 @@ config NET_L2_IEEE802154_MGMT
|
|||
select NET_MGMT
|
||||
select NET_MGMT_EVENT
|
||||
|
||||
# TODO: Selecting PHYs and frequency bands is abstracted by the concept
|
||||
# of channel pages in recent versions of the standard (see
|
||||
# IEEE 802.15.4-2020, 10.1.3).
|
||||
# This option will be replaced by configuration options on driver
|
||||
# instance level that allow selection of a channel page as well
|
||||
# as other PHY-specific configuration options (frequency bands,
|
||||
# operating modes, etc.).
|
||||
# New and existing drivers should not introduce additional
|
||||
# references to this option.
|
||||
config NET_L2_IEEE802154_SUB_GHZ
|
||||
bool
|
||||
help
|
||||
Enable support for Sub-GHz devices. This will add a tiny bit more
|
||||
logic in L2 code for channel management. This option is automatically
|
||||
selected when relevant device driver is enabled.
|
||||
|
||||
module = NET_L2_IEEE802154
|
||||
module-dep = NET_LOG
|
||||
module-str = Log level for IEEE 802.15.4
|
||||
|
|
|
|||
|
|
@ -94,10 +94,11 @@ NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_CANCEL_SCAN,
|
|||
static int ieee802154_scan(uint32_t mgmt_request, struct net_if *iface,
|
||||
void *data, size_t len)
|
||||
{
|
||||
const struct ieee802154_phy_supported_channels *supported_channels;
|
||||
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
||||
struct ieee802154_attr_value attr_value;
|
||||
struct ieee802154_req_params *scan;
|
||||
struct net_pkt *pkt = NULL;
|
||||
uint8_t channel;
|
||||
int ret;
|
||||
|
||||
if (len != sizeof(struct ieee802154_req_params) || !data) {
|
||||
|
|
@ -152,44 +153,52 @@ static int ieee802154_scan(uint32_t mgmt_request, struct net_if *iface,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* TODO: For now, we assume we are on 2.4Ghz
|
||||
* (device will have to export current channel page)
|
||||
*/
|
||||
for (channel = 11U; channel <= 26U; channel++) {
|
||||
if (IEEE802154_IS_CHAN_UNSCANNED(scan->channel_set, channel)) {
|
||||
continue;
|
||||
}
|
||||
if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES,
|
||||
&attr_value)) {
|
||||
NET_DBG("Could not determine supported channels");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
supported_channels = attr_value.phy_supported_channels;
|
||||
|
||||
scan->channel = channel;
|
||||
NET_DBG("Scanning channel %u", channel);
|
||||
ieee802154_radio_set_channel(iface, channel);
|
||||
for (int channel_range = 0; channel_range < supported_channels->num_ranges;
|
||||
channel_range++) {
|
||||
for (uint16_t channel = supported_channels->ranges[channel_range].from_channel;
|
||||
channel <= supported_channels->ranges[channel_range].to_channel; channel++) {
|
||||
if (IEEE802154_IS_CHAN_UNSCANNED(scan->channel_set, channel)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Active scan sends a beacon request */
|
||||
if (mgmt_request == NET_REQUEST_IEEE802154_ACTIVE_SCAN) {
|
||||
net_pkt_ref(pkt);
|
||||
net_pkt_frag_ref(pkt->buffer);
|
||||
scan->channel = channel;
|
||||
NET_DBG("Scanning channel %u", channel);
|
||||
ieee802154_radio_set_channel(iface, channel);
|
||||
|
||||
ret = ieee802154_radio_send(iface, pkt, pkt->buffer);
|
||||
if (ret) {
|
||||
NET_DBG("Could not send Beacon Request (%d)",
|
||||
ret);
|
||||
net_pkt_unref(pkt);
|
||||
/* Active scan sends a beacon request */
|
||||
if (mgmt_request == NET_REQUEST_IEEE802154_ACTIVE_SCAN) {
|
||||
net_pkt_ref(pkt);
|
||||
net_pkt_frag_ref(pkt->buffer);
|
||||
|
||||
ret = ieee802154_radio_send(iface, pkt, pkt->buffer);
|
||||
if (ret) {
|
||||
NET_DBG("Could not send Beacon Request (%d)", ret);
|
||||
net_pkt_unref(pkt);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Context aware sleep */
|
||||
k_sleep(K_MSEC(scan->duration));
|
||||
|
||||
k_sem_take(&ctx->scan_ctx_lock, K_FOREVER);
|
||||
|
||||
if (!ctx->scan_ctx) {
|
||||
NET_DBG("Scan request cancelled");
|
||||
ret = -ECANCELED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
k_sem_give(&ctx->scan_ctx_lock);
|
||||
}
|
||||
|
||||
/* Context aware sleep */
|
||||
k_sleep(K_MSEC(scan->duration));
|
||||
|
||||
k_sem_take(&ctx->scan_ctx_lock, K_FOREVER);
|
||||
|
||||
if (!ctx->scan_ctx) {
|
||||
NET_DBG("Scan request cancelled");
|
||||
ret = -ECANCELED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
k_sem_give(&ctx->scan_ctx_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -28,9 +28,15 @@ BUILD_ASSERT(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MIN_BE <=
|
|||
/* See section 6.2.5.1. */
|
||||
static inline int unslotted_csma_ca_channel_access(struct net_if *iface)
|
||||
{
|
||||
uint32_t turnaround_time = ieee802154_radio_get_a_turnaround_time(iface);
|
||||
uint32_t symbol_period = ieee802154_radio_get_symbol_period_us(iface);
|
||||
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
||||
uint8_t be = CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MIN_BE;
|
||||
uint32_t turnaround_time, unit_backoff_period_us;
|
||||
|
||||
turnaround_time = ieee802154_radio_get_a_turnaround_time(iface);
|
||||
unit_backoff_period_us = ieee802154_radio_get_multiple_of_symbol_period(
|
||||
iface, ctx->channel,
|
||||
IEEE802154_MAC_A_UNIT_BACKOFF_PERIOD(turnaround_time)) /
|
||||
NSEC_PER_USEC;
|
||||
|
||||
for (uint8_t nb = 0U; nb <= CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BO; nb++) {
|
||||
int ret;
|
||||
|
|
@ -42,8 +48,7 @@ static inline int unslotted_csma_ca_channel_access(struct net_if *iface)
|
|||
* radio API should expose a precise radio clock instead (which may
|
||||
* fall back to k_busy_wait() if the radio does not have a clock).
|
||||
*/
|
||||
k_busy_wait(bo_n * IEEE802154_A_UNIT_BACKOFF_PERIOD_US(turnaround_time,
|
||||
symbol_period));
|
||||
k_busy_wait(bo_n * unit_backoff_period_us);
|
||||
}
|
||||
|
||||
ret = ieee802154_radio_cca(iface);
|
||||
|
|
|
|||
72
subsys/net/l2/ieee802154/ieee802154_utils.c
Normal file
72
subsys/net/l2/ieee802154/ieee802154_utils.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Florian Grandel, Zephyr Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief IEEE 802.15.4 internal MAC and PHY Utils Implementation
|
||||
*
|
||||
* All references to the standard in this file cite IEEE 802.15.4-2020.
|
||||
*/
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(net_ieee802154, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
|
||||
|
||||
#include "ieee802154_utils.h"
|
||||
|
||||
/**
|
||||
* PHY utilities
|
||||
*/
|
||||
|
||||
bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_t channel)
|
||||
{
|
||||
struct ieee802154_attr_value value;
|
||||
|
||||
if (channel == IEEE802154_NO_CHANNEL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES,
|
||||
&value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int channel_range_index = 0;
|
||||
channel_range_index < value.phy_supported_channels->num_ranges;
|
||||
channel_range_index++) {
|
||||
const struct ieee802154_phy_channel_range *const channel_range =
|
||||
&value.phy_supported_channels->ranges[channel_range_index];
|
||||
|
||||
if (channel >= channel_range->from_channel &&
|
||||
channel <= channel_range->to_channel) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t ieee802154_radio_number_of_channels(struct net_if *iface)
|
||||
{
|
||||
struct ieee802154_attr_value value;
|
||||
uint16_t num_channels = 0;
|
||||
|
||||
if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES,
|
||||
&value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int channel_range_index = 0;
|
||||
channel_range_index < value.phy_supported_channels->num_ranges;
|
||||
channel_range_index++) {
|
||||
const struct ieee802154_phy_channel_range *const channel_range =
|
||||
&value.phy_supported_channels->ranges[channel_range_index];
|
||||
|
||||
__ASSERT_NO_MSG(channel_range->to_channel >= channel_range->from_channel);
|
||||
num_channels += channel_range->to_channel - channel_range->from_channel + 1U;
|
||||
}
|
||||
|
||||
return num_channels;
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ static inline int ieee802154_radio_attr_get(struct net_if *iface,
|
|||
/**
|
||||
* Sets the radio drivers extended address filter.
|
||||
*
|
||||
* @param iface Pointer to the IEEE 802.15.4 interface
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
* @param ieee_addr Pointer to an extended address in little endian byte order
|
||||
*/
|
||||
static inline void ieee802154_radio_filter_ieee_addr(struct net_if *iface, uint8_t *ieee_addr)
|
||||
|
|
@ -278,112 +278,204 @@ static inline void ieee802154_radio_remove_pan_id(struct net_if *iface, uint16_t
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the PHY's symbol period in microseconds.
|
||||
*
|
||||
* @details The PHY's symbol period depends on the interface's current PHY which
|
||||
* can be derived from the currently chosen channel page (phyCurrentPage).
|
||||
*
|
||||
* Examples:
|
||||
* * SUN FSK: see section 19.1, table 19-1
|
||||
* * O-QPSK: see section 12.3.3
|
||||
* * HRP UWB: derived from the preamble symbol period (T_psym), see section
|
||||
* 11.3, table 11-1 and section 15.2.5, table 15-4
|
||||
*
|
||||
* @note Currently the symbol period can only be calculated for SUN FSK and O-QPSK.
|
||||
*
|
||||
* @param iface The interface for which the symbol period should be calculated.
|
||||
*
|
||||
* @returns The symbol period for the given interface in microseconds.
|
||||
*/
|
||||
static inline uint32_t ieee802154_radio_get_symbol_period_us(struct net_if *iface)
|
||||
{
|
||||
/* TODO: Move symbol period calculation to radio driver. */
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_SUB_GHZ) &&
|
||||
ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_SUB_GHZ) {
|
||||
return IEEE802154_PHY_SYMBOL_PERIOD_US(true);
|
||||
/**
|
||||
* MAC utilities
|
||||
*
|
||||
* @note While MAC utilities may refer to PHY utilities, the inverse is not
|
||||
* true.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Retrieves the currently selected channel page from the driver (see
|
||||
* phyCurrentPage, section 11.3, table 11-2). This is PHY-related information
|
||||
* not configured by L2 but directly provided by the driver.
|
||||
*
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
*
|
||||
* @returns The currently active channel page.
|
||||
* @retval 0 if an error occurred
|
||||
*/
|
||||
static inline enum ieee802154_phy_channel_page
|
||||
ieee802154_radio_current_channel_page(struct net_if *iface)
|
||||
{
|
||||
struct ieee802154_attr_value value;
|
||||
|
||||
/* Currently we assume that drivers are statically configured to only
|
||||
* support a single channel page. Once drivers need to switch channels at
|
||||
* runtime this can be changed here w/o affecting clients.
|
||||
*/
|
||||
if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES, &value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return IEEE802154_PHY_SYMBOL_PERIOD_US(false);
|
||||
return value.phy_supported_channel_pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the PHY's turnaround time (see section 11.3, table 11-1,
|
||||
* aTurnaroundTime) in PHY symbols.
|
||||
* @brief Calculates a multiple of the PHY's symbol period in nanoseconds.
|
||||
*
|
||||
* @details The PHY's symbol period depends on the interface's current PHY
|
||||
* configuration which usually can be derived from the currently chosen channel
|
||||
* page and channel (phyCurrentPage and phyCurrentChannel, section 11.3, table
|
||||
* 11-2).
|
||||
*
|
||||
* To calculate the symbol period of HRP UWB PHYs, the nominal pulse repetition
|
||||
* frequency (PRF) is required. HRP UWB drivers will be expected to expose the
|
||||
* supported norminal PRF rates as a driver attribute. Existing drivers do not
|
||||
* allow for runtime switching of the PRF, so currently the PRF is considered to
|
||||
* be read-only and known.
|
||||
*
|
||||
* TODO: Add an UwbPrf argument once drivers need to support PRF switching at
|
||||
* runtime.
|
||||
*
|
||||
* @note We do not expose an API for a single symbol period to avoid having to
|
||||
* deal with floats for PHYs that don't require it while maintaining precision
|
||||
* in calculations where PHYs operate at symbol periods involving fractions of
|
||||
* nanoseconds.
|
||||
*
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
* @param channel The channel for which the symbol period is to be calculated.
|
||||
* @param multiplier The factor by which the symbol period is to be multiplied.
|
||||
*
|
||||
* @returns A multiple of the symbol period for the given interface with
|
||||
* nanosecond precision.
|
||||
* @retval 0 if an error occurred.
|
||||
*/
|
||||
static inline net_time_t ieee802154_radio_get_multiple_of_symbol_period(struct net_if *iface,
|
||||
uint16_t channel,
|
||||
uint16_t multiplier)
|
||||
{
|
||||
/* To keep things simple we only calculate symbol periods for channel
|
||||
* pages that are implemented by existing in-tree drivers. Add additional
|
||||
* channel pages as required.
|
||||
*/
|
||||
switch (ieee802154_radio_current_channel_page(iface)) {
|
||||
case IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915:
|
||||
return (channel >= 11
|
||||
? IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS
|
||||
: (channel > 0 ? IEEE802154_PHY_BPSK_915MHZ_SYMBOL_PERIOD_NS
|
||||
: IEEE802154_PHY_BPSK_868MHZ_SYMBOL_PERIOD_NS)) *
|
||||
multiplier;
|
||||
|
||||
case IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915:
|
||||
return (channel > 0 ? IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS
|
||||
: IEEE802154_PHY_OQPSK_868MHZ_SYMBOL_PERIOD_NS) *
|
||||
multiplier;
|
||||
|
||||
case IEEE802154_ATTR_PHY_CHANNEL_PAGE_FOUR_HRP_UWB: {
|
||||
struct ieee802154_attr_value value;
|
||||
|
||||
/* Currently we assume that drivers are statically configured to
|
||||
* only support a single PRF. Once drivers support switching PRF
|
||||
* at runtime an UWB PRF argument needs to be added to this
|
||||
* function which then must be validated against the set of
|
||||
* supported PRFs.
|
||||
*/
|
||||
if (ieee802154_radio_attr_get(iface, IEEE802154_ATTR_PHY_HRP_UWB_SUPPORTED_PRFS,
|
||||
&value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (value.phy_hrp_uwb_supported_nominal_prfs) {
|
||||
case IEEE802154_PHY_HRP_UWB_NOMINAL_4_M:
|
||||
return IEEE802154_PHY_HRP_UWB_PRF4_TPSYM_SYMBOL_PERIOD_NS * multiplier;
|
||||
|
||||
case IEEE802154_PHY_HRP_UWB_NOMINAL_16_M:
|
||||
return IEEE802154_PHY_HRP_UWB_PRF16_TPSYM_SYMBOL_PERIOD_NS * multiplier;
|
||||
|
||||
case IEEE802154_PHY_HRP_UWB_NOMINAL_64_M:
|
||||
return IEEE802154_PHY_HRP_UWB_PRF64_TPSYM_SYMBOL_PERIOD_NS * multiplier;
|
||||
|
||||
case IEEE802154_PHY_HRP_UWB_NOMINAL_64_M_BPRF:
|
||||
case IEEE802154_PHY_HRP_UWB_NOMINAL_128_M_HPRF:
|
||||
case IEEE802154_PHY_HRP_UWB_NOMINAL_256_M_HPRF:
|
||||
return IEEE802154_PHY_HRP_UWB_ERDEV_TPSYM_SYMBOL_PERIOD_NS * multiplier;
|
||||
|
||||
default:
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
case IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780:
|
||||
return IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS * multiplier;
|
||||
|
||||
case IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED:
|
||||
/* Current SUN FSK drivers only implement legacy IEEE 802.15.4g
|
||||
* 863 MHz (Europe) and 915 MHz (US ISM) bands, see IEEE
|
||||
* 802.15.4g, section 5.1, table 0. Once more bands are required
|
||||
* we need to request the currently active frequency band from
|
||||
* the driver.
|
||||
*/
|
||||
return IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS * multiplier;
|
||||
|
||||
default:
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the PHY's turnaround time for the current channel page (see
|
||||
* section 11.3, table 11-1, aTurnaroundTime) in PHY symbols.
|
||||
*
|
||||
* @details The PHY's turnaround time is used to calculate - among other
|
||||
* parameters - the TX-to-RX turnaround time (see section 10.2.2) and the
|
||||
* RX-to-TX turnaround time (see section 10.2.3).
|
||||
*
|
||||
* @note Currently the turnaround time can only be calculated for SUN FSK and O-QPSK.
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
*
|
||||
* @param iface The interface for which the turnaround time should be calculated.
|
||||
*
|
||||
* @returns The turnaround time for the given interface.
|
||||
* @returns The turnaround time for the given interface in symbols.
|
||||
* @retval 0 if an error occurred.
|
||||
*/
|
||||
static inline uint32_t ieee802154_radio_get_a_turnaround_time(struct net_if *iface)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_SUB_GHZ) &&
|
||||
ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_SUB_GHZ) {
|
||||
return IEEE802154_PHY_A_TURNAROUND_TIME(true);
|
||||
enum ieee802154_phy_channel_page channel_page =
|
||||
ieee802154_radio_current_channel_page(iface);
|
||||
|
||||
if (!channel_page) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return IEEE802154_PHY_A_TURNAROUND_TIME(false);
|
||||
/* Section 11.3, table 11-1, aTurnaroundTime: "For the SUN [...] PHYs,
|
||||
* the value is 1 ms expressed in symbol periods, rounded up to the next
|
||||
* integer number of symbol periods using the ceiling() function. [...]
|
||||
* The value is 12 [symbol periods] for all other PHYs.
|
||||
*/
|
||||
|
||||
if (channel_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED) {
|
||||
/* Current SUN FSK drivers only implement legacy IEEE 802.15.4g
|
||||
* 863 MHz (Europe) and 915 MHz (US ISM) bands, see IEEE
|
||||
* 802.15.4g, section 5.1, table 0. Once more bands are required
|
||||
* we need to request the currently active frequency band from
|
||||
* the driver.
|
||||
*/
|
||||
return IEEE802154_PHY_A_TURNAROUND_TIME_1MS(
|
||||
IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS);
|
||||
}
|
||||
|
||||
return IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT;
|
||||
}
|
||||
|
||||
static inline bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_t channel)
|
||||
{
|
||||
if (channel == IEEE802154_NO_CHANNEL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ
|
||||
const struct ieee802154_radio_api *radio =
|
||||
net_if_get_device(iface)->api;
|
||||
|
||||
if (!radio) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (radio->get_capabilities(net_if_get_device(iface)) &
|
||||
IEEE802154_HW_SUB_GHZ) {
|
||||
if (channel >
|
||||
radio->get_subg_channel_count(net_if_get_device(iface))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MAC utilities
|
||||
* @brief Verify if the given channel lies within the allowed range of available
|
||||
* channels of the driver's currently selected channel page.
|
||||
*
|
||||
* Note: While MAC utilities may refer to PHY utilities,
|
||||
* the inverse is not true.
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
* @param channel The channel to verify or IEEE802154_NO_CHANNEL
|
||||
*
|
||||
* @returns true if the channel is available, false otherwise
|
||||
*/
|
||||
bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_t channel);
|
||||
|
||||
/**
|
||||
* The number of PHY symbols forming a superframe slot when the superframe order
|
||||
* is equal to zero, see sections 8.4.2, table 8-93, aBaseSlotDuration and 6.2.1.
|
||||
* @brief Counts all available channels of the driver's currently selected
|
||||
* channel page.
|
||||
*
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
*
|
||||
* @returns The number of available channels.
|
||||
*/
|
||||
#define IEEE802154_MAC_A_BASE_SLOT_DURATION 60U
|
||||
|
||||
/**
|
||||
* The number of slots contained in any superframe, see section 8.4.2,
|
||||
* table 8-93, aNumSuperframeSlots.
|
||||
*/
|
||||
#define IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS 16U
|
||||
|
||||
/**
|
||||
* The number of PHY symbols forming a superframe when the superframe order is
|
||||
* equal to zero, see section 8.4.2, table 8-93, aBaseSuperframeDuration.
|
||||
*/
|
||||
#define IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION \
|
||||
(IEEE802154_MAC_A_BASE_SLOT_DURATION * IEEE802154_MAC_A_NUM_SUPERFRAME_SLOTS)
|
||||
uint16_t ieee802154_radio_number_of_channels(struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Calculates the MAC's superframe duration (see section 8.4.2,
|
||||
|
|
@ -392,22 +484,18 @@ static inline bool ieee802154_radio_verify_channel(struct net_if *iface, uint16_
|
|||
* @details The number of symbols forming a superframe when the superframe order
|
||||
* is equal to zero.
|
||||
*
|
||||
* @param iface The interface for which the base superframe duration should be
|
||||
* calculated.
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
*
|
||||
* @returns The base superframe duration for the given interface in microseconds.
|
||||
*/
|
||||
static inline uint32_t ieee802154_get_a_base_superframe_duration(struct net_if *iface)
|
||||
{
|
||||
return IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION *
|
||||
ieee802154_radio_get_symbol_period_us(iface);
|
||||
}
|
||||
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
||||
|
||||
/**
|
||||
* Default macResponseWaitTime in multiples of aBaseSuperframeDuration as
|
||||
* defined in section 8.4.3.1, table 8-94.
|
||||
*/
|
||||
#define IEEE802154_MAC_RESONSE_WAIT_TIME_DEFAULT 32U
|
||||
return ieee802154_radio_get_multiple_of_symbol_period(
|
||||
iface, ctx->channel, IEEE802154_MAC_A_BASE_SUPERFRAME_DURATION) /
|
||||
NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves macResponseWaitTime, see section 8.4.3.1, table 8-94,
|
||||
|
|
@ -423,16 +511,15 @@ static inline uint32_t ieee802154_get_a_base_superframe_duration(struct net_if *
|
|||
*
|
||||
* @note Currently this parameter is read-only and uses the specified default of 32.
|
||||
*
|
||||
* @param iface The interface for which the response wait time should be calculated.
|
||||
* @param iface pointer to the IEEE 802.15.4 interface
|
||||
*
|
||||
* @returns The response wait time for the given interface in microseconds.
|
||||
*/
|
||||
static inline uint32_t ieee802154_get_response_wait_time_us(struct net_if *iface)
|
||||
{
|
||||
/* TODO: Make this parameter configurable. */
|
||||
return IEEE802154_MAC_RESONSE_WAIT_TIME_DEFAULT *
|
||||
return IEEE802154_MAC_RESPONSE_WAIT_TIME_DEFAULT *
|
||||
ieee802154_get_a_base_superframe_duration(iface);
|
||||
}
|
||||
|
||||
|
||||
#endif /* __IEEE802154_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ uint8_t mock_ext_addr_be[8] = {0x00, 0x12, 0x4b, 0x00, 0x00, 0x9e, 0xa3, 0xc2};
|
|||
|
||||
static enum ieee802154_hw_caps fake_get_capabilities(const struct device *dev)
|
||||
{
|
||||
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ;
|
||||
return IEEE802154_HW_FCS;
|
||||
}
|
||||
|
||||
static int fake_cca(const struct device *dev)
|
||||
|
|
@ -119,6 +119,20 @@ static int fake_stop(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* driver-allocated attribute memory - constant across all driver instances */
|
||||
IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
|
||||
|
||||
/* API implementation: attr_get */
|
||||
static int fake_attr_get(const struct device *dev, enum ieee802154_attr attr,
|
||||
struct ieee802154_attr_value *value)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return ieee802154_attr_get_channel_page_and_range(
|
||||
attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
|
||||
&drv_attr.phy_supported_channels, value);
|
||||
}
|
||||
|
||||
static void fake_iface_init(struct net_if *iface)
|
||||
{
|
||||
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
||||
|
|
@ -152,6 +166,7 @@ static struct ieee802154_radio_api fake_radio_api = {
|
|||
.start = fake_start,
|
||||
.stop = fake_stop,
|
||||
.tx = fake_tx,
|
||||
.attr_get = fake_attr_get,
|
||||
};
|
||||
|
||||
NET_DEVICE_INIT(fake, "fake_ieee802154",
|
||||
|
|
|
|||
|
|
@ -68,9 +68,6 @@ static struct ieee802154_radio_api rapi = {.get_capabilities = get_capabilities,
|
|||
.start = start_mock,
|
||||
.stop = stop_mock,
|
||||
.configure = configure_mock,
|
||||
#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ
|
||||
.get_subg_channel_count = NULL,
|
||||
#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */
|
||||
.ed_scan = scan_mock};
|
||||
|
||||
#define DT_DRV_COMPAT vnd_ieee802154
|
||||
|
|
@ -126,8 +123,8 @@ static enum ieee802154_hw_caps get_capabilities(const struct device *dev)
|
|||
|
||||
zassert_equal(dev, radio, "Device handle incorrect.");
|
||||
|
||||
caps = IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK |
|
||||
IEEE802154_HW_FILTER | IEEE802154_HW_ENERGY_SCAN | IEEE802154_HW_SLEEP_TO_TX;
|
||||
caps = IEEE802154_HW_FCS | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_ENERGY_SCAN | IEEE802154_HW_SLEEP_TO_TX;
|
||||
if (IS_ENABLED(CONFIG_NET_PKT_TXTIME)) {
|
||||
caps |= IEEE802154_HW_TXTIME;
|
||||
}
|
||||
|
|
@ -542,7 +539,6 @@ ZTEST(openthread_radio, test_promiscuous_mode_set_test)
|
|||
* @brief Test of proper radio to OT capabilities mapping
|
||||
* Tests if different radio capabilities map for their corresponding OpenThread
|
||||
* capability
|
||||
*
|
||||
*/
|
||||
ZTEST(openthread_radio, test_get_caps_test)
|
||||
{
|
||||
|
|
@ -555,12 +551,6 @@ ZTEST(openthread_radio, test_get_caps_test)
|
|||
|
||||
/* not used by OT */
|
||||
get_capabilities_caps_mock_fake.return_val = IEEE802154_HW_FCS;
|
||||
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||
"Incorrect capabilities returned.");
|
||||
get_capabilities_caps_mock_fake.return_val = IEEE802154_HW_2_4_GHZ;
|
||||
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||
"Incorrect capabilities returned.");
|
||||
get_capabilities_caps_mock_fake.return_val = IEEE802154_HW_SUB_GHZ;
|
||||
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||
"Incorrect capabilities returned.");
|
||||
|
||||
|
|
@ -595,9 +585,8 @@ ZTEST(openthread_radio, test_get_caps_test)
|
|||
/* all at once */
|
||||
get_capabilities_caps_mock_fake.return_val =
|
||||
IEEE802154_HW_FCS | IEEE802154_HW_PROMISC | IEEE802154_HW_FILTER |
|
||||
IEEE802154_HW_CSMA | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK |
|
||||
IEEE802154_HW_SUB_GHZ | IEEE802154_HW_ENERGY_SCAN | IEEE802154_HW_TXTIME |
|
||||
IEEE802154_HW_SLEEP_TO_TX;
|
||||
IEEE802154_HW_CSMA | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_ENERGY_SCAN |
|
||||
IEEE802154_HW_TXTIME | IEEE802154_HW_SLEEP_TO_TX;
|
||||
zassert_equal(
|
||||
otPlatRadioGetCaps(ot),
|
||||
OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_ACK_TIMEOUT |
|
||||
|
|
|
|||
Loading…
Reference in a new issue