Merge branch 'backport/openthread_related_feature_v53_20241112' into 'release/v5.3'

Backport openthread related features to 5.3

See merge request espressif/esp-idf!34838
This commit is contained in:
Shu Chen
2024-11-14 09:42:38 +08:00
18 changed files with 232 additions and 19 deletions

View File

@ -278,12 +278,20 @@ menu "OpenThread"
help help
Select this option to enable border router features in OpenThread. Select this option to enable border router features in OpenThread.
menu "Thread Memory Allocation Config"
depends on OPENTHREAD_ENABLED && (SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC)
config OPENTHREAD_MEM_ALLOC_EXTERNAL
bool 'Allocate memory from PSRAM'
default y
help
Select this option to allocate buffer from PSRAM for Thread
config OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT config OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT
bool 'Allocate message pool buffer from PSRAM' bool 'Allocate message pool buffer from PSRAM'
depends on OPENTHREAD_ENABLED && (SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC)
default n default n
help help
If enabled, the message pool is managed by platform defined logic. If enabled, the message pool is managed by platform defined logic.
endmenu
config OPENTHREAD_NUM_MESSAGE_BUFFERS config OPENTHREAD_NUM_MESSAGE_BUFFERS
int "The number of openthread message buffers" int "The number of openthread message buffers"

View File

