feat(openthread): add a callback to handle rcp reset failure

This commit is contained in:
Xu Si Yu
2025-04-18 16:51:49 +08:00
parent f1ae86f830
commit 352ea8d02c
7 changed files with 80 additions and 17 deletions

View File

@ -29,6 +29,16 @@ void esp_openthread_register_rcp_failure_handler(esp_openthread_rcp_failure_hand
*/ */
void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback); void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback);
/**
* @brief Registers the callback for co-processor reset failure.
*
* @note This function should be called before esp_openthread_init.
*
* @param[in] callback The callback.
*
*/
void esp_openthread_set_coprocessor_reset_failure_callback(esp_openthread_coprocessor_reset_failure_callback callback);
/** /**
* @brief Deinitializes the connection to RCP. * @brief Deinitializes the connection to RCP.
* *

View File

@ -210,6 +210,12 @@ typedef void (*esp_openthread_rcp_failure_handler)(void);
*/ */
typedef void (*esp_openthread_compatibility_error_callback)(void); typedef void (*esp_openthread_compatibility_error_callback)(void);
/**
* @brief The OpenThread co-processor reset failure callback
*
*/
typedef void (*esp_openthread_coprocessor_reset_failure_callback)(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -47,6 +47,7 @@ typedef void (*esp_radio_spinel_rcp_failure_handler)(void);
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 void (*esp_radio_spinel_compatibility_error_callback)(void);
typedef void (*esp_radio_spinel_coprocessor_reset_failure_callback)(void);
typedef struct typedef struct
{ {
@ -402,6 +403,16 @@ esp_err_t esp_radio_spinel_rcp_version_get(char *running_rcp_version, esp_radio_
*/ */
void esp_radio_spinel_set_compatibility_error_callback(esp_radio_spinel_compatibility_error_callback callback); void esp_radio_spinel_set_compatibility_error_callback(esp_radio_spinel_compatibility_error_callback callback);
/**
* @brief Registers the callback for co-processor reset failure.
*
* @note This function should be called before esp_radio_spinel_init.
*
* @param[in] callback The callback.
*
*/
void esp_radio_spinel_set_coprocessor_reset_failure_callback(esp_radio_spinel_coprocessor_reset_failure_callback callback);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -513,6 +513,15 @@
#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_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
*
* Enables co-processor reset failure callback in Spinel driver
*/
#ifndef OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
#define OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE 1
#endif
#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI #endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
#if CONFIG_OPENTHREAD_LINK_METRICS #if CONFIG_OPENTHREAD_LINK_METRICS

View File

@ -67,3 +67,12 @@
#ifndef OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE #ifndef OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE
#define OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE 1 #define OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE 1
#endif #endif
/**
* @def OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
*
* Enables co-processor reset failure callback in Spinel driver
*/
#ifndef OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
#define OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE 1
#endif

View File

@ -54,11 +54,9 @@ static otRadioCaps s_radio_caps = (OT_RADIO_CAPS_ENERGY_SCAN |
OT_RADIO_CAPS_SLEEP_TO_TX); OT_RADIO_CAPS_SLEEP_TO_TX);
static const char *radiospinel_workflow = "radio_spinel"; 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 esp_openthread_compatibility_error_callback s_compatibility_error_callback = NULL;
static esp_openthread_coprocessor_reset_failure_callback s_coprocessor_reset_failure_callback = NULL;
static char s_internal_rcp_version[OT_SPINEL_RCP_VERSION_MAX_SIZE] = {'\0'}; static char s_internal_rcp_version[OT_SPINEL_RCP_VERSION_MAX_SIZE] = {'\0'};
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)
@ -74,12 +72,15 @@ static const esp_openthread_radio_config_t *esp_openthread_radio_config_get(void
static void ot_spinel_compatibility_error_callback(void *context) static void ot_spinel_compatibility_error_callback(void *context)
{ {
OT_UNUSED_VARIABLE(context); OT_UNUSED_VARIABLE(context);
if (s_compatibility_error_callback) { assert(s_compatibility_error_callback);
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); static void ot_spinel_coprocessor_reset_failure_callback(void *context)
} {
OT_UNUSED_VARIABLE(context);
assert(s_coprocessor_reset_failure_callback);
s_coprocessor_reset_failure_callback();
} }
void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback) void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback)
@ -87,6 +88,11 @@ void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibilit
s_compatibility_error_callback = callback; s_compatibility_error_callback = callback;
} }
void esp_openthread_set_coprocessor_reset_failure_callback(esp_openthread_coprocessor_reset_failure_callback callback)
{
s_coprocessor_reset_failure_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];
@ -112,6 +118,7 @@ esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *conf
ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().Enable(config->radio_config.radio_spi_config), OT_PLAT_LOG_TAG, ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().Enable(config->radio_config.radio_spi_config), OT_PLAT_LOG_TAG,
"Spinel interface init failed"); "Spinel interface init failed");
#endif #endif
s_spinel_driver.SetCoprocessorResetFailureCallback(ot_spinel_coprocessor_reset_failure_callback, esp_openthread_get_instance());
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);
if (strlen(s_internal_rcp_version) > 0) { if (strlen(s_internal_rcp_version) > 0) {
const char *running_rcp_version = s_spinel_driver.GetVersion(); const char *running_rcp_version = s_spinel_driver.GetVersion();

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -42,6 +42,7 @@ static otRadioCaps s_radio_caps = (OT_RADIO_CAPS_ENERGY_SCAN |
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_compatibility_error_callback s_radio_spinel_compatibility_error_callback = NULL;
static esp_radio_spinel_coprocessor_reset_failure_callback s_radio_spinel_coprocessor_reset_failure_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)
{ {
@ -74,12 +75,15 @@ static void esp_radio_spinel_restore_vendor_properities(void *context)
static void radio_spinel_compatibility_error_callback(void *context) static void radio_spinel_compatibility_error_callback(void *context)
{ {
OT_UNUSED_VARIABLE(context); OT_UNUSED_VARIABLE(context);
if (s_radio_spinel_compatibility_error_callback) { assert(s_radio_spinel_compatibility_error_callback);
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); static void radio_spinel_coprocessor_reset_failure_callback(void *context)
} {
OT_UNUSED_VARIABLE(context);
assert(s_radio_spinel_coprocessor_reset_failure_callback);
s_radio_spinel_coprocessor_reset_failure_callback();
} }
void esp_radio_spinel_set_compatibility_error_callback(esp_radio_spinel_compatibility_error_callback callback) void esp_radio_spinel_set_compatibility_error_callback(esp_radio_spinel_compatibility_error_callback callback)
@ -87,6 +91,11 @@ void esp_radio_spinel_set_compatibility_error_callback(esp_radio_spinel_compatib
s_radio_spinel_compatibility_error_callback = callback; s_radio_spinel_compatibility_error_callback = callback;
} }
void esp_radio_spinel_set_coprocessor_reset_failure_callback(esp_radio_spinel_coprocessor_reset_failure_callback callback)
{
s_radio_spinel_coprocessor_reset_failure_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);
@ -232,6 +241,7 @@ void esp_radio_spinel_set_callbacks(const esp_radio_spinel_callbacks_t aCallback
{ {
s_esp_radio_spinel_callbacks[idx] = aCallbacks; s_esp_radio_spinel_callbacks[idx] = aCallbacks;
RadioSpinelCallbacks Callbacks; RadioSpinelCallbacks Callbacks;
memset(&Callbacks, 0, sizeof(Callbacks));
Callbacks.mReceiveDone = ReceiveDone; Callbacks.mReceiveDone = ReceiveDone;
Callbacks.mTransmitDone = TransmitDone; Callbacks.mTransmitDone = TransmitDone;
Callbacks.mEnergyScanDone = EnergyScanDone; Callbacks.mEnergyScanDone = EnergyScanDone;
@ -266,6 +276,7 @@ void esp_radio_spinel_init(esp_radio_spinel_idx_t idx)
// Multipan is not currently supported // Multipan is not currently supported
iidList[0] = 0; iidList[0] = 0;
s_spinel_driver[idx].SetCoprocessorResetFailureCallback(radio_spinel_coprocessor_reset_failure_callback, instance);
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].SetCompatibilityErrorCallback(radio_spinel_compatibility_error_callback, instance); s_radio[idx].SetCompatibilityErrorCallback(radio_spinel_compatibility_error_callback, instance);
s_radio[idx].Init(/*skip_rcp_compatibility_check=*/false, /*reset_radio=*/true, &s_spinel_driver[idx], s_radio_caps, false); s_radio[idx].Init(/*skip_rcp_compatibility_check=*/false, /*reset_radio=*/true, &s_spinel_driver[idx], s_radio_caps, false);