From 29d5873819574803095c899a7415e9cf44a80451 Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Tue, 3 Jan 2023 17:29:30 +0800 Subject: [PATCH] openthread_port: support CSL on esp32c6 --- .../ieee802154/include/esp_ieee802154.h | 71 ++++- components/ieee802154/lib | 2 +- components/openthread/CMakeLists.txt | 1 + components/openthread/Kconfig | 20 ++ components/openthread/linker.lf | 10 + .../openthread/port/esp_openthread_radio.c | 289 +++++++++++++++++- .../openthread-core-esp32x-ftd-config.h | 57 ++++ 7 files changed, 434 insertions(+), 16 deletions(-) create mode 100644 components/openthread/linker.lf diff --git a/components/ieee802154/include/esp_ieee802154.h b/components/ieee802154/include/esp_ieee802154.h index d2e91e01cc..3d8860a493 100644 --- a/components/ieee802154/include/esp_ieee802154.h +++ b/components/ieee802154/include/esp_ieee802154.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -474,6 +474,75 @@ extern void esp_ieee802154_timer0_done(void); */ extern void esp_ieee802154_timer1_done(void); +/** + * @brief Set the IEEE 802.15.4 Radio to receive state at a specific time. + * + * + * @param[in] time A specific timestamp for starting receiving. + * @return + * - ESP_OK on success + * - ESP_FAIL on failure due to invalid state. + * + * Note: Radio will start receiving after the timestamp, and continue receiving until it receives a valid frame. + * Ref to esp_ieee802154_receive_done(). + * + */ +esp_err_t esp_ieee802154_receive_at(uint32_t time); + +/** + * @brief Transmit the given frame at a specific time. + * + * @param[in] frame The pointer to the frame. Refer to `esp_ieee802154_transmit()`. + * @param[in] cca Perform CCA before transmission if it's true, otherwise transmit the frame directly. + * @param[in] time A specific timestamp for starting transmission. + * + * @return + * - ESP_OK on success. + * - ESP_FAIL on failure due to invalid state. + * + * Note: The transmit result will be reported via esp_ieee802154_transmit_done() + * or esp_ieee802154_transmit_failed(). + * + */ +esp_err_t esp_ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time); + +/** + * @brief Get the RSSI of the most recent received frame. + * + * @return The value of RSSI. + * + */ +int8_t esp_ieee802154_get_recent_rssi(void); + +/** + * @brief Get the LQI of the most recent received frame. + * + * @return The value of LQI. + * + */ +uint8_t esp_ieee802154_get_recent_lqi(void); + +/** + * @brief Set the key and addr for a frame needs to be encrypted by HW. + * + * @param[in] frame A frame needs to be encrypted. Refer to `esp_ieee802154_transmit()`. + * @param[in] key A 16-bytes key for encryption. + * @param[in] addr An 8-bytes addr for HW to generate nonce, in general, is the device extended address. + * + */ +void esp_ieee802154_set_transmit_security(uint8_t *frame, uint8_t *key, uint8_t *addr); + +/** + * @brief This function will be called when a received frame needs to be acked with Enh-Ack, the upper + * layer should generate the Enh-Ack frame in this callback function. + * + * @param[in] frame The received frame. + * @param[in] frame_info The frame information. Refer to `esp_ieee802154_frame_info_t`. + * @param[out] enhack_frame The Enh-ack frame need to be generated via this function, HW will send it back after AIFS. + * + */ +void esp_ieee802154_enh_ack_generator(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info, uint8_t* enhack_frame); + #ifdef __cplusplus } #endif diff --git a/components/ieee802154/lib b/components/ieee802154/lib index ecb84fc262..54ceb75476 160000 --- a/components/ieee802154/lib +++ b/components/ieee802154/lib @@ -1 +1 @@ -Subproject commit ecb84fc262cfb8d0f262c22f7f8792bf069dfdd9 +Subproject commit 54ceb75476f7bdbb8a2557d2a8a012a9342e7a37 diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index 3f7d153419..2290df57b2 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -167,6 +167,7 @@ idf_component_register(SRC_DIRS "${src_dirs}" INCLUDE_DIRS "${public_include_dirs}" PRIV_INCLUDE_DIRS "${private_include_dirs}" REQUIRES esp_netif lwip + LDFRAGMENTS linker.lf PRIV_REQUIRES console driver esp_event esp_partition esp_timer ieee802154 mbedtls spi_flash) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 267012a01b..f8376b52bd 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -165,4 +165,24 @@ menu "OpenThread" help Set the OpenThread UART buffer size. + config OPENTHREAD_LINK_METRICS + bool "Enable link metrics feature" + depends on OPENTHREAD_ENABLED + default n + help + Select this option to enable link metrics feature + + config OPENTHREAD_CSL_ENABLE + bool "Enable CSL feature" + depends on OPENTHREAD_ENABLED + default n + help + Select this option to enable CSL feature + + config OPENTHREAD_CSL_DEBUG_ENABLE + bool "Enable CSL debug" + depends on OPENTHREAD_CSL_ENABLE + default n + help + Select this option to set rx on when sleep in CSL feature, only for debug endmenu diff --git a/components/openthread/linker.lf b/components/openthread/linker.lf new file mode 100644 index 0000000000..2704ecbe09 --- /dev/null +++ b/components/openthread/linker.lf @@ -0,0 +1,10 @@ +[mapping:openthread] +archive: libopenthread.a +entries: + if OPENTHREAD_CSL_ENABLE = y || OPENTHREAD_LINK_METRICS = y: + mesh_forwarder (noflash_text) + mac_frame (noflash_text) + csl_tx_scheduler (noflash_text) + link_metrics (noflash_text) + mac (noflash_text) + sub_mac (noflash_text) diff --git a/components/openthread/port/esp_openthread_radio.c b/components/openthread/port/esp_openthread_radio.c index 7241c4f616..d98e53e221 100644 --- a/components/openthread/port/esp_openthread_radio.c +++ b/components/openthread/port/esp_openthread_radio.c @@ -22,10 +22,16 @@ #include "rom/ets_sys.h" #include "openthread-core-config.h" +#include "openthread/link.h" #include "openthread/platform/diag.h" #include "openthread/platform/radio.h" +#include "utils/link_metrics.h" +#include "utils/mac_frame.h" #define ESP_RECEIVE_SENSITIVITY -120 +#define ESP_OPENTHREAD_XTAL_ACCURACY 130 +#define ESP_OPENTHREAD_CSL_ACCURACY 1 +#define ESP_OPENTHREAD_CSL_UNCERTAIN 1 #define EVENT_TX_DONE (1 << 0) #define EVENT_TX_FAILED (1 << 1) @@ -46,16 +52,38 @@ typedef struct { static otRadioFrame s_transmit_frame; static esp_openthread_radio_tx_psdu s_transmit_psdu; +static uint8_t *s_enhack; static otRadioFrame s_receive_frame[CONFIG_IEEE802154_RX_BUFFER_SIZE]; static otRadioFrame s_ack_frame; static int s_ed_power; -static int s_rssi = 127; static esp_ieee802154_tx_error_t s_tx_error; static int s_radio_event_fd = -1; static bool s_diag_mode = false; static const char *s_radio_workflow = "radio"; static uint8_t s_txrx_events; +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT +static otRadioIeInfo s_transmit_ie_info; +#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +static uint32_t s_csl_period; +static uint32_t s_csl_sample_time; +#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 +static uint32_t s_mac_frame_counter; +static uint8_t s_key_id; +static struct otMacKeyMaterial s_pervious_key; +static struct otMacKeyMaterial s_current_key; +static struct otMacKeyMaterial s_next_key; +static bool s_with_security_enh_ack = false; +static uint32_t s_ack_frame_counter; +static uint8_t s_ack_key_id; +static uint8_t s_security_key[16]; +static uint8_t s_security_addr[8]; +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + static esp_openthread_circular_queue_info_t s_recv_queue = {.head = 0, .tail = 0, .used = 0}; static void set_event(uint8_t event) @@ -92,6 +120,10 @@ esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *conf s_ack_frame.mPsdu = NULL; memset(&s_recv_queue, 0, sizeof(esp_openthread_circular_queue_info_t)); +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + s_transmit_frame.mInfo.mTxInfo.mIeInfo = &s_transmit_ie_info; +#endif + esp_ieee802154_enable(); esp_ieee802154_set_promiscuous(false); esp_ieee802154_set_rx_when_idle(true); @@ -266,7 +298,31 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) aFrame->mPsdu[-1] = aFrame->mLength; // lenth locates one byte before the psdu (esp_openthread_radio_tx_psdu); - esp_ieee802154_transmit(&aFrame->mPsdu[-1], aFrame->mInfo.mTxInfo.mCsmaCaEnabled); +// TODO: remove this macro check when esp32h4 unsupported. +#if !CONFIG_IDF_TARGET_ESP32H4 + // esp32h4 do not support tx security + if (otMacFrameIsSecurityEnabled(aFrame) && !aFrame->mInfo.mTxInfo.mIsSecurityProcessed) { + otMacFrameSetFrameCounter(aFrame, s_mac_frame_counter++); + if (otMacFrameIsKeyIdMode1(aFrame)) { + s_transmit_frame.mInfo.mTxInfo.mAesKey = &s_current_key; + if (!s_transmit_frame.mInfo.mTxInfo.mIsARetx) { + otMacFrameSetKeyId(aFrame, s_key_id); + } + esp_ieee802154_get_extended_address(s_security_addr); + } + memcpy(s_security_key, s_current_key.mKeyMaterial.mKey.m8, sizeof(s_current_key.mKeyMaterial.mKey.m8)); + esp_ieee802154_set_transmit_security(&aFrame->mPsdu[-1], s_security_key, s_security_addr); + } + + // esp32h4 do not support transmit at + if (aFrame->mInfo.mTxInfo.mTxDelay != 0) { + esp_ieee802154_transmit_at(&aFrame->mPsdu[-1], aFrame->mInfo.mTxInfo.mCsmaCaEnabled, + (aFrame->mInfo.mTxInfo.mTxDelayBaseTime + aFrame->mInfo.mTxInfo.mTxDelay)); + } else +#endif + { + esp_ieee802154_transmit(&aFrame->mPsdu[-1], aFrame->mInfo.mTxInfo.mCsmaCaEnabled); + } otPlatRadioTxStarted(aInstance, aFrame); @@ -280,14 +336,29 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) int8_t otPlatRadioGetRssi(otInstance *aInstance) { - return s_rssi; + return esp_ieee802154_get_recent_rssi(); } otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) { - return (otRadioCaps)(OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_SLEEP_TO_TX); + return (otRadioCaps)(OT_RADIO_CAPS_ENERGY_SCAN | +// TODO: remove this macro check when esp32h4 unsupported. +#if !CONFIG_IDF_TARGET_ESP32H4 + OT_RADIO_CAPS_TRANSMIT_SEC | OT_RADIO_CAPS_RECEIVE_TIMING | OT_RADIO_CAPS_TRANSMIT_TIMING | +#endif + OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_SLEEP_TO_TX); } +// TODO: remove this macro check when esp32h4 unsupported. +#if !CONFIG_IDF_TARGET_ESP32H4 +// esp32h4 do not support receive at +otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration) +{ + esp_ieee802154_receive_at((aStart + aDuration)); + return OT_ERROR_NONE; +} +#endif + bool otPlatRadioGetPromiscuous(otInstance *aInstance) { return esp_ieee802154_get_promiscuous(); @@ -295,7 +366,11 @@ bool otPlatRadioGetPromiscuous(otInstance *aInstance) void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) { +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + esp_ieee802154_set_pending_mode(ESP_IEEE802154_AUTO_PENDING_ENHANCED); +#else esp_ieee802154_set_pending_mode(ESP_IEEE802154_AUTO_PENDING_ENABLE); +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 } otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress) @@ -404,36 +479,212 @@ void otPlatDiagAlarmCallback(otInstance *aInstance) OT_UNUSED_VARIABLE(aInstance); } +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 +void otPlatRadioSetMacKey(otInstance *aInstance, uint8_t aKeyIdMode, uint8_t aKeyId, const otMacKeyMaterial *aPrevKey, + const otMacKeyMaterial *aCurrKey, const otMacKeyMaterial *aNextKey, otRadioKeyType aKeyType) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aKeyIdMode); + assert(aKeyType == OT_KEY_TYPE_LITERAL_KEY); + assert(aPrevKey != NULL && aCurrKey != NULL && aNextKey != NULL); + + s_key_id = aKeyId; + s_pervious_key = *aPrevKey; + s_current_key = *aCurrKey; + s_next_key = *aNextKey; +} + +void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter) +{ + OT_UNUSED_VARIABLE(aInstance); + + s_mac_frame_counter = aMacFrameCounter; +} +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + +uint64_t otPlatRadioGetNow(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return esp_timer_get_time(); +} + +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTime) +{ + OT_UNUSED_VARIABLE(aInstance); + s_csl_sample_time = aCslSampleTime; +} + +static IRAM_ATTR uint16_t get_csl_phase() +{ + uint32_t cur_time = esp_timer_get_time(); + uint32_t csl_period_us = s_csl_period * OT_US_PER_TEN_SYMBOLS; + uint32_t diff = (csl_period_us - (cur_time % csl_period_us) + (s_csl_sample_time % csl_period_us)) % csl_period_us; + + return (uint16_t)(diff / OT_US_PER_TEN_SYMBOLS + 1); +} +#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + +uint16_t otPlatTimeGetXtalAccuracy(void) +{ + return ESP_OPENTHREAD_XTAL_ACCURACY; +} + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +otError otPlatRadioConfigureEnhAckProbing(otInstance *aInstance, otLinkMetrics aLinkMetrics, + const otShortAddress aShortAddress, const otExtAddress *aExtAddress) +{ + otError error = otLinkMetricsConfigureEnhAckProbing(aShortAddress, aExtAddress, aLinkMetrics); + return error; +} +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, otShortAddress aShortAddr, + const otExtAddress *aExtAddr) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aShortAddr); + OT_UNUSED_VARIABLE(aExtAddr); + s_csl_period = aCslPeriod; + + return OT_ERROR_NONE; +} + +uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance) +{ + return ESP_OPENTHREAD_CSL_ACCURACY; +} + +uint8_t otPlatRadioGetCslUncertainty(otInstance *aInstance) +{ + return ESP_OPENTHREAD_CSL_UNCERTAIN; +} + +#endif + // events void IRAM_ATTR esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, - esp_ieee802154_frame_info_t *s_ack_frame_info) + esp_ieee802154_frame_info_t *ack_frame_info) { ETS_ASSERT(frame == (uint8_t *)&s_transmit_psdu); if (ack != NULL) { s_ack_frame.mLength = (uint16_t)(*ack); s_ack_frame.mPsdu = (uint8_t *)(ack + 1); + s_ack_frame.mChannel = ack_frame_info->channel; + s_ack_frame.mInfo.mRxInfo.mRssi = ack_frame_info->rssi; + s_ack_frame.mInfo.mRxInfo.mTimestamp = ack_frame_info->timestamp; } set_event(EVENT_TX_DONE); } +static void IRAM_ATTR convert_to_ot_frame(uint8_t *data, esp_ieee802154_frame_info_t *frame_info, + otRadioFrame *radio_frame) +{ + radio_frame->mPsdu = data + 1; + radio_frame->mLength = *data; + radio_frame->mChannel = frame_info->channel; + radio_frame->mInfo.mRxInfo.mRssi = frame_info->rssi; + radio_frame->mInfo.mRxInfo.mAckedWithFramePending = frame_info->pending; + radio_frame->mInfo.mRxInfo.mTimestamp = esp_timer_get_time(); + +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + radio_frame->mInfo.mRxInfo.mTimestamp = frame_info->timestamp; +#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +} + +static void IRAM_ATTR enh_ack_set_security_addr_and_key(otRadioFrame *ack_frame) +{ + struct otMacKeyMaterial *key = NULL; + uint8_t key_id; + + ETS_ASSERT(otMacFrameIsSecurityEnabled(ack_frame)); + key_id = otMacFrameGetKeyId(ack_frame); + ETS_ASSERT(otMacFrameIsKeyIdMode1(ack_frame) && key_id != 0); + + if (key_id == s_key_id) { + key = &s_current_key; + } else if (key_id == s_key_id - 1) { + key = &s_pervious_key; + } else if (key_id == s_key_id + 1) { + key = &s_next_key; + } else { + ETS_ASSERT(false); + } + s_ack_frame_counter = s_mac_frame_counter; + s_ack_key_id = key_id; + s_with_security_enh_ack = true; + if (otMacFrameIsKeyIdMode1(ack_frame)) { + esp_ieee802154_get_extended_address(s_security_addr); + memcpy(s_security_key, (*key).mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE); + } + + esp_ieee802154_set_transmit_security(&ack_frame->mPsdu[-1], s_security_key, s_security_addr); +} + +void IRAM_ATTR esp_ieee802154_enh_ack_generator(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info, + uint8_t *enhack_frame) +{ + otRadioFrame ack_frame; + otRadioFrame ot_frame; + uint8_t ack_ie_data[OT_ACK_IE_MAX_SIZE]; + uint8_t offset = 0; +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + uint8_t link_metrics_data_len = 0; + uint8_t link_metrics_data[OT_ENH_PROBING_IE_DATA_MAX_SIZE]; + otMacAddress mac_addr; +#endif + ack_frame.mPsdu = enhack_frame + 1; + convert_to_ot_frame(frame, frame_info, &ot_frame); + +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + if (s_csl_period > 0) { + offset += otMacFrameGenerateCslIeTemplate(ack_ie_data); + } +#endif + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + otMacFrameGetSrcAddr(&ot_frame, &mac_addr); + link_metrics_data_len = otLinkMetricsEnhAckGenData(&mac_addr, esp_ieee802154_get_recent_lqi(), + esp_ieee802154_get_recent_rssi(), link_metrics_data); + if (link_metrics_data_len > 0) { + offset += otMacFrameGenerateEnhAckProbingIe(ack_ie_data, link_metrics_data, link_metrics_data_len); + } +#endif + + ETS_ASSERT(otMacFrameGenerateEnhAck(&ot_frame, frame_info->pending, ack_ie_data, offset, &ack_frame) == OT_ERROR_NONE); + enhack_frame[0] = ack_frame.mLength; + + s_enhack = enhack_frame; + + if (otMacFrameIsSecurityEnabled(&ack_frame) && !ack_frame.mInfo.mTxInfo.mIsSecurityProcessed) { + otMacFrameSetFrameCounter(&ack_frame, s_mac_frame_counter++); + enh_ack_set_security_addr_and_key(&ack_frame); + } +} + void IRAM_ATTR esp_ieee802154_receive_done(uint8_t *data, esp_ieee802154_frame_info_t *frame_info) { + otRadioFrame ot_frame; + ot_frame.mPsdu = data + 1; + if (s_recv_queue.used == CONFIG_IEEE802154_RX_BUFFER_SIZE) { ESP_EARLY_LOGE(OT_PLAT_LOG_TAG, "radio receive buffer full!"); return; } - s_rssi = frame_info->rssi; - - s_receive_frame[s_recv_queue.tail].mPsdu = data + 1; - s_receive_frame[s_recv_queue.tail].mLength = *data; - s_receive_frame[s_recv_queue.tail].mChannel = frame_info->channel; - s_receive_frame[s_recv_queue.tail].mInfo.mRxInfo.mRssi = frame_info->rssi; - s_receive_frame[s_recv_queue.tail].mInfo.mRxInfo.mAckedWithFramePending = frame_info->pending; - s_receive_frame[s_recv_queue.tail].mInfo.mRxInfo.mTimestamp = esp_timer_get_time(); - + convert_to_ot_frame(data, frame_info, &(s_receive_frame[s_recv_queue.tail])); +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + // Inform if this frame was acknowledged with secured Enh-ACK. + if (otMacFrameIsAckRequested(&ot_frame) && otMacFrameIsVersion2015(&ot_frame)) { + s_receive_frame[s_recv_queue.tail].mInfo.mRxInfo.mAckedWithSecEnhAck = s_with_security_enh_ack; + s_receive_frame[s_recv_queue.tail].mInfo.mRxInfo.mAckFrameCounter = s_ack_frame_counter; + s_receive_frame[s_recv_queue.tail].mInfo.mRxInfo.mAckKeyId = s_ack_key_id; + } + s_with_security_enh_ack = false; +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 s_recv_queue.tail = (s_recv_queue.tail + 1) % CONFIG_IEEE802154_RX_BUFFER_SIZE; s_recv_queue.used++; set_event(EVENT_RX_DONE); @@ -454,6 +705,16 @@ void IRAM_ATTR esp_ieee802154_receive_sfd_done(void) void IRAM_ATTR esp_ieee802154_transmit_sfd_done(uint8_t *frame) { + assert(frame == (uint8_t *)&s_transmit_psdu || frame == s_enhack); +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + otRadioFrame ot_frame; + ot_frame.mPsdu = frame + 1; + ot_frame.mLength = frame[0]; + + if (s_csl_period > 0) { + otMacFrameSetCslIe(&ot_frame, s_csl_period, get_csl_phase()); + } +#endif } void IRAM_ATTR esp_ieee802154_energy_detect_done(int8_t power) diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 18747d2d3a..4f26e4dc26 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -434,4 +434,61 @@ */ #define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE CONFIG_OPENTHREAD_DNS_CLIENT +#if CONFIG_OPENTHREAD_CSL_ENABLE + +/** + * @def OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + * + * Define as 1 to support Thread 1.2 CSL feature. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +#define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + * + * Define as 1 to set the ahead time for CSL transmit timing. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US +#define OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US 20000 +#endif + +/** + * @def OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE + * + * Define as 1 to enable support Thread 1.2 CSL debug. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE +#define OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE CONFIG_OPENTHREAD_CSL_DEBUG_ENABLE +#endif + +#endif // CONFIG_OPENTHREAD_CSL_ENABLE + +#if CONFIG_OPENTHREAD_LINK_METRICS + +/** + * @def OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + * + * Define as 1 to support Thread 1.2 Link Metrics Subject feature. + * + */ +#ifndef OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + * + * Define as 1 to support Thread 1.2 Link Metrics feature. + * + */ +#ifndef OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE +#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 1 +#endif +#endif //CONFIG_OPENTHREAD_LINK_METRICS + #define OPENTHREAD_FTD 1