@ -66,6 +66,16 @@ esp_netif_t *esp_openthread_get_backbone_netif(void);
*/ */
void esp_openthread_register_rcp_failure_handler(esp_openthread_rcp_failure_handler handler); void esp_openthread_register_rcp_failure_handler(esp_openthread_rcp_failure_handler handler);
/**
* @brief Registers the callback for spinel compatibility error.
*
* @note This function must be called before esp_openthread_init.
*
* @param[in] callback The callback.
*
*/
void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback);
/** /**
* @brief Deinitializes the connection to RCP. * @brief Deinitializes the connection to RCP.
* *

View File

@ -200,6 +200,8 @@ typedef struct {
typedef void (*esp_openthread_rcp_failure_handler)(void); typedef void (*esp_openthread_rcp_failure_handler)(void);
typedef void (*esp_openthread_compatibility_error_callback)(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -46,6 +46,7 @@ typedef struct {
typedef void (*esp_radio_spinel_rcp_failure_handler)(void); /* The handler for rcp failure.*/ typedef void (*esp_radio_spinel_rcp_failure_handler)(void); /* The handler for rcp failure.*/
typedef esp_err_t (*esp_radio_spinel_uart_init_handler)(const esp_radio_spinel_uart_config_t *uart_config_t, int *uart_fd); /* The handler for UART initialization.*/ typedef esp_err_t (*esp_radio_spinel_uart_init_handler)(const esp_radio_spinel_uart_config_t *uart_config_t, int *uart_fd); /* The handler for UART initialization.*/
typedef esp_err_t (*esp_radio_spinel_uart_deinit_handler)(const esp_radio_spinel_uart_config_t *uart_config_t, int *uart_fd); /* The handler for UART deinitialization.*/ typedef esp_err_t (*esp_radio_spinel_uart_deinit_handler)(const esp_radio_spinel_uart_config_t *uart_config_t, int *uart_fd); /* The handler for UART deinitialization.*/
typedef void (*esp_radio_spinel_compatibility_error_callback)(void);
typedef struct typedef struct
{ {
@ -391,6 +392,16 @@ esp_err_t esp_radio_spinel_rcp_deinit(esp_radio_spinel_idx_t idx);
*/ */
esp_err_t esp_radio_spinel_rcp_version_get(char *running_rcp_version, esp_radio_spinel_idx_t idx); esp_err_t esp_radio_spinel_rcp_version_get(char *running_rcp_version, esp_radio_spinel_idx_t idx);
/**
* @brief Registers the callback for spinel compatibility error.
*
* @note This function must be called before esp_radio_spinel_init.
*
* @param[in] callback The callback.
*
*/
void esp_radio_spinel_set_compatibility_error_callback(esp_radio_spinel_compatibility_error_callback callback);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get frame counter.
*
* @param[in] idx The index of 802.15.4 related protocol stack.
*
* @return
* - The frame counter
*
*/
uint32_t esp_radio_spinel_extern_get_frame_counter(esp_radio_spinel_idx_t idx);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_heap_caps.h"
#include <utility>
#include "common/new.hpp"
template <typename T, typename... Args>
inline T *New(uint32_t alloc_caps, Args &&...args)
{
void *p = heap_caps_calloc(1, sizeof(T), alloc_caps);
if (p != nullptr) {
return new (p) T(std::forward<Args>(args)...);
}
return nullptr;
}

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -84,7 +84,7 @@ void esp_openthread_platform_workflow_unregister(const char *name);
* @brief Initializes the platform-specific support for the OpenThread stack. * @brief Initializes the platform-specific support for the OpenThread stack.
* *
* @note This function is not called by and will not call the OpenThread library. * @note This function is not called by and will not call the OpenThread library.
* The user needs to call otInstanceInitSingle to intialize the OpenThread * The user needs to call otInstanceInitSingle to initialize the OpenThread
* stack after calling this function. * stack after calling this function.
* *
* @param[in] init_config The initialization configuration. * @param[in] init_config The initialization configuration.
@ -146,6 +146,15 @@ esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openth
* *
*/ */
void esp_openthread_set_storage_name(const char *name); void esp_openthread_set_storage_name(const char *name);
/**
* @brief Gets the caps of memory allocation.
*
* @return
* - The caps of the memory.
*/
uint32_t esp_openthread_get_alloc_caps(void);
#ifdef __cplusplus #ifdef __cplusplus
} // end of extern "C" } // end of extern "C"
#endif #endif

View File

@ -261,6 +261,16 @@
#define OPENTHREAD_POSIX_CONFIG_RCP_TIME_SYNC_INTERVAL (60 * 1000 * 1000) #define OPENTHREAD_POSIX_CONFIG_RCP_TIME_SYNC_INTERVAL (60 * 1000 * 1000)
#endif #endif
/**
* @def OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE
*
* Enables compatibility error callback in Spinel
*/
#ifndef OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE
#define OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE 1
#endif
#endif #endif
/** /**

View File

@ -73,6 +73,24 @@
*/ */
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS CONFIG_OPENTHREAD_NUM_MESSAGE_BUFFERS #define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS CONFIG_OPENTHREAD_NUM_MESSAGE_BUFFERS
/**
* @def OPENTHREAD_CONFIG_COAP_API_ENABLE
*
* Define to 1 to enable the CoAP API.
*
*/
#define OPENTHREAD_CONFIG_COAP_API_ENABLE 1
/**
* @def OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
*
* Define to 1 to enable platform NETIF support.
*
*/
#ifndef OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1
#endif
/** /**
* @def OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE * @def OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
* *

View File

@ -41,7 +41,6 @@
* *
*/ */
#ifndef OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT #ifndef OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT
// TZ-567: Set OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT to 3 after adding rcp failure notification mechanism
#define OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT 3 #define OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT 3
#endif #endif
@ -77,3 +76,23 @@
#ifndef OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT #ifndef OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT
#define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT #define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT
#endif #endif
/**
* @def OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE
*
* Enables compatibility error callback in Spinel
*/
#ifndef OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE
#define OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE 1
#endif
/**
* @def OPENTHREAD_SPINEL_CONFIG_MAX_SRC_MATCH_ENTRIES
*
* Defines size of the local source match table used by RadioSpinel
* when OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT is used.
*/
#ifndef OPENTHREAD_SPINEL_CONFIG_MAX_SRC_MATCH_ENTRIES
#define OPENTHREAD_SPINEL_CONFIG_MAX_SRC_MATCH_ENTRIES 12
#endif

View File

@ -5,4 +5,4 @@ supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
originator: 'Organization: Google LLC' originator: 'Organization: Google LLC'
description: OpenThread released by Google is an open-source implementation of the Thread networking description: OpenThread released by Google is an open-source implementation of the Thread networking
url: https://github.com/espressif/openthread url: https://github.com/espressif/openthread
hash: f32c18bc0840f400182456e58ae3900fc2fb4af7 hash: 005c5cefc22aaf0396e4327ee7f2e0ad32a7733b

View File

@ -16,6 +16,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_netif.h" #include "esp_netif.h"
#include "esp_openthread.h" #include "esp_openthread.h"
#include "esp_openthread_border_router.h"
#include "esp_openthread_common_macro.h" #include "esp_openthread_common_macro.h"
#include "esp_openthread_lock.h" #include "esp_openthread_lock.h"
#include "esp_openthread_netif_glue_priv.h" #include "esp_openthread_netif_glue_priv.h"
@ -33,6 +34,7 @@
#include "openthread/ip6.h" #include "openthread/ip6.h"
#include "openthread/link.h" #include "openthread/link.h"
#include "openthread/message.h" #include "openthread/message.h"
#include "openthread/platform/infra_if.h"
#include "openthread/thread.h" #include "openthread/thread.h"
typedef struct { typedef struct {
@ -381,3 +383,16 @@ esp_netif_t *esp_openthread_get_netif(void)
{ {
return s_openthread_netif; return s_openthread_netif;
} }
otError otPlatGetInfraIfLinkLayerAddress(otInstance *aInstance, uint32_t aIfIndex, otPlatInfraIfLinkLayerAddress *aInfraIfLinkLayerAddress)
{
esp_netif_t *backbone_netif = esp_openthread_get_backbone_netif();
if (esp_netif_get_netif_impl_index(backbone_netif) != aIfIndex) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to get LL address, error: Invalid If index");
return OT_ERROR_FAILED;
} else {
esp_netif_get_mac(backbone_netif, aInfraIfLinkLayerAddress->mAddress);
aInfraIfLinkLayerAddress->mLength = 6;
return OT_ERROR_NONE;
}
}

View File

@ -204,3 +204,13 @@ esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openth
} }
return ESP_OK; return ESP_OK;
} }
uint32_t esp_openthread_get_alloc_caps(void)
{
return
#if CONFIG_OPENTHREAD_PLATFORM_MALLOC_CAP_SPIRAM
(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#else
(MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT);
#endif
}

View File

@ -54,6 +54,8 @@ static const char *radiospinel_workflow = "radio_spinel";
static const esp_openthread_radio_config_t *s_esp_openthread_radio_config = NULL; static const esp_openthread_radio_config_t *s_esp_openthread_radio_config = NULL;
static esp_openthread_compatibility_error_callback s_compatibility_error_callback = NULL;
static void esp_openthread_radio_config_set(const esp_openthread_radio_config_t *config) static void esp_openthread_radio_config_set(const esp_openthread_radio_config_t *config)
{ {
s_esp_openthread_radio_config = config; s_esp_openthread_radio_config = config;
@ -64,6 +66,22 @@ static const esp_openthread_radio_config_t *esp_openthread_radio_config_get(void
return s_esp_openthread_radio_config; return s_esp_openthread_radio_config;
} }
static void ot_spinel_compatibility_error_callback(void *context)
{
OT_UNUSED_VARIABLE(context);
if (s_compatibility_error_callback) {
s_compatibility_error_callback();
} else {
ESP_LOGE(OT_PLAT_LOG_TAG, "None callback to handle compatibility error of openthread spinel");
assert(false);
}
}
void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback)
{
s_compatibility_error_callback = callback;
}
esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *config) esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *config)
{ {
spinel_iid_t iidList[ot::Spinel::kSpinelHeaderMaxNumIid]; spinel_iid_t iidList[ot::Spinel::kSpinelHeaderMaxNumIid];
@ -89,7 +107,8 @@ esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *conf
"Spinel interface init failed"); "Spinel interface init failed");
#endif #endif
s_spinel_driver.Init(s_spinel_interface.GetSpinelInterface(), true, iidList, ot::Spinel::kSpinelHeaderMaxNumIid); s_spinel_driver.Init(s_spinel_interface.GetSpinelInterface(), true, iidList, ot::Spinel::kSpinelHeaderMaxNumIid);
s_radio.Init(/*skip_rcp_compatibility_check=*/false, /*reset_radio=*/true, &s_spinel_driver, s_radio_caps); s_radio.SetCompatibilityErrorCallback(ot_spinel_compatibility_error_callback, esp_openthread_get_instance());
s_radio.Init(/*skip_rcp_compatibility_check=*/false, /*reset_radio=*/true, &s_spinel_driver, s_radio_caps, /*RCP_time_sync=*/true);
#if CONFIG_OPENTHREAD_RADIO_SPINEL_SPI // CONFIG_OPENTHREAD_RADIO_SPINEL_SPI #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 failed"); ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().AfterRadioInit(), OT_PLAT_LOG_TAG, "Spinel interface init failed");
#endif #endif
@ -336,15 +355,15 @@ void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCoun
} }
#if CONFIG_OPENTHREAD_DIAG #if CONFIG_OPENTHREAD_DIAG
otError otPlatDiagProcess(otInstance *instance, int argc, char *argv[], char *output, size_t output_max_len) otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
{ {
// deliver the platform specific diags commands to radio only ncp. // deliver the platform specific diags commands to radio only ncp.
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE] = {'\0'}; char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE] = {'\0'};
char *cur = cmd; char *cur = cmd;
char *end = cmd + sizeof(cmd); char *end = cmd + sizeof(cmd);
for (int index = 0; index < argc; index++) { for (int index = 0; index < aArgsLength; index++) {
cur += snprintf(cur, static_cast<size_t>(end - cur), "%s ", argv[index]); cur += snprintf(cur, static_cast<size_t>(end - cur), "%s ", aArgs[index]);
} }
return s_radio.PlatDiagProcess(cmd); return s_radio.PlatDiagProcess(cmd);

