Merge branch 'backport/openthread_related_feature_v52' into 'release/v5.2'

Backport some openthread related features (backport v5.2)

See merge request espressif/esp-idf!28053
This commit is contained in:
Jiang Jiang Jian 2023-12-25 20:37:03 +08:00
commit 3139ae0f0e
30 changed files with 849 additions and 275 deletions

View File

@ -17,6 +17,7 @@ typedef enum {
void esp_coex_ieee802154_txrx_pti_set(ieee802154_coex_event_t event);
void esp_coex_ieee802154_ack_pti_set(ieee802154_coex_event_t event);
void esp_coex_ieee802154_coex_break_notify(void);
#endif
#endif

@ -1 +1 @@
Subproject commit b5da84bed42578946162241cfc6b37449bd2c251
Subproject commit 667353cc7a0520924135ce50b798f495cd308e47

View File

@ -455,6 +455,85 @@ static inline void ieee802154_ll_disable_coex(void)
IEEE802154.pti.hw_ack_pti = 1;
}
static inline void ieee802154_ll_clear_debug_cnt(uint32_t clear_bits)
{
IEEE802154.debug_cnt_clr.val = clear_bits;
}
static inline uint32_t ieee802154_ll_get_sfd_timeout_cnt(void)
{
return IEEE802154.debug_sfd_timeout_cnt;
}
static inline uint32_t ieee802154_ll_get_crc_error_cnt(void)
{
return IEEE802154.debug_crc_error_cnt;
}
static inline uint32_t ieee802154_ll_get_ed_abort_cnt(void)
{
return IEEE802154.debug_ed_abort_cnt;
}
static inline uint32_t ieee802154_ll_get_cca_fail_cnt(void)
{
return IEEE802154.debug_cca_fail_cnt;
}
static inline uint32_t ieee802154_ll_get_rx_fliter_fail_cnt(void)
{
return IEEE802154.debug_rx_filter_fail_cnt;
}
static inline uint32_t ieee802154_ll_get_no_rss_detect_cnt(void)
{
return IEEE802154.debug_no_rss_detect_cnt;
}
static inline uint32_t ieee802154_ll_get_rx_abort_coex_cnt(void)
{
return IEEE802154.debug_rx_abort_coex_cnt;
}
static inline uint32_t ieee802154_ll_get_rx_restart_cnt(void)
{
return IEEE802154.debug_rx_restart_cnt;
}
static inline uint32_t ieee802154_ll_get_tx_ack_abort_coex_cnt(void)
{
return IEEE802154.debug_tx_ack_abort_coex_cnt;
}
static inline uint32_t ieee802154_ll_get_ed_scan_coex_cnt(void)
{
return IEEE802154.debug_ed_scan_break_coex_cnt;
}
static inline uint32_t ieee802154_ll_get_rx_ack_abort_coex_cnt(void)
{
return IEEE802154.debug_rx_ack_abort_coex_cnt;
}
static inline uint32_t ieee802154_ll_get_rx_ack_timeout_cnt(void)
{
return IEEE802154.debug_rx_ack_timeout_cnt;
}
static inline uint32_t ieee802154_ll_get_tx_break_coex_cnt(void)
{
return IEEE802154.debug_tx_break_coex_cnt;
}
static inline uint32_t ieee802154_ll_get_tx_security_error_cnt(void)
{
return IEEE802154.debug_tx_security_error_cnt;
}
static inline uint32_t ieee802154_ll_get_cca_busy_cnt(void)
{
return IEEE802154.debug_cca_busy_cnt;
}
#endif
#ifdef __cplusplus

View File

@ -159,4 +159,11 @@ menu "IEEE 802.15.4"
default 10
help
set the record abort table size
config IEEE802154_TXRX_STATISTIC
bool "Enable record tx/rx packets information for debugging"
depends on IEEE802154_DEBUG
default n
help
Enabling this option to record the tx and rx
endmenu # IEEE 802.15.4

View File

@ -5,6 +5,7 @@
*/
#include <stdio.h>
#include <string.h>
#include "hal/ieee802154_ll.h"
#include "esp_ieee802154_util.h"
#include "esp_log.h"
@ -237,4 +238,122 @@ void ieee802154_assert_print(void)
}
#endif // CONFIG_IEEE802154_ASSERT
#if CONFIG_IEEE802154_TXRX_STATISTIC
static ieee802154_txrx_statistic_t s_ieee802154_txrx_statistic;
void ieee802154_txrx_statistic_clear(void)
{
memset(&s_ieee802154_txrx_statistic, 0, sizeof(ieee802154_txrx_statistic_t));
}
void ieee802154_txrx_statistic(ieee802154_ll_events events)
{
if (events == IEEE802154_EVENT_TX_DONE) {
s_ieee802154_txrx_statistic.tx.done_nums++;
} else if (events == IEEE802154_EVENT_RX_DONE) {
s_ieee802154_txrx_statistic.rx.done_nums++;
}
s_ieee802154_txrx_statistic.tx.abort.cca_busy_nums += ieee802154_ll_get_cca_busy_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_CCA_BUSY_CNT_CLEAR);
s_ieee802154_txrx_statistic.tx.abort.tx_security_error_nums += ieee802154_ll_get_tx_security_error_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR);
// Do not record TX_BREAK_COEX_ERR due to ZB-105.
s_ieee802154_txrx_statistic.tx.abort.rx_ack_timeout_nums += ieee802154_ll_get_rx_ack_timeout_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR);
s_ieee802154_txrx_statistic.tx.abort.rx_ack_coex_break_nums += ieee802154_ll_get_rx_ack_abort_coex_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR);
s_ieee802154_txrx_statistic.tx.abort.cca_failed_nums += ieee802154_ll_get_cca_fail_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_CCA_FAIL_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.tx_ack_coex_break_nums += ieee802154_ll_get_tx_ack_abort_coex_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_TX_ACK_ABORT_COEX_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.rx_restart_nums += ieee802154_ll_get_rx_restart_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_RX_RESTART_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.rx_coex_break_nums += ieee802154_ll_get_rx_abort_coex_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_RX_ABORT_COEX_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.no_rss_nums += ieee802154_ll_get_no_rss_detect_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_NO_RSS_DETECT_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.filter_fail_nums += ieee802154_ll_get_rx_fliter_fail_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_RX_FILTER_FAIL_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.ed_abort_nums += ieee802154_ll_get_ed_abort_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_ED_ABORT_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.crc_error_nums += ieee802154_ll_get_crc_error_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_CRC_ERROR_CNT_CLEAR);
s_ieee802154_txrx_statistic.rx.abort.sfd_timeout_nums += ieee802154_ll_get_sfd_timeout_cnt();
ieee802154_ll_clear_debug_cnt(IEEE802154_SFD_TIMEOUT_CNT_CLEAR);
}
void ieee802154_tx_nums_update(void)
{
s_ieee802154_txrx_statistic.tx.nums++;
}
void ieee802154_tx_break_coex_nums_update(void)
{
s_ieee802154_txrx_statistic.tx.abort.tx_coex_break_nums++;
}
void ieee802154_txrx_statistic_print(void)
{
uint64_t tx_success_nums = s_ieee802154_txrx_statistic.tx.done_nums - s_ieee802154_txrx_statistic.tx.abort.rx_ack_coex_break_nums - s_ieee802154_txrx_statistic.tx.abort.rx_ack_timeout_nums;
uint64_t tx_abort_nums = s_ieee802154_txrx_statistic.tx.abort.rx_ack_coex_break_nums + s_ieee802154_txrx_statistic.tx.abort.rx_ack_timeout_nums +
s_ieee802154_txrx_statistic.tx.abort.tx_coex_break_nums + s_ieee802154_txrx_statistic.tx.abort.tx_security_error_nums +
s_ieee802154_txrx_statistic.tx.abort.cca_failed_nums + s_ieee802154_txrx_statistic.tx.abort.cca_busy_nums;
uint64_t tx_nums = s_ieee802154_txrx_statistic.tx.nums;
float tx_success_ratio = (tx_nums > 0 ? ((float)tx_success_nums / tx_nums) : 0);
float tx_done_ratio = (tx_nums > 0 ? ((float)s_ieee802154_txrx_statistic.tx.done_nums / tx_nums) : 0);
float tx_abort_ratio = (tx_nums > 0 ? ((float)tx_abort_nums / tx_nums) : 0);
float tx_abort_rx_ack_coex_break_ratio = (tx_nums > 0 ? ((float)s_ieee802154_txrx_statistic.tx.abort.rx_ack_coex_break_nums / tx_nums) : 0);
float tx_abort_rx_ack_timeout_ratio = (tx_nums > 0 ? ((float)s_ieee802154_txrx_statistic.tx.abort.rx_ack_timeout_nums / tx_nums) : 0);
float tx_abort_tx_coex_break_ratio = (tx_nums > 0 ? ((float)s_ieee802154_txrx_statistic.tx.abort.tx_coex_break_nums / tx_nums) : 0);
float tx_abort_tx_security_error_ratio = (tx_nums > 0 ? ((float)s_ieee802154_txrx_statistic.tx.abort.tx_security_error_nums / tx_nums) : 0);
float tx_abort_cca_failed_ratio = (tx_nums > 0 ? ((float)s_ieee802154_txrx_statistic.tx.abort.cca_failed_nums / tx_nums) : 0);
float tx_abort_cca_busy_ratio = (tx_nums > 0 ? ((float)s_ieee802154_txrx_statistic.tx.abort.cca_busy_nums / tx_nums) : 0);
uint64_t rx_abort_nums = s_ieee802154_txrx_statistic.rx.abort.tx_ack_coex_break_nums + s_ieee802154_txrx_statistic.rx.abort.sfd_timeout_nums +
s_ieee802154_txrx_statistic.rx.abort.crc_error_nums + s_ieee802154_txrx_statistic.rx.abort.filter_fail_nums +
s_ieee802154_txrx_statistic.rx.abort.no_rss_nums + s_ieee802154_txrx_statistic.rx.abort.rx_coex_break_nums +
s_ieee802154_txrx_statistic.rx.abort.rx_restart_nums + s_ieee802154_txrx_statistic.rx.abort.ed_abort_nums;
uint64_t rx_success_nums = s_ieee802154_txrx_statistic.rx.done_nums - s_ieee802154_txrx_statistic.rx.abort.tx_ack_coex_break_nums;
ESP_LOGW(TAG, "+--------------------+-----------------------------------+--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-10s%-15llu%9.2f%%|%-25s%-15llu%9.2f%%|", "", "Done:", s_ieee802154_txrx_statistic.tx.done_nums, tx_done_ratio*100, "Success:", tx_success_nums, tx_success_ratio*100);
ESP_LOGW(TAG, "+ +-----------------------------------+--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-15llu%9.2f%%|", "", "", "rx_ack_coex_break:", s_ieee802154_txrx_statistic.tx.abort.rx_ack_coex_break_nums, tx_abort_rx_ack_coex_break_ratio*100);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-15llu%9.2f%%|", "", "", "rx_ack_timeout:", s_ieee802154_txrx_statistic.tx.abort.rx_ack_timeout_nums, tx_abort_rx_ack_timeout_ratio*100);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-5s%-15llu|%-10s%-15llu%9.2f%%|%-25s%-15llu%9.2f%%|", "TX:", s_ieee802154_txrx_statistic.tx.nums, "Abort", tx_abort_nums, tx_abort_ratio*100, "tx_coex_break:", s_ieee802154_txrx_statistic.tx.abort.tx_coex_break_nums, tx_abort_tx_coex_break_ratio*100);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-15llu%9.2f%%|", "", "", "tx_security_error:", s_ieee802154_txrx_statistic.tx.abort.tx_security_error_nums, tx_abort_tx_security_error_ratio*100);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-15llu%9.2f%%|", "", "", "cca_failed:", s_ieee802154_txrx_statistic.tx.abort.cca_failed_nums, tx_abort_cca_failed_ratio*100);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-15llu%9.2f%%|", "", "", "cca_busy:", s_ieee802154_txrx_statistic.tx.abort.cca_busy_nums, tx_abort_cca_busy_ratio*100);
ESP_LOGW(TAG, "+--------------------+-----------------------------------+--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-10s%-25llu|%-25s%-25llu|", "", "Done:", s_ieee802154_txrx_statistic.rx.done_nums, "Success:", rx_success_nums);
ESP_LOGW(TAG, "+ +-----------------------------------+--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-25llu|", "", "", "tx_ack_coex_break:", s_ieee802154_txrx_statistic.rx.abort.tx_ack_coex_break_nums);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-25llu|", "", "", "sfd_timeout:", s_ieee802154_txrx_statistic.rx.abort.sfd_timeout_nums);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-25llu|", "", "", "crc_error:", s_ieee802154_txrx_statistic.rx.abort.crc_error_nums);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-10s%-25llu|%-25s%-25llu|", "RX", "Abort", rx_abort_nums, "filter_fail:", s_ieee802154_txrx_statistic.rx.abort.filter_fail_nums);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-25llu|", "", "", "no_rss:", s_ieee802154_txrx_statistic.rx.abort.no_rss_nums);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-25llu|", "", "", "rx_coex_break:", s_ieee802154_txrx_statistic.rx.abort.rx_coex_break_nums);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-25llu|", "", "", "rx_restart:", s_ieee802154_txrx_statistic.rx.abort.rx_restart_nums);
ESP_LOGW(TAG, "+ + +--------------------------------------------------+");
ESP_LOGW(TAG, "|%-20s|%-35s|%-25s%-25llu|", "", "", "ed_abort:", s_ieee802154_txrx_statistic.rx.abort.ed_abort_nums);
ESP_LOGW(TAG, "+--------------------+-----------------------------------+--------------------------------------------------+");
}
#endif // CONFIG_IEEE802154_TXRX_STATISTIC
#endif // CONFIG_IEEE802154_DEBUG

