From 352ea8d02c7dfc989510dc2c8ee2acb97ff10418 Mon Sep 17 00:00:00 2001 From: Xu Si Yu Date: Fri, 18 Apr 2025 16:51:49 +0800 Subject: [PATCH] feat(openthread): add a callback to handle rcp reset failure --- .../include/esp_openthread_spinel.h | 10 ++++++++ .../openthread/include/esp_openthread_types.h | 6 +++++ .../openthread/include/esp_radio_spinel.h | 13 +++++++++- .../openthread-core-esp32x-ftd-config.h | 9 +++++++ .../openthread-core-esp32x-spinel-config.h | 9 +++++++ .../src/port/esp_openthread_radio_spinel.cpp | 25 ++++++++++++------- .../src/spinel/esp_radio_spinel.cpp | 25 +++++++++++++------ 7 files changed, 80 insertions(+), 17 deletions(-) diff --git a/components/openthread/include/esp_openthread_spinel.h b/components/openthread/include/esp_openthread_spinel.h index 70c74413e2..2900095420 100644 --- a/components/openthread/include/esp_openthread_spinel.h +++ b/components/openthread/include/esp_openthread_spinel.h @@ -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); +/** + * @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. * diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index df552ed142..364d596100 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -210,6 +210,12 @@ typedef void (*esp_openthread_rcp_failure_handler)(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 } #endif diff --git a/components/openthread/include/esp_radio_spinel.h b/components/openthread/include/esp_radio_spinel.h index 710d61d646..3f21e9e198 100644 --- a/components/openthread/include/esp_radio_spinel.h +++ b/components/openthread/include/esp_radio_spinel.h @@ -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 */ @@ -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_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_coprocessor_reset_failure_callback)(void); 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); +/** + * @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 } #endif diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 942ceeb6bf..59d3780fa9 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -513,6 +513,15 @@ #define OPENTHREAD_POSIX_CONFIG_RCP_TIME_SYNC_INTERVAL (60 * 1000 * 1000) #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 #if CONFIG_OPENTHREAD_LINK_METRICS diff --git a/components/openthread/private_include/openthread-core-esp32x-spinel-config.h b/components/openthread/private_include/openthread-core-esp32x-spinel-config.h index 350a21c6dc..7c3853ecb5 100644 --- a/components/openthread/private_include/openthread-core-esp32x-spinel-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-spinel-config.h @@ -67,3 +67,12 @@ #ifndef OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE #define OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE 1 #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 diff --git a/components/openthread/src/port/esp_openthread_radio_spinel.cpp b/components/openthread/src/port/esp_openthread_radio_spinel.cpp index 17fa36bbe6..2a2995483e 100644 --- a/components/openthread/src/port/esp_openthread_radio_spinel.cpp +++ b/components/openthread/src/port/esp_openthread_radio_spinel.cpp @@ -54,11 +54,9 @@ static otRadioCaps s_radio_caps = (OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_SLEEP_TO_TX); static const char *radiospinel_workflow = "radio_spinel"; - 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_coprocessor_reset_failure_callback s_coprocessor_reset_failure_callback = NULL; 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) @@ -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) { 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); - } + assert(s_compatibility_error_callback); + s_compatibility_error_callback(); +} + +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) @@ -87,6 +88,11 @@ void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibilit 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) { 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, "Spinel interface init failed"); #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); if (strlen(s_internal_rcp_version) > 0) { const char *running_rcp_version = s_spinel_driver.GetVersion(); diff --git a/components/openthread/src/spinel/esp_radio_spinel.cpp b/components/openthread/src/spinel/esp_radio_spinel.cpp index aba599e355..bef9cbe011 100644 --- a/components/openthread/src/spinel/esp_radio_spinel.cpp +++ b/components/openthread/src/spinel/esp_radio_spinel.cpp @@ -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 */ @@ -42,6 +42,7 @@ static otRadioCaps s_radio_caps = (OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_SLEEP_TO_TX); 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) { @@ -74,12 +75,15 @@ 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); - } + assert(s_radio_spinel_compatibility_error_callback); + s_radio_spinel_compatibility_error_callback(); +} + +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) @@ -87,6 +91,11 @@ void esp_radio_spinel_set_compatibility_error_callback(esp_radio_spinel_compatib 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) { 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; RadioSpinelCallbacks Callbacks; + memset(&Callbacks, 0, sizeof(Callbacks)); Callbacks.mReceiveDone = ReceiveDone; Callbacks.mTransmitDone = TransmitDone; Callbacks.mEnergyScanDone = EnergyScanDone; @@ -266,6 +276,7 @@ void esp_radio_spinel_init(esp_radio_spinel_idx_t idx) // Multipan is not currently supported 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_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);