From 1f24f725bfe96d1903be276e9684ee541684649e Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Wed, 16 Oct 2024 11:08:41 +0200 Subject: [PATCH 1/3] [nrf fromtree] drivers: ieee802154: add Kconfig IEEE802154_SELECTIVE_TXCHANNEL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Kconfig `IEEE802154_SELECTIVE_TXCHANNEL` is added along with the new capability `IEEE802154_HW_SELECTIVE_TXCHANNEL`. The new capability of the ieee802154 drivers allows to schedule CSL transmissions as stated in IEEE 802.15.4-2020 chapter 6.12.2.7 CSL over multiple channels. The benefit of the new API is that additional call to `ieee802154_radio_api::set_channel()` is not required. The drivers will switch to the new channel as late as possible for CSL transmissions thus will not interrupt any reception that might be in progress until the very late moment when the transmission actually starts. This improves reception performance when CSL transmissions are used. Signed-off-by: Damian Krolik Signed-off-by: Andrzej KuroĊ› (cherry picked from commit 2fbba82591d43660d81efff67a131d198cec1ffd) --- drivers/ieee802154/Kconfig | 8 +++++ include/zephyr/net/ieee802154_pkt.h | 22 ++++++++++++ include/zephyr/net/ieee802154_radio.h | 36 ++++++++++++++++++- .../zephyr/net/ieee802154_radio_openthread.h | 3 ++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig index 916cc1a9ddb..a4e4e6d307d 100644 --- a/drivers/ieee802154/Kconfig +++ b/drivers/ieee802154/Kconfig @@ -92,6 +92,14 @@ config IEEE802154_CSL_DEBUG help Enable support for CSL debugging by avoiding sleep state in favor of receive state. +config IEEE802154_SELECTIVE_TXCHANNEL + bool "Support for selective TX channel setting" + help + Enable support for selectively setting TX channel for every timed transmission request. + The drivers MAY have the capability IEEE802154_HW_SELECTIVE_TXCHANNEL only if + this Kconfig option is enabled. If the Kconfig option is disabled the drivers + MUST NOT have the capability. + module = IEEE802154_DRIVER module-str = IEEE 802.15.4 driver module-help = Sets log level for IEEE 802.15.4 Device Drivers. diff --git a/include/zephyr/net/ieee802154_pkt.h b/include/zephyr/net/ieee802154_pkt.h index 3270f994248..b51db139c60 100644 --- a/include/zephyr/net/ieee802154_pkt.h +++ b/include/zephyr/net/ieee802154_pkt.h @@ -59,6 +59,16 @@ struct net_pkt_cb_ieee802154 { */ uint8_t rssi; }; + struct { +#if defined(CONFIG_IEEE802154_SELECTIVE_TXCHANNEL) + /* The channel used for timed transmissions. + * + * Please refer to `ieee802154_radio_api::tx` documentation for + * details. + */ + uint8_t txchannel; +#endif /* CONFIG_IEEE802154_SELECTIVE_TXCHANNEL */ + }; }; /* Flags */ @@ -179,6 +189,18 @@ static inline void net_pkt_set_ieee802154_rssi_dbm(struct net_pkt *pkt, int16_t CODE_UNREACHABLE; } +#if defined(CONFIG_IEEE802154_SELECTIVE_TXCHANNEL) +static inline uint8_t net_pkt_ieee802154_txchannel(struct net_pkt *pkt) +{ + return net_pkt_cb_ieee802154(pkt)->txchannel; +} + +static inline void net_pkt_set_ieee802154_txchannel(struct net_pkt *pkt, uint8_t channel) +{ + net_pkt_cb_ieee802154(pkt)->txchannel = channel; +} +#endif /* CONFIG_IEEE802154_SELECTIVE_TXCHANNEL */ + static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_fpb; diff --git a/include/zephyr/net/ieee802154_radio.h b/include/zephyr/net/ieee802154_radio.h index 10a1922f6fa..f9a557beba0 100644 --- a/include/zephyr/net/ieee802154_radio.h +++ b/include/zephyr/net/ieee802154_radio.h @@ -520,13 +520,26 @@ enum ieee802154_hw_caps { /** RxOnWhenIdle handling supported */ IEEE802154_RX_ON_WHEN_IDLE = BIT(12), + /** Support for timed transmissions on selective channel. + * + * This capability informs that transmissions with modes + * @ref IEEE802154_TX_MODE_TXTIME and @ref IEEE802154_TX_MODE_TXTIME_CCA support + * scheduling of timed transmissions on selective tx channel. + * The driver MAY have this capability only if the Kconfig option + * `CONFIG_IEEE802154_SELECTIVE_TXCHANNEL` is set, otherwise the driver MUST + * NOT have this capability. + * + * Please refer to the `ieee802154_radio_api::tx` documentation for details. + */ + IEEE802154_HW_SELECTIVE_TXCHANNEL = BIT(13), + /* Note: Update also IEEE802154_HW_CAPS_BITS_COMMON_COUNT when changing * the ieee802154_hw_caps type. */ }; /** @brief Number of bits used by ieee802154_hw_caps type. */ -#define IEEE802154_HW_CAPS_BITS_COMMON_COUNT (13) +#define IEEE802154_HW_CAPS_BITS_COMMON_COUNT (14) /** @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 @@ -625,6 +638,8 @@ enum ieee802154_tx_mode { * Transmit packet in the future, at the specified time, no CCA. * * @note requires IEEE802154_HW_TXTIME capability. + * + * @note capability IEEE802154_HW_SELECTIVE_TXCHANNEL may apply. */ IEEE802154_TX_MODE_TXTIME, @@ -635,6 +650,8 @@ enum ieee802154_tx_mode { * * @note Required for Thread 1.2 Coordinated Sampled Listening feature * (see Thread specification 1.2.0, ch. 3.2.6.3). + * + * @note capability IEEE802154_HW_SELECTIVE_TXCHANNEL may apply. */ IEEE802154_TX_MODE_TXTIME_CCA, @@ -1657,6 +1674,23 @@ struct ieee802154_radio_api { * considerable idle waiting time. SHALL return `-ENETDOWN` unless the * interface is "UP". * + * @note The transmission occurs on the radio channel set by the call to + * `set_channel()`. However, if the `CONFIG_IEEE802154_SELECTIVE_TXCHANNEL` + * is set and the driver has the capability `IEEE802154_HW_SELECTIVE_TXCHANNEL` + * then the transmissions requested with `mode` IEEE802154_TX_MODE_TXTIME + * or `IEEE802154_TX_MODE_TXTIME_CCA` SHALL use the radio channel + * returned by `net_pkt_ieee802154_txchannel()` to transmit the packet + * and receive an ACK on that channel if the frame requested it. After + * the operation the driver should return to the channel set previously by + * `set_channel()` call. + * It is responsibility of an upper layer to set the required radio channel + * for the packet by a call to `net_pkt_set_ieee802154_txchannel()`. + * This feature allows CSL transmissions as stated in IEEE 802.15.4-2020 + * chapter 6.12.2.7 CSL over multiple channels. This feature allows to perform + * a switch of the radio channel as late as possible before transmission without + * interrupting possible reception that could occur if separate `set_channel()` + * was called. + * * @param dev pointer to IEEE 802.15.4 driver device * @param mode the transmission mode, some of which require specific * offloading capabilities. diff --git a/include/zephyr/net/ieee802154_radio_openthread.h b/include/zephyr/net/ieee802154_radio_openthread.h index e45bbc6b85b..3606c7a2b78 100644 --- a/include/zephyr/net/ieee802154_radio_openthread.h +++ b/include/zephyr/net/ieee802154_radio_openthread.h @@ -64,6 +64,9 @@ enum ieee802154_openthread_tx_mode { * section 11.3, table 11-2). * * Requires IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA capability. + * + * @note Capability @ref IEEE802154_HW_SELECTIVE_TXCHANNEL applies as for + * @ref IEEE802154_TX_MODE_TXTIME_CCA. */ IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA = IEEE802154_TX_MODE_PRIV_START }; From 343a300dbf544e22c21372162997294778a8cf29 Mon Sep 17 00:00:00 2001 From: Przemyslaw Bida Date: Wed, 27 Nov 2024 14:00:25 +0100 Subject: [PATCH 2/3] [nrf fromtree] drivers: ieee802154: New API for modulated carrier wave transmission. Added new API function to start modulated carrier wave transmission Signed-off-by: Przemyslaw Bida (cherry picked from commit e0f94f882309679c6e8133fdcf25fa8878748ecc) --- drivers/ieee802154/Kconfig | 5 ++++ drivers/ieee802154/ieee802154_nrf5.c | 24 +++++++++++++++--- include/zephyr/net/ieee802154_radio.h | 25 +++++++++++++++++++ modules/hal_nordic/Kconfig | 2 +- modules/openthread/Kconfig.features | 1 + modules/openthread/platform/diag.c | 2 ++ modules/openthread/platform/platform-zephyr.h | 2 ++ modules/openthread/platform/radio.c | 2 ++ 8 files changed, 59 insertions(+), 4 deletions(-) diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig index a4e4e6d307d..af405551f63 100644 --- a/drivers/ieee802154/Kconfig +++ b/drivers/ieee802154/Kconfig @@ -100,6 +100,11 @@ config IEEE802154_SELECTIVE_TXCHANNEL this Kconfig option is enabled. If the Kconfig option is disabled the drivers MUST NOT have the capability. +config IEEE802154_CARRIER_FUNCTIONS + bool "Support for carrier functions" + help + Enable support for functions such as modulated carrier and continuous carrier. + module = IEEE802154_DRIVER module-str = IEEE 802.15.4 driver module-help = Sets log level for IEEE 802.15.4 Device Drivers. diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 613c913868b..a74606edf44 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -720,7 +720,7 @@ static int nrf5_stop(const struct device *dev) return 0; } -#if defined(CONFIG_NRF_802154_CARRIER_FUNCTIONS) +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) static int nrf5_continuous_carrier(const struct device *dev) { ARG_UNUSED(dev); @@ -737,6 +737,23 @@ static int nrf5_continuous_carrier(const struct device *dev) return 0; } + +static int nrf_modulated_carrier(const struct device *dev, const uint8_t *data) +{ + ARG_UNUSED(dev); + + nrf_802154_tx_power_set(nrf5_data.txpwr); + + if (!nrf_802154_modulated_carrier(data)) { + LOG_ERR("Failed to enter modulated carrier state"); + return -EIO; + } + + LOG_DBG("Modulated carrier wave transmission started (channel: %d)", + nrf_802154_channel_get()); + + return 0; +} #endif #if !defined(CONFIG_IEEE802154_NRF5_EXT_IRQ_MGMT) @@ -1244,15 +1261,16 @@ static const struct ieee802154_radio_api nrf5_radio_api = { .set_txpower = nrf5_set_txpower, .start = nrf5_start, .stop = nrf5_stop, -#if defined(CONFIG_NRF_802154_CARRIER_FUNCTIONS) +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) .continuous_carrier = nrf5_continuous_carrier, + .modulated_carrier = nrf_modulated_carrier, #endif .tx = nrf5_tx, .ed_scan = nrf5_energy_scan_start, .get_time = nrf5_get_time, .get_sch_acc = nrf5_get_acc, .configure = nrf5_configure, - .attr_get = nrf5_attr_get + .attr_get = nrf5_attr_get, }; #if defined(CONFIG_NET_L2_IEEE802154) diff --git a/include/zephyr/net/ieee802154_radio.h b/include/zephyr/net/ieee802154_radio.h index f9a557beba0..e2ab96ffac4 100644 --- a/include/zephyr/net/ieee802154_radio.h +++ b/include/zephyr/net/ieee802154_radio.h @@ -1765,6 +1765,7 @@ struct ieee802154_radio_api { */ int (*stop)(const struct device *dev); +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) /** * @brief Start continuous carrier wave transmission. * @@ -1786,6 +1787,30 @@ struct ieee802154_radio_api { */ int (*continuous_carrier)(const struct device *dev); + /** + * @brief Start modulated carrier wave transmission. + * + * @details When the radio is emitting modulated carrier signals, it + * blocks all transmissions on the selected channel. + * This function is to be called only during radio + * tests. Do not use it during normal device operation. + * + * @note Implementations MAY **sleep** and will usually NOT be + * **isr-ok**. MAY be called in any interface state once the driver is + * fully initialized ("ready"). + * + * @param dev pointer to IEEE 802.15.4 driver device + * @param data Pointer to a buffer to modulate the carrier with. + * The first byte is the data length. + * + * @retval 0 modulated carrier wave transmission started + * @retval -EALREADY The driver was already in "TESTING" state and + * emitting a modulated carrier. + * @retval -EIO not started + */ + int (*modulated_carrier)(const struct device *dev, const uint8_t *data); +#endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */ + /** * @brief Set or update driver configuration. * diff --git a/modules/hal_nordic/Kconfig b/modules/hal_nordic/Kconfig index dd4e0a0859b..f29b77e120e 100644 --- a/modules/hal_nordic/Kconfig +++ b/modules/hal_nordic/Kconfig @@ -204,7 +204,7 @@ config NRF_802154_SECURITY_KEY_STORAGE_SIZE config NRF_802154_CARRIER_FUNCTIONS bool "nRF 802.15.4 carrier functions" - default y if OPENTHREAD_DIAG + default y if (OPENTHREAD_DIAG || IEEE802154_CARRIER_FUNCTIONS) help This option enables functions such as modulated carrier and continuous carrier. If this option is modified on a multicore SoC, its remote counterpart must be set to the exact same value. diff --git a/modules/openthread/Kconfig.features b/modules/openthread/Kconfig.features index ccdd3236d38..514b9b85745 100644 --- a/modules/openthread/Kconfig.features +++ b/modules/openthread/Kconfig.features @@ -136,6 +136,7 @@ config OPENTHREAD_DHCP6_SERVER config OPENTHREAD_DIAG bool "Diagnostic functions support" + depends on IEEE802154_CARRIER_FUNCTIONS help Enable OpenThread CLI diagnostic commands diff --git a/modules/openthread/platform/diag.c b/modules/openthread/platform/diag.c index a55368bb10f..b92e34209b8 100644 --- a/modules/openthread/platform/diag.c +++ b/modules/openthread/platform/diag.c @@ -86,6 +86,7 @@ void otPlatDiagRadioReceived(otInstance *aInstance, ARG_UNUSED(aError); } +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable) { if (!otPlatDiagModeGet()) { @@ -94,6 +95,7 @@ otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable) return platformRadioTransmitCarrier(aInstance, aEnable); } +#endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */ void otPlatDiagAlarmCallback(otInstance *aInstance) { diff --git a/modules/openthread/platform/platform-zephyr.h b/modules/openthread/platform/platform-zephyr.h index 8e2d91bd5ef..94fd04d7057 100644 --- a/modules/openthread/platform/platform-zephyr.h +++ b/modules/openthread/platform/platform-zephyr.h @@ -70,10 +70,12 @@ void platformUartPanic(void); */ uint16_t platformRadioChannelGet(otInstance *aInstance); +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) /** * Start/stop continuous carrier wave transmission. */ otError platformRadioTransmitCarrier(otInstance *aInstance, bool aEnable); +#endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */ /** * This function initializes the random number service used by OpenThread. diff --git a/modules/openthread/platform/radio.c b/modules/openthread/platform/radio.c index 7e2943e734f..33fc7b42bbf 100644 --- a/modules/openthread/platform/radio.c +++ b/modules/openthread/platform/radio.c @@ -809,6 +809,7 @@ otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, } #endif +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) otError platformRadioTransmitCarrier(otInstance *aInstance, bool aEnable) { if (radio_api->continuous_carrier == NULL) { @@ -831,6 +832,7 @@ otError platformRadioTransmitCarrier(otInstance *aInstance, bool aEnable) return OT_ERROR_NONE; } +#endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */ otRadioState otPlatRadioGetState(otInstance *aInstance) { From f35376b26a1721070407be98b787e02be5d68714 Mon Sep 17 00:00:00 2001 From: Przemyslaw Bida Date: Thu, 28 Nov 2024 12:17:03 +0100 Subject: [PATCH 3/3] [nrf fromtree] net: openthread: Add `modcarrier` command to OT diag module. Commit add `modcarrier` shell command for Openthread diagnostic mode. Command can transmit modulated carrier out of device for test purposes. Signed-off-by: Przemyslaw Bida (cherry picked from commit 63e1bb41b103426a15b53e2dcaaf53655b3bafb8) --- drivers/ieee802154/Kconfig | 1 + modules/openthread/Kconfig.features | 1 - modules/openthread/platform/diag.c | 37 +++++++++++++++++++ modules/openthread/platform/platform-zephyr.h | 9 ++++- modules/openthread/platform/radio.c | 29 +++++++++++++++ 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig index af405551f63..629b492a579 100644 --- a/drivers/ieee802154/Kconfig +++ b/drivers/ieee802154/Kconfig @@ -102,6 +102,7 @@ config IEEE802154_SELECTIVE_TXCHANNEL config IEEE802154_CARRIER_FUNCTIONS bool "Support for carrier functions" + default y if OPENTHREAD_DIAG help Enable support for functions such as modulated carrier and continuous carrier. diff --git a/modules/openthread/Kconfig.features b/modules/openthread/Kconfig.features index 514b9b85745..ccdd3236d38 100644 --- a/modules/openthread/Kconfig.features +++ b/modules/openthread/Kconfig.features @@ -136,7 +136,6 @@ config OPENTHREAD_DHCP6_SERVER config OPENTHREAD_DIAG bool "Diagnostic functions support" - depends on IEEE802154_CARRIER_FUNCTIONS help Enable OpenThread CLI diagnostic commands diff --git a/modules/openthread/platform/diag.c b/modules/openthread/platform/diag.c index b92e34209b8..23ea3b97986 100644 --- a/modules/openthread/platform/diag.c +++ b/modules/openthread/platform/diag.c @@ -7,9 +7,11 @@ #include #include +#include #include #include "platform-zephyr.h" +#include "zephyr/sys/util.h" /** * Diagnostics mode variables. @@ -19,6 +21,8 @@ static bool sDiagMode; static void *sDiagCallbackContext; static otPlatDiagOutputCallback sDiagOutputCallback; +static otError startModCarrier(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]); + static void diag_output(const char *aFormat, ...) { va_list args; @@ -47,6 +51,12 @@ otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArg ARG_UNUSED(aInstance); ARG_UNUSED(aArgsLength); +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) + if (strcmp(aArgs[0], "modcarrier") == 0) { + return startModCarrier(aInstance, aArgsLength - 1, aArgs + 1); + } +#endif + /* Add more platform specific diagnostics features here. */ diag_output("diag feature '%s' is not supported\r\n", aArgs[0]); @@ -276,3 +286,30 @@ otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode) #endif /* DT_HAS_COMPAT_STATUS_OKAY(openthread_config) && \ * DT_NODE_HAS_PROP(DT_COMPAT_GET_ANY_STATUS_OKAY(openthread_config), diag_gpios) */ + +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) + +static otError startModCarrier(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]) +{ + ARG_UNUSED(aInstance); + ARG_UNUSED(aArgsLength); + + bool enable = true; + uint8_t data[OT_RADIO_FRAME_MAX_SIZE + 1]; + + if (aArgsLength <= 0) { + return OT_ERROR_INVALID_ARGS; + } + + if (strcmp(aArgs[0], "stop") == 0) { + enable = false; + } else { + if (hex2bin(aArgs[0], strlen(aArgs[0]), data, ARRAY_SIZE(data)) == 0) { + return OT_ERROR_INVALID_ARGS; + } + } + + return platformRadioTransmitModulatedCarrier(aInstance, enable, data); +} + +#endif diff --git a/modules/openthread/platform/platform-zephyr.h b/modules/openthread/platform/platform-zephyr.h index 94fd04d7057..ca25fedf2b1 100644 --- a/modules/openthread/platform/platform-zephyr.h +++ b/modules/openthread/platform/platform-zephyr.h @@ -77,13 +77,20 @@ uint16_t platformRadioChannelGet(otInstance *aInstance); otError platformRadioTransmitCarrier(otInstance *aInstance, bool aEnable); #endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */ +#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS) +/** + * Start/stop modulated carrier wave transmission. + */ +otError platformRadioTransmitModulatedCarrier(otInstance *aInstance, bool aEnable, + const uint8_t *aData); +#endif + /** * This function initializes the random number service used by OpenThread. * */ void platformRandomInit(void); - /** * Initialize platform Shell driver. */ diff --git a/modules/openthread/platform/radio.c b/modules/openthread/platform/radio.c index 33fc7b42bbf..73f6f4dc9cc 100644 --- a/modules/openthread/platform/radio.c +++ b/modules/openthread/platform/radio.c @@ -11,6 +11,7 @@ * */ +#include #define LOG_MODULE_NAME net_otPlat_radio #include @@ -832,6 +833,34 @@ otError platformRadioTransmitCarrier(otInstance *aInstance, bool aEnable) return OT_ERROR_NONE; } + +otError platformRadioTransmitModulatedCarrier(otInstance *aInstance, bool aEnable, + const uint8_t *aData) +{ + if (radio_api->modulated_carrier == NULL) { + return OT_ERROR_NOT_IMPLEMENTED; + } + + if (aEnable && sState == OT_RADIO_STATE_RECEIVE) { + if (aData == NULL) { + return OT_ERROR_INVALID_ARGS; + } + + radio_api->set_txpower(radio_dev, get_transmit_power_for_channel(channel)); + + if (radio_api->modulated_carrier(radio_dev, aData) != 0) { + return OT_ERROR_FAILED; + } + sState = OT_RADIO_STATE_TRANSMIT; + } else if ((!aEnable) && sState == OT_RADIO_STATE_TRANSMIT) { + return otPlatRadioReceive(aInstance, channel); + } else { + return OT_ERROR_INVALID_STATE; + } + + return OT_ERROR_NONE; +} + #endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */ otRadioState otPlatRadioGetState(otInstance *aInstance)