View File

@ -455,7 +455,11 @@ static IRAM_ATTR void isr_handle_tx_abort(void)
next_operation();
break;
case IEEE802154_TX_ABORT_BY_TX_COEX_BREAK:
#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
esp_coex_ieee802154_coex_break_notify();
#endif
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA);
IEEE802154_TX_BREAK_COEX_NUMS_UPDATE();
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_COEXIST);
next_operation();
break;
@ -628,6 +632,7 @@ esp_err_t ieee802154_mac_init(void)
esp_err_t ret = ESP_OK;
modem_clock_module_mac_reset(PERIPH_IEEE802154_MODULE); // reset ieee802154 MAC
ieee802154_pib_init();
IEEE802154_TXRX_STATISTIC_CLEAR();
ieee802154_ll_enable_events(IEEE802154_EVENT_MASK);
#if !CONFIG_IEEE802154_TEST
@ -672,6 +677,7 @@ IEEE802154_STATIC void start_ed(uint32_t duration)
IEEE802154_STATIC void tx_init(const uint8_t *frame)
{
IEEE802154_TX_NUMS_UPDATE();
s_tx_frame = (uint8_t *)frame;
stop_current_operation();
ieee802154_pib_update();

View File

@ -393,3 +393,15 @@ __attribute__((weak)) void esp_ieee802154_timer1_done(void)
{
}
#if CONFIG_IEEE802154_TXRX_STATISTIC
void esp_ieee802154_txrx_statistic_clear(void)
{
ieee802154_txrx_statistic_clear();
}
void esp_ieee802154_txrx_statistic_print(void)
{
ieee802154_txrx_statistic_print();
}
#endif // CONFIG_IEEE802154_TXRX_STATISTIC

View File

@ -586,6 +586,24 @@ esp_err_t esp_ieee802154_set_transmit_security(uint8_t *frame, uint8_t *key, uin
*/
esp_err_t esp_ieee802154_enh_ack_generator(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info, uint8_t* enhack_frame);
/**
* The configurable definitions via Kconfig
*/
#if CONFIG_IEEE802154_TXRX_STATISTIC
/**
* @brief Clear the current IEEE802.15.4 statistic.
*
*/
void esp_ieee802154_txrx_statistic_clear(void);
/**
* @brief Print the current IEEE802.15.4 statistic.
*
*/
void esp_ieee802154_txrx_statistic_print(void);
#endif // CONFIG_IEEE802154_TXRX_STATISTIC
#ifdef __cplusplus
}
#endif

View File

@ -18,6 +18,7 @@ extern "C" {
#define IEEE802154_PROBE(a) do { \
IEEE802154_RECORD_EVENT(a); \
ieee802154_record_abort(a); \
IEEE802154_TXRX_STATISTIC(a); \
} while(0)
#if CONFIG_IEEE802154_RECORD_EVENT
@ -173,6 +174,62 @@ void ieee802154_assert_print(void);
#define IEEE802154_ASSERT(a) assert(a)
#endif // CONFIG_IEEE802154_ASSERT
#if CONFIG_IEEE802154_TXRX_STATISTIC
typedef struct ieee802154_txrx_statistic{
struct {
uint64_t nums;
uint64_t done_nums;
struct {
uint64_t rx_ack_coex_break_nums; // IEEE802154_RX_ACK_ABORT_COEX_CNT_REG
uint64_t rx_ack_timeout_nums; // IEEE802154_RX_ACK_TIMEOUT_CNT_REG
uint64_t tx_coex_break_nums; // IEEE802154_TX_BREAK_COEX_CNT_REG
uint64_t tx_security_error_nums; // IEEE802154_TX_SECURITY_ERROR_CNT_REG
uint64_t cca_failed_nums; // IEEE802154_CCA_FAIL_CNT_REG
uint64_t cca_busy_nums; // IEEE802154_CCA_BUSY_CNT_REG
} abort;
} tx;
struct {
uint64_t done_nums;
struct {
uint64_t sfd_timeout_nums; // IEEE802154_SFD_TIMEOUT_CNT_REG
uint64_t crc_error_nums; // IEEE802154_CRC_ERROR_CNT_REG
uint64_t filter_fail_nums; // IEEE802154_RX_FILTER_FAIL_CNT_REG
uint64_t no_rss_nums; // IEEE802154_NO_RSS_DETECT_CNT_REG
uint64_t rx_coex_break_nums; // IEEE802154_RX_ABORT_COEX_CNT_REG
uint64_t rx_restart_nums; // IEEE802154_RX_RESTART_CNT_REG
uint64_t tx_ack_coex_break_nums; // IEEE802154_TX_ACK_ABORT_COEX_CNT_REG
uint64_t ed_abort_nums; // IEEE802154_ED_ABORT_CNT_REG
} abort;
} rx;
} ieee802154_txrx_statistic_t;
#define IEEE802154_TXRX_STATISTIC_CLEAR() do { \
ieee802154_txrx_statistic_clear();\
} while(0)
#define IEEE802154_TXRX_STATISTIC(a) do { \
ieee802154_txrx_statistic(a);\
} while(0)
#define IEEE802154_TX_NUMS_UPDATE() do { \
ieee802154_tx_nums_update();\
} while(0)
#define IEEE802154_TX_BREAK_COEX_NUMS_UPDATE() do { \
ieee802154_tx_break_coex_nums_update();\
} while(0)
void ieee802154_txrx_statistic_clear(void);
void ieee802154_txrx_statistic_print(void);
void ieee802154_txrx_statistic(ieee802154_ll_events events);
void ieee802154_tx_nums_update(void);
void ieee802154_tx_break_coex_nums_update(void);
#else
#define IEEE802154_TXRX_STATISTIC(a)
#define IEEE802154_TX_NUMS_UPDATE()
#define IEEE802154_TXRX_STATISTIC_CLEAR()
#define IEEE802154_TX_BREAK_COEX_NUMS_UPDATE()
#endif // CONFIG_IEEE802154_TXRX_STATISTIC
// TODO: replace etm code using common interface