View File

@ -10,9 +10,11 @@
#include "platform/exit_code.h" #include "platform/exit_code.h"
#include "radio_spinel.hpp" #include "radio_spinel.hpp"
#include "esp_radio_spinel.h" #include "esp_radio_spinel.h"
#include "esp_radio_spinel_platform.h"
#include "esp_radio_spinel_adapter.hpp" #include "esp_radio_spinel_adapter.hpp"
#include "esp_radio_spinel_uart_interface.hpp" #include "esp_radio_spinel_uart_interface.hpp"
#include "spinel_driver.hpp" #include "spinel_driver.hpp"
#include "openthread/link.h"
#define SPINEL_VENDOR_PROPERTY_BIT_PENDINGMODE BIT(0) #define SPINEL_VENDOR_PROPERTY_BIT_PENDINGMODE BIT(0)
#define SPINEL_VENDOR_PROPERTY_BIT_COORDINATOR BIT(1) #define SPINEL_VENDOR_PROPERTY_BIT_COORDINATOR BIT(1)
@ -39,6 +41,8 @@ static otRadioCaps s_radio_caps = (OT_RADIO_CAPS_ENERGY_SCAN |
OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_ACK_TIMEOUT |
OT_RADIO_CAPS_SLEEP_TO_TX); OT_RADIO_CAPS_SLEEP_TO_TX);
static esp_radio_spinel_compatibility_error_callback s_radio_spinel_compatibility_error_callback = NULL;
static esp_radio_spinel_idx_t get_index_from_instance(otInstance *instance) static esp_radio_spinel_idx_t get_index_from_instance(otInstance *instance)
{ {
// TZ-563: Implement the function to get the esp radio spinel idx from otInstance for multipan rcp // TZ-563: Implement the function to get the esp radio spinel idx from otInstance for multipan rcp
@ -67,6 +71,22 @@ static void esp_radio_spinel_restore_vendor_properities(void *context)
} }
} }
static void radio_spinel_compatibility_error_callback(void *context)
{
OT_UNUSED_VARIABLE(context);
if (s_radio_spinel_compatibility_error_callback) {
s_radio_spinel_compatibility_error_callback();
} else {
ESP_LOGE(ESP_SPINEL_LOG_TAG, "None callback to handle compatibility error of openthread spinel");
assert(false);
}
}
void esp_openthread_set_compatibility_error_callback(esp_radio_spinel_compatibility_error_callback callback)
{
s_radio_spinel_compatibility_error_callback = callback;
}
void ReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError) void ReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{ {
esp_radio_spinel_idx_t idx = get_index_from_instance(aInstance); esp_radio_spinel_idx_t idx = get_index_from_instance(aInstance);
@ -242,12 +262,13 @@ esp_err_t esp_radio_spinel_uart_interface_enable(const esp_radio_spinel_uart_con
void esp_radio_spinel_init(esp_radio_spinel_idx_t idx) void esp_radio_spinel_init(esp_radio_spinel_idx_t idx)
{ {
spinel_iid_t iidList[ot::Spinel::kSpinelHeaderMaxNumIid]; spinel_iid_t iidList[ot::Spinel::kSpinelHeaderMaxNumIid];
otInstance *instance = get_instance_from_index(idx);
// Multipan is not currently supported // Multipan is not currently supported
iidList[0] = 0; iidList[0] = 0;
s_spinel_driver[idx].Init(s_spinel_interface[idx].GetSpinelInterface(), true, iidList, ot::Spinel::kSpinelHeaderMaxNumIid); s_spinel_driver[idx].Init(s_spinel_interface[idx].GetSpinelInterface(), true, iidList, ot::Spinel::kSpinelHeaderMaxNumIid);
s_radio[idx].Init(/*skip_rcp_compatibility_check=*/false, /*reset_radio=*/true, &s_spinel_driver[idx], s_radio_caps); s_radio[idx].SetCompatibilityErrorCallback(radio_spinel_compatibility_error_callback, instance);
otInstance *instance = get_instance_from_index(idx); s_radio[idx].Init(/*skip_rcp_compatibility_check=*/false, /*reset_radio=*/true, &s_spinel_driver[idx], s_radio_caps, false);
s_radio[idx].SetVendorRestorePropertiesCallback(esp_radio_spinel_restore_vendor_properities, instance); s_radio[idx].SetVendorRestorePropertiesCallback(esp_radio_spinel_restore_vendor_properities, instance);
} }
@ -405,6 +426,19 @@ esp_err_t esp_radio_spinel_set_rcp_ready(esp_radio_spinel_idx_t idx)
return ESP_OK; return ESP_OK;
} }
// TZ-1261
uint32_t otLinkGetFrameCounter(otInstance *aInstance)
{
esp_radio_spinel_idx_t idx = get_index_from_instance(aInstance);
return esp_radio_spinel_extern_get_frame_counter(idx);
}
__attribute__((weak)) uint32_t esp_radio_spinel_extern_get_frame_counter(esp_radio_spinel_idx_t idx)
{
ESP_LOGW(ESP_SPINEL_LOG_TAG, "None function to get frame counter");
return 0;
}
namespace ot { namespace ot {
namespace Spinel { namespace Spinel {

View File

@ -2,7 +2,6 @@
# SPDX-License-Identifier: Unlicense OR CC0-1.0 # SPDX-License-Identifier: Unlicense OR CC0-1.0
# !/usr/bin/env python3 # !/usr/bin/env python3
# this file defines some functions for testing cli and br under pytest framework # this file defines some functions for testing cli and br under pytest framework
import re import re
import socket import socket
import struct import struct
@ -145,7 +144,7 @@ def changeDeviceRole(dut:IdfDut, role:str) -> None:
def getDataset(dut:IdfDut) -> str: def getDataset(dut:IdfDut) -> str:
clean_buffer(dut) clean_buffer(dut)
execute_command(dut, 'dataset active -x') execute_command(dut, 'dataset active -x')
dut_data = dut.expect(r'\n(\w{212})\r', timeout=5)[1].decode() dut_data = dut.expect(r'\n(\w+)\r', timeout=5)[1].decode()
return str(dut_data) return str(dut_data)