View File

@ -18,6 +18,7 @@ if(CONFIG_OPENTHREAD_ENABLED)
"openthread/include/openthread"
"openthread/src"
"openthread/src/core"
"openthread/src/lib"
"openthread/src/lib/hdlc"
"openthread/src/lib/spinel"
"openthread/src/ncp"
@ -31,6 +32,7 @@ if(CONFIG_OPENTHREAD_ENABLED)
"openthread/src/core/common"
"openthread/src/core/crypto"
"openthread/src/core/diags"
"openthread/src/core/instance"
"openthread/src/core/mac"
"openthread/src/core/radio"
"openthread/src/core/thread"
@ -41,7 +43,7 @@ if(CONFIG_OPENTHREAD_ENABLED)
set(exclude_srcs
"openthread/examples/platforms/utils/logging_rtt.c"
"openthread/examples/platforms/utils/soft_source_match_table.c"
"openthread/src/core/common/extension_example.cpp")
"openthread/src/core/instance/extension_example.cpp")
if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD)
list(APPEND src_dirs

View File

@ -163,6 +163,7 @@ menu "OpenThread"
config OPENTHREAD_RCP_SPI
bool "SPI RCP"
select GPIO_CTRL_FUNC_IN_IRAM
help
Select this to enable SPI connection to host.
endchoice

View File

@ -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
*/
@ -69,8 +69,22 @@ void esp_openthread_register_rcp_failure_handler(esp_openthread_rcp_failure_hand
/**
* @brief Deinitializes the conneciton to RCP.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if fail to deinitialize RCP
*
*/
void esp_openthread_rcp_deinit(void);
esp_err_t esp_openthread_rcp_deinit(void);
/**
* @brief Initializes the conneciton to RCP.
*
* @return
* - ESP_OK on success
* - ESP_FAIL if fail to initialize RCP
*
*/
esp_err_t esp_openthread_rcp_init(void);
#ifdef __cplusplus
}

@ -1 +1 @@
Subproject commit 12f563ee490236f7332eb22f568e71c7c1d4a3b7
Subproject commit 648c28e792567bc00602c92e43518c1784599251

@ -1 +1 @@
Subproject commit af5938e389be40650507748272bb6c6b3a2de2cf
Subproject commit 41ef80717f4b757440125932723cc8721ef42f7f

View File

@ -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
*/

View File

@ -14,18 +14,12 @@
namespace esp {
namespace openthread {
class SpiSpinelInterface {
class SpiSpinelInterface : public ot::Spinel::SpinelInterface {
public:
/**
* @brief This constructor of object.
*
* @param[in] callback Callback on frame received
* @param[in] callback_context Callback context
* @param[in] frame_buffer A reference to a `RxFrameBuffer` object.
*
*/
SpiSpinelInterface(ot::Spinel::SpinelInterface::ReceiveFrameCallback callback, void *callback_context,
ot::Spinel::SpinelInterface::RxFrameBuffer &frame_buffer);
SpiSpinelInterface();
/**
* @brief This destructor of the object.
@ -34,24 +28,26 @@ public:
~SpiSpinelInterface(void);
/**
* @brief This method initializes the spinel interface.
* Initializes the interface to the Radio Co-processor (RCP).
*
* @note This method should be called before reading and sending spinel frames to the interface.
*
* @param[in] aCallback Callback on frame received
* @param[in] aCallbackContext Callback context
* @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object.
*
* @retval OT_ERROR_NONE The interface is initialized successfully
* @retval OT_ERROR_ALREADY The interface is already initialized.
* @retval OT_ERROR_FAILED Failed to initialize the interface.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if already initialized
* - ESP_ERR_NO_MEM if allocation has failed
* - ESP_FAIL on failure
*/
esp_err_t Init(const esp_openthread_spi_host_config_t &spi_config);
otError Init(ReceiveFrameCallback aCallback, void *aCallbackContext, RxFrameBuffer &aFrameBuffer);
/**
* @brief This method deinitializes the HDLC interface.
* Deinitializes the interface to the RCP.
*
* @return
* - ESP_OK on success
* - ESP_FAIL on failure
*/
esp_err_t Deinit(void);
void Deinit(void);
/**
* @brief This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
@ -80,20 +76,42 @@ public:
otError WaitForFrame(uint64_t timeout_us);
/**
* This method performs spi processing to the RCP.
* Updates the file descriptor sets with file descriptors used by the radio driver.
*
* @param[in] mainloop The mainloop context
* @param[in,out] aMainloopContext A pointer to the mainloop context.
*
*/
void Process(const void *mainloop);
void UpdateFdSet(void *aMainloopContext);
/**
* This methods updates the mainloop context.
* Performs radio driver processing.
*
* @param[inout] mainloop The mainloop context.
* @param[in] aMainloopContext A pointer to the mainloop context.
*
*/
void Update(void *mainloop);
void Process(const void *aMainloopContext);
/**
* Returns the bus speed between the host and the radio.
*
* @returns Bus speed in bits/second.
*
*/
uint32_t GetBusSpeed(void) const;
/**
* This method is called when RCP failure detected and resets internal states of the interface.
*
*/
otError HardwareReset(void);
/**
* Returns the RCP interface metrics.
*
* @returns The RCP interface metrics.
*
*/
const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; }
/**
* This methods registers the callback for RCP failure.
@ -111,10 +129,33 @@ public:
otError ResetConnection(void) { return OT_ERROR_NONE; }
/**
* This method is called when RCP failure detected and resets internal states of the interface.
* @brief This method enable the spinel interface.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if already initialized
* - ESP_ERR_NO_MEM if allocation has failed
* - ESP_FAIL on failure
*/
otError HardwareReset(void);
esp_err_t Enable(const esp_openthread_spi_host_config_t &spi_config);
/**
* @brief This method disable the spinel interface.
*
* @return
* - ESP_OK on success
* - ESP_FAIL on failure
*/
esp_err_t Disable(void);
/**
* @brief This method should be called after radio is initialized.
*
* @return
* - ESP_OK on success
* - ESP_FAIL on failure
*/
esp_err_t AfterRadioInit(void);
private:
static constexpr uint8_t kSPIFrameHeaderSize = 5;
@ -130,14 +171,16 @@ private:
int m_event_fd;
volatile uint16_t m_pending_data_len;
ot::Spinel::SpinelInterface::ReceiveFrameCallback m_receiver_frame_callback;
ReceiveFrameCallback m_receiver_frame_callback;
void *m_receiver_frame_context;
ot::Spinel::SpinelInterface::RxFrameBuffer &m_receive_frame_buffer;
RxFrameBuffer *m_receive_frame_buffer;
bool m_has_pending_device_frame;
spi_device_handle_t m_device;
esp_openthread_rcp_failure_handler mRcpFailureHandler;
otRcpInterfaceMetrics mInterfaceMetrics;
};
} // namespace openthread

View File

@ -0,0 +1,50 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "esp_openthread.h"
#include "esp_openthread_types.h"
#include "hal/uart_types.h"
#include "lib/spinel/spinel_interface.hpp"
#include "lib/hdlc/hdlc.hpp"
#include "openthread/error.h"
namespace esp {
namespace openthread {
/**
* This class defines an template to adapt both UartSpinelInterface and SpiSpinelInterface.
*
*/
template <typename InterfaceType> class SpinelInterfaceAdapter {
public:
/**
* @brief This constructor of object.
*/
SpinelInterfaceAdapter(void) {}
/**
* @brief This destructor of the object.
*
*/
~SpinelInterfaceAdapter(void) {}
/**
* @brief This method return the underlying spinel interface.
*
* @return The underlying spinel interface.
*
*/
InterfaceType &GetSpinelInterface(void) { return mSpinelInterface; }
private:
InterfaceType mSpinelInterface;
};
} // namespace openthread
} // namespace esp

View File

@ -21,18 +21,12 @@ namespace openthread {
* This class defines an UART interface to the Radio Co-processor (RCP).
*
*/
class UartSpinelInterface {
class UartSpinelInterface : public ot::Spinel::SpinelInterface {
public:
/**
* @brief This constructor of object.
*
* @param[in] callback Callback on frame received
* @param[in] callback_context Callback context
* @param[in] frame_buffer A reference to a `RxFrameBuffer` object.
*
*/
UartSpinelInterface(ot::Spinel::SpinelInterface::ReceiveFrameCallback callback, void *callback_context,
ot::Spinel::SpinelInterface::RxFrameBuffer &frame_buffer);
UartSpinelInterface(void);
/**
* @brief This destructor of the object.
@ -41,65 +35,92 @@ public:
~UartSpinelInterface(void);
/**
* @brief This method initializes the HDLC interface.
* Initializes the interface to the Radio Co-processor (RCP).
*
* @note This method should be called before reading and sending spinel frames to the interface.
*
* @param[in] aCallback Callback on frame received
* @param[in] aCallbackContext Callback context
* @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object.
*
* @retval OT_ERROR_NONE The interface is initialized successfully
* @retval OT_ERROR_ALREADY The interface is already initialized.
* @retval OT_ERROR_FAILED Failed to initialize the interface.
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if allocation has failed
* - ESP_ERROR on failure
*/
esp_err_t Init(const esp_openthread_uart_config_t &radio_uart_config);
otError Init(ReceiveFrameCallback aCallback, void *aCallbackContext, RxFrameBuffer &aFrameBuffer);
/**
* @brief This method deinitializes the HDLC interface.
* Deinitializes the interface to the RCP.
*
*/
esp_err_t Deinit(void);
void Deinit(void);
/**
* @brief This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
* Encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
*
* @note This is blocking call, i.e., if the socket is not writable, this method waits for it to become writable
* for up to `kMaxWaitTime` interval.
* @param[in] aFrame A pointer to buffer containing the spinel frame to send.
* @param[in] aLength The length (number of bytes) in the frame.
*
* @param[in] frame A pointer to buffer containing the spinel frame to send.
* @param[in] length The length (number of bytes) in the frame.
*
* @return
* -OT_ERROR_NONE Successfully encoded and sent the spinel frame.
* -OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame.
* -OT_ERROR_FAILED Failed to send due to socket not becoming writable within `kMaxWaitTime`.
* @retval OT_ERROR_NONE Successfully encoded and sent the spinel frame.
* @retval OT_ERROR_BUSY Failed due to another operation is on going.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame.
* @retval OT_ERROR_FAILED Failed to call the SPI driver to send the frame.
*
*/
otError SendFrame(const uint8_t *frame, uint16_t length);
otError SendFrame(const uint8_t *aFrame, uint16_t aLength);
/**
* This method waits for receiving part or all of spinel frame within specified timeout.
* Waits for receiving part or all of spinel frame within specified interval.
*
* @param[in] timeout_us The timeout value in microseconds.
* @param[in] aTimeout The timeout value in microseconds.
*
* @return
* -OT_ERROR_NONE Part or all of spinel frame is received.
* -OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p timeout_us.
* @retval OT_ERROR_NONE Part or all of spinel frame is received.
* @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout.
*
*/
otError WaitForFrame(uint64_t timeout_us);
otError WaitForFrame(uint64_t aTimeoutUs);
/**
* This method performs uart processing to the RCP.
* Updates the file descriptor sets with file descriptors used by the radio driver.
*
* @param[in] mainloop The mainloop context
* @param[in,out] aMainloopContext A pointer to the mainloop context.
*
*/
void Process(const void *mainloop);
void UpdateFdSet(void *aMainloopContext);
/**
* This methods updates the mainloop context.
* Performs radio driver processing.
*
* @param[inout] mainloop The mainloop context.
* @param[in] aMainloopContext A pointer to the mainloop context.
*
*/
void Update(void *mainloop);
void Process(const void *aMainloopContext);
/**
* Returns the bus speed between the host and the radio.
*
* @returns Bus speed in bits/second.
*
*/
uint32_t GetBusSpeed(void) const;
/**
* Hardware resets the RCP.
*
* @retval OT_ERROR_NONE Successfully reset the RCP.
* @retval OT_ERROR_NOT_IMPLEMENT The hardware reset is not implemented.
*
*/
otError HardwareReset(void);
/**
* Returns the RCP interface metrics.
*
* @returns The RCP interface metrics.
*
*/
const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; }
/**
* This methods registers the callback for RCP failure.
@ -109,12 +130,6 @@ public:
*/
void RegisterRcpFailureHandler(esp_openthread_rcp_failure_handler handler) { mRcpFailureHandler = handler; }
/**
* This method is called when RCP failure detected and resets internal states of the interface.
*
*/
otError HardwareReset(void);
/**
* This method is called when RCP is reset to recreate the connection with it.
* Intentionally empty.
@ -122,14 +137,25 @@ public:
*/
otError ResetConnection(void) { return OT_ERROR_NONE; }
private:
enum {
/**
* Maximum spinel frame size.
*
*/
kMaxFrameSize = ot::Spinel::SpinelInterface::kMaxFrameSize,
/**
* @brief This method enable the HDLC interface.
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if allocation has failed
* - ESP_ERROR on failure
*/
esp_err_t Enable(const esp_openthread_uart_config_t &radio_uart_config);
/**
* @brief This method disable the HDLC interface.
*
*/
esp_err_t Disable(void);
private:
enum {
/**
* Maximum wait time in Milliseconds for socket to become writable (see `SendFrame`).
*
@ -152,9 +178,9 @@ private:
static void HandleHdlcFrame(void *context, otError error);
void HandleHdlcFrame(otError error);
ot::Spinel::SpinelInterface::ReceiveFrameCallback m_receiver_frame_callback;
ReceiveFrameCallback m_receiver_frame_callback;
void *m_receiver_frame_context;
ot::Spinel::SpinelInterface::RxFrameBuffer &m_receive_frame_buffer;
RxFrameBuffer *m_receive_frame_buffer;
ot::Hdlc::Decoder m_hdlc_decoder;
uint8_t *m_uart_rx_buffer;
@ -162,6 +188,8 @@ private:
esp_openthread_uart_config_t m_uart_config;
int m_uart_fd;
otRcpInterfaceMetrics mInterfaceMetrics;
// Non-copyable, intentionally not implemented.
UartSpinelInterface(const UartSpinelInterface &);
UartSpinelInterface &operator=(const UartSpinelInterface &);

View File

@ -20,7 +20,7 @@
#include "esp_partition.h"
#include "common/code_utils.hpp"
#include "common/logging.hpp"
#include "core/common/instance.hpp"
#include "core/instance/instance.hpp"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "openthread/cli.h"

View File

@ -13,6 +13,7 @@
#include "esp_openthread_platform.h"
#include "esp_openthread_types.h"
#include "esp_system.h"
#include "esp_spinel_interface.hpp"
#include "esp_spi_spinel_interface.hpp"
#include "esp_uart_spinel_interface.hpp"
#include "openthread-core-config.h"
@ -20,41 +21,100 @@
#include "lib/spinel/spinel.h"
#include "openthread/platform/diag.h"
#include "openthread/platform/radio.h"
#include "platform/exit_code.h"
using ot::Spinel::RadioSpinel;
using esp::openthread::SpinelInterfaceAdapter;
#if CONFIG_OPENTHREAD_RADIO_SPINEL_UART
#if CONFIG_OPENTHREAD_RADIO_SPINEL_UART // CONFIG_OPENTHREAD_RADIO_SPINEL_UART
using esp::openthread::UartSpinelInterface;
static RadioSpinel<UartSpinelInterface> s_radio;
static SpinelInterfaceAdapter<UartSpinelInterface> s_spinel_interface;
#else // CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
using esp::openthread::SpiSpinelInterface;
static RadioSpinel<SpiSpinelInterface> s_radio;
#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART
static SpinelInterfaceAdapter<SpiSpinelInterface> s_spinel_interface;
#endif
static RadioSpinel s_radio;
static const char *radiospinel_workflow = "radio_spinel";
static const esp_openthread_radio_config_t *s_esp_openthread_radio_config = NULL;
static void esp_openthread_radio_config_set(const esp_openthread_radio_config_t *config)
{
s_esp_openthread_radio_config = config;
}
static const esp_openthread_radio_config_t *esp_openthread_radio_config_get(void)
{
return s_esp_openthread_radio_config;
}
esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *config)
{
#if CONFIG_OPENTHREAD_RADIO_SPINEL_UART
ESP_RETURN_ON_ERROR(s_radio.GetSpinelInterface().Init(config->radio_config.radio_uart_config), OT_PLAT_LOG_TAG,
spinel_iid_t iidList[ot::Spinel::kSpinelHeaderMaxNumIid];
iidList[0] = 0;
ot::Spinel::RadioSpinelCallbacks callbacks;
#if CONFIG_OPENTHREAD_DIAG
callbacks.mDiagReceiveDone = otPlatDiagRadioReceiveDone;
callbacks.mDiagTransmitDone = otPlatDiagRadioTransmitDone;
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
callbacks.mEnergyScanDone = otPlatRadioEnergyScanDone;
callbacks.mReceiveDone = otPlatRadioReceiveDone;
callbacks.mTransmitDone = otPlatRadioTxDone;
callbacks.mTxStarted = otPlatRadioTxStarted;
s_radio.SetCallbacks(callbacks);
esp_openthread_radio_config_set(&config->radio_config);
#if CONFIG_OPENTHREAD_RADIO_SPINEL_UART // CONFIG_OPENTHREAD_RADIO_SPINEL_UART
ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().Enable(config->radio_config.radio_uart_config), OT_PLAT_LOG_TAG,
"Spinel interface init falied");
#else // CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
ESP_RETURN_ON_ERROR(s_radio.GetSpinelInterface().Init(config->radio_config.radio_spi_config), OT_PLAT_LOG_TAG,
#else // CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().Enable(config->radio_config.radio_spi_config), OT_PLAT_LOG_TAG,
"Spinel interface init failed");
#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART
s_radio.Init(/*reset_radio=*/true, /*skip_rcp_compatibility_check=*/false);
#endif
s_radio.Init(s_spinel_interface.GetSpinelInterface(), /*reset_radio=*/true, /*skip_rcp_compatibility_check=*/false, iidList, ot::Spinel::kSpinelHeaderMaxNumIid);
#if CONFIG_OPENTHREAD_RADIO_SPINEL_SPI // CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().AfterRadioInit(), OT_PLAT_LOG_TAG, "Spinel interface init falied");
#endif
return esp_openthread_platform_workflow_register(&esp_openthread_radio_update, &esp_openthread_radio_process,
radiospinel_workflow);
}
void esp_openthread_register_rcp_failure_handler(esp_openthread_rcp_failure_handler handler)
{
s_radio.GetSpinelInterface().RegisterRcpFailureHandler(handler);
s_spinel_interface.GetSpinelInterface().RegisterRcpFailureHandler(handler);
}
void esp_openthread_rcp_deinit(void)
esp_err_t esp_openthread_rcp_deinit(void)
{
s_radio.GetSpinelInterface().Deinit();
ESP_RETURN_ON_FALSE(otThreadGetDeviceRole(esp_openthread_get_instance()) == OT_DEVICE_ROLE_DISABLED, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "Thread is enabled, failed to deinitialize RCP");
ESP_RETURN_ON_FALSE(!otIp6IsEnabled(esp_openthread_get_instance()), ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OT interface is up, failed to deinitialize RCP");
if (s_radio.IsEnabled()) {
ESP_RETURN_ON_FALSE(s_radio.Sleep() == OT_ERROR_NONE, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "Radio fails to sleep");
ESP_RETURN_ON_FALSE(s_radio.Disable() == OT_ERROR_NONE, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "Fail to disable radio");
}
ESP_RETURN_ON_FALSE(s_spinel_interface.GetSpinelInterface().Disable() == OT_ERROR_NONE, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "Fail to deinitialize UART");
esp_openthread_platform_workflow_unregister(radiospinel_workflow);
return ESP_OK;
}
esp_err_t esp_openthread_rcp_init(void)
{
const esp_openthread_radio_config_t *radio_config = esp_openthread_radio_config_get();
#if CONFIG_OPENTHREAD_RADIO_SPINEL_UART
ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().Enable(radio_config->radio_uart_config), OT_PLAT_LOG_TAG,
"Spinel interface init falied");
#else // CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().Enable(radio_config->radio_spi_config), OT_PLAT_LOG_TAG,
"Spinel interface init failed");
#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART
ESP_RETURN_ON_FALSE(s_radio.Enable(esp_openthread_get_instance()) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG, "Fail to enable radio");
s_radio.RestoreProperties();
return esp_openthread_platform_workflow_register(&esp_openthread_radio_update, &esp_openthread_radio_process,
radiospinel_workflow);
}
void esp_openthread_radio_deinit(void)
@ -72,7 +132,7 @@ esp_err_t esp_openthread_radio_process(otInstance *instance, const esp_openthrea
void esp_openthread_radio_update(esp_openthread_mainloop_context_t *mainloop)
{
s_radio.GetSpinelInterface().Update((void *)mainloop);
s_spinel_interface.GetSpinelInterface().UpdateFdSet((void *)mainloop);
}
void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)

View File

@ -17,10 +17,10 @@
#include "esp_attr.h"
#include "esp_check.h"
#include "esp_err.h"
#include "esp_heap_caps.h"
#include "esp_openthread_common_macro.h"
#include "esp_openthread_task_queue.h"
#include "esp_openthread_types.h"
#include "esp_rom_sys.h"
#include <stdint.h>
#include <string.h>
#include "driver/gpio.h"
@ -33,37 +33,38 @@
static const char *SPI_SLAVE_TAG = "spi_slave";
static void *s_context = NULL;
static uint8_t *s_prev_output_buf;
static uint16_t s_prev_output_len;
static uint8_t *s_prev_input_buf;
static uint16_t s_prev_input_len;
static uint8_t *s_output_buf;
static uint16_t s_output_len;
static uint8_t *s_input_buf;
static uint16_t s_input_len;
static bool s_request_transaction = false;
static esp_openthread_spi_slave_config_t s_spi_config;
static otPlatSpiSlaveTransactionProcessCallback s_process_callback = NULL;
static otPlatSpiSlaveTransactionCompleteCallback s_complete_callback = NULL;
static spi_slave_transaction_t s_spi_transaction;
typedef struct {
uint16_t output_buf_len;
uint16_t input_buf_len;
} pending_transaction_t;
static otPlatSpiSlaveTransactionProcessCallback s_process_callback = NULL;
static otPlatSpiSlaveTransactionCompleteCallback s_complete_callback = NULL;
static DRAM_ATTR esp_openthread_spi_slave_config_t *s_spi_config;
static DRAM_ATTR spi_slave_transaction_t *s_spi_transaction;
static DRAM_ATTR pending_transaction_t *s_pending_transaction;
static void IRAM_ATTR handle_spi_setup_done(spi_slave_transaction_t *trans)
{
if (s_request_transaction) {
gpio_set_level(s_spi_config.intr_pin, 0);
gpio_set_level(s_spi_config->intr_pin, 0);
}
}
static void IRAM_ATTR handle_spi_transaction_done(spi_slave_transaction_t *trans)
{
gpio_set_level(s_spi_config.intr_pin, 1);
pending_transaction_t *pending_transaction = (pending_transaction_t *)&(trans->user);
gpio_set_level(s_spi_config->intr_pin, 1);
pending_transaction_t *pending_transaction = (pending_transaction_t *)(trans->user);
trans->trans_len /= CHAR_BIT;
if (s_complete_callback &&
s_complete_callback(s_context, (uint8_t *)trans->tx_buffer, pending_transaction->output_buf_len,
s_complete_callback(s_context, (void*)trans->tx_buffer, pending_transaction->output_buf_len,
trans->rx_buffer, pending_transaction->input_buf_len, trans->trans_len)) {
esp_openthread_task_queue_post(s_process_callback, s_context);
}
@ -72,23 +73,38 @@ static void IRAM_ATTR handle_spi_transaction_done(spi_slave_transaction_t *trans
esp_err_t esp_openthread_host_rcp_spi_init(const esp_openthread_platform_config_t *config)
{
s_spi_config = config->host_config.spi_slave_config;
s_spi_config = heap_caps_malloc(sizeof(esp_openthread_spi_slave_config_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
ESP_RETURN_ON_FALSE(s_spi_config != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG,
"failed to allocate memory for SPI transaction on internal heap");
memcpy(s_spi_config, &(config->host_config.spi_slave_config), sizeof(esp_openthread_spi_slave_config_t));
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1 << s_spi_config.intr_pin),
.pin_bit_mask = (1 << s_spi_config->intr_pin),
};
ESP_RETURN_ON_ERROR(gpio_config(&io_conf), OT_PLAT_LOG_TAG, "fail to configure SPI gpio");
gpio_set_pull_mode(s_spi_config.bus_config.mosi_io_num, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(s_spi_config.bus_config.sclk_io_num, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(s_spi_config.slave_config.spics_io_num, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(s_spi_config->bus_config.mosi_io_num, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(s_spi_config->bus_config.sclk_io_num, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(s_spi_config->slave_config.spics_io_num, GPIO_PULLUP_ONLY);
s_spi_transaction = heap_caps_malloc(sizeof(spi_slave_transaction_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
s_pending_transaction = heap_caps_malloc(sizeof(pending_transaction_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (s_spi_transaction == NULL || s_pending_transaction == NULL) {
heap_caps_free(s_spi_config);
heap_caps_free(s_spi_transaction);
heap_caps_free(s_pending_transaction);
ESP_LOGE(OT_PLAT_LOG_TAG, "failed to allocate memory for SPI transaction on internal heap");
return ESP_ERR_NO_MEM;
}
s_spi_transaction->user = (void *)s_pending_transaction;
/* Initialize SPI slave interface */
s_spi_config.slave_config.post_setup_cb = handle_spi_setup_done;
s_spi_config.slave_config.post_trans_cb = handle_spi_transaction_done;
ESP_RETURN_ON_ERROR(spi_slave_initialize(s_spi_config.host_device, &s_spi_config.bus_config,
&s_spi_config.slave_config, SPI_DMA_CH_AUTO),
s_spi_config->slave_config.post_setup_cb = handle_spi_setup_done;
s_spi_config->slave_config.post_trans_cb = handle_spi_transaction_done;
ESP_RETURN_ON_ERROR(spi_slave_initialize(s_spi_config->host_device, &s_spi_config->bus_config,
&s_spi_config->slave_config, SPI_DMA_CH_AUTO),
OT_PLAT_LOG_TAG, "fail to initialize SPI slave");
return ESP_OK;
@ -96,9 +112,15 @@ esp_err_t esp_openthread_host_rcp_spi_init(const esp_openthread_platform_config_
void esp_openthread_spi_slave_deinit(void)
{
spi_slave_free(s_spi_config.host_device);
s_spi_config.slave_config.post_setup_cb = NULL;
s_spi_config.slave_config.post_trans_cb = NULL;
spi_slave_free(s_spi_config->host_device);
s_spi_config->slave_config.post_setup_cb = NULL;
s_spi_config->slave_config.post_trans_cb = NULL;
heap_caps_free(s_spi_config);
heap_caps_free(s_spi_transaction);
heap_caps_free(s_pending_transaction);
s_spi_config = NULL;
s_spi_transaction = NULL;
s_pending_transaction = NULL;
return;
}
@ -115,43 +137,38 @@ otError IRAM_ATTR otPlatSpiSlavePrepareTransaction(uint8_t *aOutputBuf, uint16_t
uint16_t aInputBufLen, bool aRequestTransactionFlag)
{
esp_err_t trans_state = ESP_OK;
pending_transaction_t *pending_transaction = NULL;
if (aOutputBuf == NULL) {
aOutputBuf = s_prev_output_buf;
aOutputBufLen = s_prev_output_len;
uint16_t trans_length = 0;
if (aOutputBuf != NULL) {
s_output_buf = aOutputBuf;
s_output_len = aOutputBufLen;
}
if (aInputBuf == NULL) {
aInputBuf = s_prev_input_buf;
aInputBufLen = s_prev_input_len;
if (aInputBuf != NULL) {
s_input_buf = aInputBuf;
s_input_len = aInputBufLen;
}
s_prev_output_buf = aOutputBuf;
s_prev_output_len = aOutputBufLen;
s_prev_input_buf = aInputBuf;
s_prev_input_len = aInputBufLen;
s_spi_transaction.length = aOutputBufLen > aInputBufLen ? aOutputBufLen : aInputBufLen;
s_spi_transaction.length *= CHAR_BIT;
s_spi_transaction.rx_buffer = aInputBuf;
s_spi_transaction.tx_buffer = aOutputBuf;
assert(sizeof(s_spi_transaction.user) >= sizeof(pending_transaction_t));
pending_transaction = (pending_transaction_t *)&(s_spi_transaction.user);
pending_transaction->input_buf_len = aInputBufLen;
pending_transaction->output_buf_len = aOutputBufLen;
s_spi_transaction.user = pending_transaction;
s_request_transaction = aRequestTransactionFlag;
if ((gpio_get_level(s_spi_config.slave_config.spics_io_num) == 0)) {
trans_length = s_output_len > s_input_len ? s_output_len : s_input_len;
trans_length *= CHAR_BIT;
if ((gpio_get_level(s_spi_config->slave_config.spics_io_num) == 0)) {
ESP_EARLY_LOGE(SPI_SLAVE_TAG, "SPI busy");
return OT_ERROR_BUSY;
}
s_spi_transaction->length = trans_length;
s_spi_transaction->rx_buffer = s_input_buf;
s_spi_transaction->tx_buffer = s_output_buf;
pending_transaction_t *pending_transaction = (pending_transaction_t *)s_spi_transaction->user;
pending_transaction->input_buf_len = s_input_len;
pending_transaction->output_buf_len = s_output_len;
s_request_transaction = aRequestTransactionFlag;
if (xPortCanYield()) {
spi_slave_queue_reset(s_spi_config.host_device);
trans_state = spi_slave_queue_trans(s_spi_config.host_device, &s_spi_transaction, 0);
spi_slave_queue_reset(s_spi_config->host_device);
trans_state = spi_slave_queue_trans(s_spi_config->host_device, s_spi_transaction, 0);
} else {
spi_slave_queue_reset_isr(s_spi_config.host_device);
trans_state = spi_slave_queue_trans_isr(s_spi_config.host_device, &s_spi_transaction);
spi_slave_queue_reset_isr(s_spi_config->host_device);
trans_state = spi_slave_queue_trans_isr(s_spi_config->host_device, s_spi_transaction);
}
if (trans_state == ESP_OK) {

View File

@ -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
*/
@ -57,6 +57,7 @@ typedef struct {
TaskHandle_t source_task;
struct udp_pcb *pcb;
uint8_t netif_index;
esp_err_t err;
} udp_bind_netif_task_t;
typedef struct {
@ -255,7 +256,6 @@ otError otPlatUdpBind(otUdpSocket *udp_socket)
static void udp_bind_netif_task(void *ctx)
{
udp_bind_netif_task_t *task = (udp_bind_netif_task_t *)ctx;
udp_bind_netif(task->pcb, netif_get_by_index(task->netif_index));
xTaskNotifyGive(task->source_task);
}
@ -276,16 +276,20 @@ static uint8_t get_netif_index(otNetifIdentifier netif_identifier)
otError otPlatUdpBindToNetif(otUdpSocket *udp_socket, otNetifIdentifier netif_identifier)
{
otError err = OT_ERROR_NONE;
udp_bind_netif_task_t task = {
.source_task = xTaskGetCurrentTaskHandle(),
.pcb = (struct udp_pcb *)udp_socket->mHandle,
.netif_index = get_netif_index(netif_identifier),
.err = ESP_OK,
};
tcpip_callback(udp_bind_netif_task, &task);
wait_for_task_notification();
return OT_ERROR_NONE;
if (task.err != ESP_OK) {
err = OT_ERROR_FAILED;
}
return err;
}
static void udp_connect_task(void *ctx)
@ -424,14 +428,20 @@ exit:
static void udp_multicast_join_leave_task(void *ctx)
{
udp_multicast_join_leave_task_t *task = (udp_multicast_join_leave_task_t *)ctx;
struct netif *target = netif_get_by_index(task->netif_index);
if (task->is_join) {
if (mld6_joingroup_netif(netif_get_by_index(task->netif_index), &task->addr) != ERR_OK) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to join multicast group");
}
if (target == NULL) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to %s multicast group, index%d netif is not ready",
task->is_join ? "join" : "leave", task->netif_index);
} else {
if (mld6_leavegroup_netif(netif_get_by_index(task->netif_index), &task->addr) != ERR_OK) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to leave multicast group");
if (task->is_join) {
if (mld6_joingroup_netif(target, &task->addr) != ERR_OK) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to join multicast group");
}
} else {
if (mld6_leavegroup_netif(target, &task->addr) != ERR_OK) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to leave multicast group");
}
}
}
free(task);

View File

@ -25,17 +25,39 @@ using ot::Spinel::SpinelInterface;
namespace esp {
namespace openthread {
SpiSpinelInterface::SpiSpinelInterface(SpinelInterface::ReceiveFrameCallback callback, void *callback_context,
SpinelInterface::RxFrameBuffer &frame_buffer)
SpiSpinelInterface::SpiSpinelInterface(void)
: m_event_fd(-1)
, m_receiver_frame_callback(callback)
, m_receiver_frame_context(callback_context)
, m_receive_frame_buffer(frame_buffer)
, m_receiver_frame_callback(nullptr)
, m_receiver_frame_context(nullptr)
, m_receive_frame_buffer(nullptr)
, mRcpFailureHandler(nullptr)
{
}
esp_err_t SpiSpinelInterface::Init(const esp_openthread_spi_host_config_t &spi_config)
SpiSpinelInterface::~SpiSpinelInterface(void)
{
Deinit();
}
otError SpiSpinelInterface::Init(ReceiveFrameCallback aCallback, void *aCallbackContext, RxFrameBuffer &aFrameBuffer)
{
otError error = OT_ERROR_NONE;
m_receiver_frame_callback = aCallback;
m_receiver_frame_context = aCallbackContext;
m_receive_frame_buffer = &aFrameBuffer;
return error;
}
void SpiSpinelInterface::Deinit(void)
{
m_receiver_frame_callback = nullptr;
m_receiver_frame_context = nullptr;
m_receive_frame_buffer = nullptr;
}
esp_err_t SpiSpinelInterface::Enable(const esp_openthread_spi_host_config_t &spi_config)
{
ESP_RETURN_ON_FALSE(m_event_fd < 0, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "event fd was initialized");
m_spi_config = spi_config;
@ -62,10 +84,16 @@ esp_err_t SpiSpinelInterface::Init(const esp_openthread_spi_host_config_t &spi_c
ESP_LOGI(OT_PLAT_LOG_TAG, "spinel SPI interface initialization completed");
return ESP_OK;
}
esp_err_t SpiSpinelInterface::AfterRadioInit(void)
{
return ConductSPITransaction(true, 0, 0);
}
esp_err_t SpiSpinelInterface::Deinit(void)
esp_err_t SpiSpinelInterface::Disable(void)
{
if (m_event_fd >= 0) {
close(m_event_fd);
@ -80,11 +108,6 @@ esp_err_t SpiSpinelInterface::Deinit(void)
return ESP_OK;
}
SpiSpinelInterface::~SpiSpinelInterface(void)
{
Deinit();
}
otError SpiSpinelInterface::SendFrame(const uint8_t *frame, uint16_t length)
{
ESP_RETURN_ON_FALSE(frame, OT_ERROR_INVALID_ARGS, OT_PLAT_LOG_TAG, "empty frame");
@ -113,13 +136,13 @@ esp_err_t SpiSpinelInterface::ConductSPITransaction(bool reset, uint16_t tx_data
tx_frame.SetHeaderAcceptLen(rx_data_size);
uint8_t *rx_buffer;
otError err = m_receive_frame_buffer.SetSkipLength(kSPIFrameHeaderSize);
otError err = m_receive_frame_buffer->SetSkipLength(kSPIFrameHeaderSize);
ESP_RETURN_ON_FALSE(err == OT_ERROR_NONE, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG, "buffer space is insufficient");
rx_buffer = m_receive_frame_buffer.GetFrame() - kSPIFrameHeaderSize;
if (m_receive_frame_buffer.GetFrameMaxLength() < rx_data_size) {
rx_data_size = m_receive_frame_buffer.GetFrameMaxLength();
rx_buffer = m_receive_frame_buffer->GetFrame() - kSPIFrameHeaderSize;
if (m_receive_frame_buffer->GetFrameMaxLength() < rx_data_size) {
rx_data_size = m_receive_frame_buffer->GetFrameMaxLength();
}
uint16_t data_size = tx_data_size > rx_data_size ? tx_data_size : rx_data_size;
data_size += kSPIFrameHeaderSize;
@ -143,7 +166,7 @@ esp_err_t SpiSpinelInterface::ConductSPITransaction(bool reset, uint16_t tx_data
if (rx_frame.IsResetFlagSet()) {
ESP_LOGW(OT_PLAT_LOG_TAG, "RCP Reset");
m_receive_frame_buffer.DiscardFrame();
m_receive_frame_buffer->DiscardFrame();
return ESP_OK;
}
if (rx_frame.GetHeaderDataLen() == 0 && rx_frame.GetHeaderAcceptLen() == 0) {
@ -156,16 +179,16 @@ esp_err_t SpiSpinelInterface::ConductSPITransaction(bool reset, uint16_t tx_data
if (gpio_get_level(m_spi_config.intr_pin) == 1) {
m_pending_data_len = 0;
}
if (m_receive_frame_buffer.SetLength(rx_frame.GetHeaderDataLen()) != OT_ERROR_NONE) {
if (m_receive_frame_buffer->SetLength(rx_frame.GetHeaderDataLen()) != OT_ERROR_NONE) {
ESP_LOGW(OT_PLAT_LOG_TAG, "insufficient buffer space to hold a frame of length %d...",
rx_frame.GetHeaderDataLen());
m_receive_frame_buffer.DiscardFrame();
m_receive_frame_buffer->DiscardFrame();
return ESP_ERR_NO_MEM;
}
m_receiver_frame_callback(m_receiver_frame_context);
} else {
m_pending_data_len = 0;
m_receive_frame_buffer.DiscardFrame();
m_receive_frame_buffer->DiscardFrame();
}
m_pending_data_len = 0;
@ -180,26 +203,26 @@ void SpiSpinelInterface::GpioIntrHandler(void *arg)
write(instance->m_event_fd, &event, sizeof(event));
}
void SpiSpinelInterface::Update(void *mainloop)
void SpiSpinelInterface::UpdateFdSet(void *aMainloopContext)
{
if (m_pending_data_len > 0) {
((esp_openthread_mainloop_context_t *)mainloop)->timeout.tv_sec = 0;
((esp_openthread_mainloop_context_t *)mainloop)->timeout.tv_usec = 0;
((esp_openthread_mainloop_context_t *)aMainloopContext)->timeout.tv_sec = 0;
((esp_openthread_mainloop_context_t *)aMainloopContext)->timeout.tv_usec = 0;
}
FD_SET(m_event_fd, &((esp_openthread_mainloop_context_t *)mainloop)->read_fds);
FD_SET(m_event_fd, &((esp_openthread_mainloop_context_t *)mainloop)->error_fds);
if (m_event_fd > ((esp_openthread_mainloop_context_t *)mainloop)->max_fd) {
((esp_openthread_mainloop_context_t *)mainloop)->max_fd = m_event_fd;
FD_SET(m_event_fd, &((esp_openthread_mainloop_context_t *)aMainloopContext)->read_fds);
FD_SET(m_event_fd, &((esp_openthread_mainloop_context_t *)aMainloopContext)->error_fds);
if (m_event_fd > ((esp_openthread_mainloop_context_t *)aMainloopContext)->max_fd) {
((esp_openthread_mainloop_context_t *)aMainloopContext)->max_fd = m_event_fd;
}
}
void SpiSpinelInterface::Process(const void *mainloop)
void SpiSpinelInterface::Process(const void *aMainloopContext)
{
if (FD_ISSET(m_event_fd, &((esp_openthread_mainloop_context_t *)mainloop)->error_fds)) {
if (FD_ISSET(m_event_fd, &((esp_openthread_mainloop_context_t *)aMainloopContext)->error_fds)) {
ESP_LOGE(OT_PLAT_LOG_TAG, "SPI INTR GPIO error event");
return;
}
if (FD_ISSET(m_event_fd, &((esp_openthread_mainloop_context_t *)mainloop)->read_fds)) {
if (FD_ISSET(m_event_fd, &((esp_openthread_mainloop_context_t *)aMainloopContext)->read_fds)) {
uint64_t event;
read(m_event_fd, &event, sizeof(event));
m_pending_data_len = SpinelInterface::kMaxFrameSize;
@ -249,5 +272,10 @@ otError SpiSpinelInterface::HardwareReset(void)
return OT_ERROR_NONE;
}
uint32_t SpiSpinelInterface::GetBusSpeed(void) const
{
return m_spi_config.spi_device.clock_speed_hz;
}
} // namespace openthread
} // namespace esp

View File

@ -27,13 +27,10 @@
namespace esp {
namespace openthread {
UartSpinelInterface::UartSpinelInterface(ot::Spinel::SpinelInterface::ReceiveFrameCallback callback,
void *callback_context,
ot::Spinel::SpinelInterface::RxFrameBuffer &frame_buffer)
: m_receiver_frame_callback(callback)
, m_receiver_frame_context(callback_context)
, m_receive_frame_buffer(frame_buffer)
, m_hdlc_decoder(frame_buffer, HandleHdlcFrame, this)
UartSpinelInterface::UartSpinelInterface(void)
: m_receiver_frame_callback(nullptr)
, m_receiver_frame_context(nullptr)
, m_receive_frame_buffer(nullptr)
, m_uart_fd(-1)
, mRcpFailureHandler(nullptr)
{
@ -41,9 +38,29 @@ UartSpinelInterface::UartSpinelInterface(ot::Spinel::SpinelInterface::ReceiveFra
UartSpinelInterface::~UartSpinelInterface(void)
{
Deinit();
}
esp_err_t UartSpinelInterface::Init(const esp_openthread_uart_config_t &radio_uart_config)
otError UartSpinelInterface::Init(ReceiveFrameCallback aCallback, void *aCallbackContext, RxFrameBuffer &aFrameBuffer)
{
otError error = OT_ERROR_NONE;
m_receiver_frame_callback = aCallback;
m_receiver_frame_context = aCallbackContext;
m_receive_frame_buffer = &aFrameBuffer;
m_hdlc_decoder.Init(aFrameBuffer, HandleHdlcFrame, this);
return error;
}
void UartSpinelInterface::Deinit(void)
{
m_receiver_frame_callback = nullptr;
m_receiver_frame_context = nullptr;
m_receive_frame_buffer = nullptr;
}
esp_err_t UartSpinelInterface::Enable(const esp_openthread_uart_config_t &radio_uart_config)
{
esp_err_t error = ESP_OK;
m_uart_rx_buffer = static_cast<uint8_t *>(heap_caps_malloc(kMaxFrameSize, MALLOC_CAP_8BIT));
@ -56,7 +73,7 @@ esp_err_t UartSpinelInterface::Init(const esp_openthread_uart_config_t &radio_ua
return error;
}
esp_err_t UartSpinelInterface::Deinit(void)
esp_err_t UartSpinelInterface::Disable(void)
{
if (m_uart_rx_buffer) {
heap_caps_free(m_uart_rx_buffer);
@ -88,24 +105,14 @@ exit:
return error;
}
void UartSpinelInterface::Process(const void *mainloop)
void UartSpinelInterface::Process(const void *aMainloopContext)
{
if (FD_ISSET(m_uart_fd, &((esp_openthread_mainloop_context_t *)mainloop)->read_fds)) {
if (FD_ISSET(m_uart_fd, &((esp_openthread_mainloop_context_t *)aMainloopContext)->read_fds)) {
ESP_LOGD(OT_PLAT_LOG_TAG, "radio uart read event");
TryReadAndDecode();
}
}
void UartSpinelInterface::Update(void *mainloop)
{
// Register only READ events for radio UART and always wait
// for a radio WRITE to complete.
FD_SET(m_uart_fd, &((esp_openthread_mainloop_context_t *)mainloop)->read_fds);
if (m_uart_fd > ((esp_openthread_mainloop_context_t *)mainloop)->max_fd) {
((esp_openthread_mainloop_context_t *)mainloop)->max_fd = m_uart_fd;
}
}
int UartSpinelInterface::TryReadAndDecode(void)
{
uint8_t buffer[UART_HW_FIFO_LEN(m_uart_config.port)];
@ -246,7 +253,7 @@ void UartSpinelInterface::HandleHdlcFrame(otError error)
m_receiver_frame_callback(m_receiver_frame_context);
} else {
ESP_LOGE(OT_PLAT_LOG_TAG, "dropping radio frame: %s", otThreadErrorToString(error));
m_receive_frame_buffer.DiscardFrame();
m_receive_frame_buffer->DiscardFrame();
}
}
@ -294,5 +301,20 @@ otError UartSpinelInterface::HardwareReset(void)
return OT_ERROR_NONE;
}
void UartSpinelInterface::UpdateFdSet(void *aMainloopContext)
{
// Register only READ events for radio UART and always wait
// for a radio WRITE to complete.
FD_SET(m_uart_fd, &((esp_openthread_mainloop_context_t *)aMainloopContext)->read_fds);
if (m_uart_fd > ((esp_openthread_mainloop_context_t *)aMainloopContext)->max_fd) {
((esp_openthread_mainloop_context_t *)aMainloopContext)->max_fd = m_uart_fd;
}
}
uint32_t UartSpinelInterface::GetBusSpeed(void) const
{
return m_uart_config.uart_config.baud_rate;
}
} // namespace openthread
} // namespace esp

View File

@ -471,32 +471,32 @@ extern "C" {
#define IEEE802154_SFD_TIMEOUT_CNT_CLEAR_S 14
#define IEEE802154_CRC_ERROR_CNT_CLEAR (BIT(13))
#define IEEE802154_CRC_ERROR_CNT_CLEAR_S 13
#define IEEE802154_ED_ABORT_CNT_CLEAR (BIT(12))
#define IEEE802154_ED_ABORT_CNT_CLEAR_S 12
#define IEEE802154_CCA_FAIL_CNT_CLEAR (BIT(11))
#define IEEE802154_CCA_FAIL_CNT_CLEAR_S 11
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR (BIT(10))
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR_S 10
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR (BIT(9))
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR_S 9
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR (BIT(8))
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR_S 8
#define IEEE802154_RX_RESTART_CNT_CLEAR (BIT(7))
#define IEEE802154_RX_RESTART_CNT_CLEAR_S 7
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR (BIT(12))
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR_S 12
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR (BIT(11))
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR_S 11
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR (BIT(10))
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR_S 10
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR (BIT(9))
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR_S 9
#define IEEE802154_RX_RESTART_CNT_CLEAR (BIT(8))
#define IEEE802154_RX_RESTART_CNT_CLEAR_S 8
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR (BIT(7))
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR_S 7
#define IEEE802154_TX_ACK_ABORT_COEX_CNT_CLEAR (BIT(6))
#define IEEE802154_TX_ACK_ABORT_COEX_CNT_CLEAR_S 6
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR (BIT(5))
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR_S 5
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR (BIT(4))
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR_S 4
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR (BIT(3))
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR_S 3
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR (BIT(2))
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR_S 2
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR (BIT(1))
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR_S 1
#define IEEE802154_CCA_BUSY_CNT_CLEAR (BIT(0))
#define IEEE802154_CCA_BUSY_CNT_CLEAR_S 0
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR (BIT(5))
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR_S 5
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR (BIT(4))
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR_S 4
#define IEEE802154_ED_ABORT_CNT_CLEAR (BIT(3))
#define IEEE802154_ED_ABORT_CNT_CLEAR_S 3
#define IEEE802154_CCA_FAIL_CNT_CLEAR (BIT(2))
#define IEEE802154_CCA_FAIL_CNT_CLEAR_S 2
#define IEEE802154_CCA_BUSY_CNT_CLEAR (BIT(1))
#define IEEE802154_CCA_BUSY_CNT_CLEAR_S 1
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR (BIT(0))
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR_S 0
#define IEEE802154_MAC_DATE_REG (IEEE802154_REG_BASE + 0x0184)
#define IEEE802154_MAC_DATE 0xFFFFFFFF

View File

@ -472,32 +472,32 @@ extern "C" {
#define IEEE802154_SFD_TIMEOUT_CNT_CLEAR_S 14
#define IEEE802154_CRC_ERROR_CNT_CLEAR (BIT(13))
#define IEEE802154_CRC_ERROR_CNT_CLEAR_S 13
#define IEEE802154_ED_ABORT_CNT_CLEAR (BIT(12))
#define IEEE802154_ED_ABORT_CNT_CLEAR_S 12
#define IEEE802154_CCA_FAIL_CNT_CLEAR (BIT(11))
#define IEEE802154_CCA_FAIL_CNT_CLEAR_S 11
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR (BIT(10))
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR_S 10
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR (BIT(9))
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR_S 9
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR (BIT(8))
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR_S 8
#define IEEE802154_RX_RESTART_CNT_CLEAR (BIT(7))
#define IEEE802154_RX_RESTART_CNT_CLEAR_S 7
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR (BIT(12))
#define IEEE802154_RX_FILTER_FAIL_CNT_CLEAR_S 12
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR (BIT(11))
#define IEEE802154_NO_RSS_DETECT_CNT_CLEAR_S 11
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR (BIT(10))
#define IEEE802154_RX_ABORT_COEX_CNT_CLEAR_S 10
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR (BIT(9))
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR_S 9
#define IEEE802154_RX_RESTART_CNT_CLEAR (BIT(8))
#define IEEE802154_RX_RESTART_CNT_CLEAR_S 8
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR (BIT(7))
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR_S 7
#define IEEE802154_TX_ACK_ABORT_COEX_CNT_CLEAR (BIT(6))
#define IEEE802154_TX_ACK_ABORT_COEX_CNT_CLEAR_S 6
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR (BIT(5))
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR_S 5
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR (BIT(4))
#define IEEE802154_RX_ACK_ABORT_COEX_CNT_CLEAR_S 4
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR (BIT(3))
#define IEEE802154_RX_ACK_TIMEOUT_CNT_CLEAR_S 3
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR (BIT(2))
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR_S 2
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR (BIT(1))
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR_S 1
#define IEEE802154_CCA_BUSY_CNT_CLEAR (BIT(0))
#define IEEE802154_CCA_BUSY_CNT_CLEAR_S 0
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR (BIT(5))
#define IEEE802154_TX_BREAK_COEX_CNT_CLEAR_S 5
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR (BIT(4))
#define IEEE802154_TX_SECURITY_ERROR_CNT_CLEAR_S 4
#define IEEE802154_ED_ABORT_CNT_CLEAR (BIT(3))
#define IEEE802154_ED_ABORT_CNT_CLEAR_S 3
#define IEEE802154_CCA_FAIL_CNT_CLEAR (BIT(2))
#define IEEE802154_CCA_FAIL_CNT_CLEAR_S 2
#define IEEE802154_CCA_BUSY_CNT_CLEAR (BIT(1))
#define IEEE802154_CCA_BUSY_CNT_CLEAR_S 1
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR (BIT(0))
#define IEEE802154_ED_SCAN_COEX_CNT_CLEAR_S 0
#define DEBUG_SEL_CFG0_REG (IEEE802154_REG_BASE + 0x184)
#define DEBUG_FIELD3_SEL 0x0000001F

View File

@ -92,8 +92,8 @@ static void ot_task_worker(void *aContext)
esp_openthread_launch_mainloop();
// Clean up
esp_netif_destroy(openthread_netif);
esp_openthread_netif_glue_deinit();
esp_netif_destroy(openthread_netif);
esp_vfs_eventfd_unregister();
vTaskDelete(NULL);
}

View File

@ -95,8 +95,8 @@ static void ot_task_worker(void *aContext)
esp_openthread_launch_mainloop();
// Clean up
esp_netif_destroy(openthread_netif);
esp_openthread_netif_glue_deinit();
esp_netif_destroy(openthread_netif);
esp_vfs_eventfd_unregister();
vTaskDelete(NULL);

View File

@ -193,8 +193,8 @@ static void ot_task_worker(void *aContext)
esp_openthread_launch_mainloop();
// Clean up
esp_netif_destroy(openthread_netif);
esp_openthread_netif_glue_deinit();
esp_netif_destroy(openthread_netif);
esp_vfs_eventfd_unregister();
vTaskDelete(NULL);

View File

@ -129,8 +129,8 @@ static void ot_task_worker(void *aContext)
esp_openthread_launch_mainloop();
// Clean up
esp_netif_destroy(openthread_netif);
esp_openthread_netif_glue_deinit();
esp_netif_destroy(openthread_netif);
esp_vfs_eventfd_unregister();
vTaskDelete(NULL);