mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'fix/fix_openthread_netif_glue_deinit_issue_v6.1' into 'release/v6.1'
fix(openthread): fix stack deinit by reversing netif glue teardown and hardening workflow cleanup (v6.1) See merge request espressif/esp-idf!52397
This commit is contained in:
@@ -289,8 +289,6 @@ esp_err_t esp_disable_extern_coex_gpio_pin(void)
|
||||
#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE && CONFIG_SOC_IEEE802154_SUPPORTED
|
||||
esp_err_t esp_coex_wifi_i154_enable(void)
|
||||
{
|
||||
// TODO: Add a scheme for wifi and 154 coex.
|
||||
// Remove this function if FCC-50 closes.
|
||||
coex_enable();
|
||||
esp_coex_ieee802154_status_enable();
|
||||
return ESP_OK;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -106,6 +106,11 @@ esp_err_t esp_openthread_start(const esp_openthread_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief This function performs OpenThread stack and platform driver deinitialization and delete the handle task.
|
||||
*
|
||||
* @note Thread must already be inactive (`otThreadSetEnabled(false)` and
|
||||
* `otIp6SetEnabled(false)`). If border routing was initialized, call
|
||||
* `esp_openthread_border_router_deinit()` first.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if Thread is already active
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -44,6 +44,11 @@ esp_err_t esp_openthread_border_router_init(void);
|
||||
/**
|
||||
* @brief Deinitializes the border router features of OpenThread.
|
||||
*
|
||||
* @note This function must be called while the OpenThread mainloop is still running
|
||||
* and after Thread IPv6 has been brought down:
|
||||
* `otThreadSetEnabled(instance, false)` then `otIp6SetEnabled(instance, false)`.
|
||||
* Call `esp_openthread_stop()` only after this function returns.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if not initialized
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WORKFLOW_MAX_NAMELEN 16
|
||||
#define WORKFLOW_MAX_NAMELEN 32
|
||||
|
||||
/**
|
||||
* @brief update function declaration
|
||||
@@ -60,11 +60,13 @@ typedef struct esp_openthread_platform_workflow {
|
||||
*
|
||||
* @param[in] updatefcn The update function of the workflow added to the list.
|
||||
* @param[in] processfcn The process function of the workflow added to the list.
|
||||
* @param[in] name The name of the added workflow
|
||||
* @param[in] name The name of the added workflow. Must be non-empty and shorter
|
||||
* than WORKFLOW_MAX_NAMELEN (including the terminating '\\0').
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM on allocation failure
|
||||
* - ESP_ERR_INVALID_ARG if name is NULL, empty, or too long
|
||||
* - ESP_FAIL on other failures
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -225,12 +225,9 @@ esp_err_t esp_openthread_launch_mainloop(void)
|
||||
esp_openthread_lock_release();
|
||||
if (error != ESP_OK) {
|
||||
ESP_LOGE(OT_PLAT_LOG_TAG, "esp_openthread_platform_process failed");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
error = ESP_FAIL;
|
||||
ESP_LOGE(OT_PLAT_LOG_TAG, "OpenThread system polling failed");
|
||||
break;
|
||||
ESP_LOGE(OT_PLAT_LOG_TAG, "OpenThread system polling failed (errno: %d)", errno);
|
||||
}
|
||||
}
|
||||
#if CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
|
||||
|
||||
@@ -150,6 +150,9 @@ static esp_err_t process_thread_transmit(otInstance *instance)
|
||||
|
||||
int ret = read(s_openthread_netif_glue.event_fd, &event, sizeof(event));
|
||||
assert(ret == sizeof(event));
|
||||
if (s_packet_queue == NULL) {
|
||||
return ESP_OK;
|
||||
}
|
||||
while (xQueueReceive(s_packet_queue, &msg, 0) == pdTRUE) {
|
||||
if (msg) {
|
||||
otError ot_error = otIp6Send(esp_openthread_get_instance(), msg);
|
||||
@@ -179,9 +182,15 @@ static esp_err_t openthread_netif_transmit(void *handle, void *buffer, size_t le
|
||||
{
|
||||
esp_err_t error = ESP_OK;
|
||||
otError ot_error = OT_ERROR_NONE;
|
||||
otMessage *message = NULL;
|
||||
|
||||
esp_openthread_task_switching_lock_acquire(portMAX_DELAY);
|
||||
|
||||
if (s_packet_queue == NULL) {
|
||||
ESP_LOGW(OT_PLAT_LOG_TAG, "Thread netif transmit after glue deinit");
|
||||
ExitNow(error = ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
|
||||
otMessageSettings settings = {};
|
||||
switch (otThreadGetDeviceRole(esp_openthread_get_instance()))
|
||||
{
|
||||
@@ -195,7 +204,7 @@ static esp_err_t openthread_netif_transmit(void *handle, void *buffer, size_t le
|
||||
break;
|
||||
}
|
||||
|
||||
otMessage *message = otIp6NewMessage(esp_openthread_get_instance(), &settings);
|
||||
message = otIp6NewMessage(esp_openthread_get_instance(), &settings);
|
||||
if (message == NULL) {
|
||||
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to allocate OpenThread message");
|
||||
ExitNow(error = ESP_ERR_NO_MEM);
|
||||
@@ -359,22 +368,28 @@ exit:
|
||||
void esp_openthread_netif_glue_deinit(void)
|
||||
{
|
||||
otInstance *instance = esp_openthread_get_instance();
|
||||
otIp6SetAddressCallback(instance, NULL, NULL);
|
||||
otIp6SetReceiveCallback(instance, NULL, NULL);
|
||||
if (s_packet_queue) {
|
||||
vQueueDelete(s_packet_queue);
|
||||
s_packet_queue = NULL;
|
||||
if (s_openthread_netif) {
|
||||
esp_netif_action_stop(s_openthread_netif, OPENTHREAD_EVENT, OPENTHREAD_EVENT_STOP, NULL);
|
||||
s_openthread_netif = NULL;
|
||||
}
|
||||
unregister_openthread_event_handlers();
|
||||
esp_openthread_platform_workflow_unregister(netif_glue_workflow);
|
||||
if (s_openthread_netif_glue.event_fd >= 0) {
|
||||
close(s_openthread_netif_glue.event_fd);
|
||||
s_openthread_netif_glue.event_fd = -1;
|
||||
}
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_STOP, NULL, 0, 0) != ESP_OK) {
|
||||
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to stop OpenThread netif");
|
||||
otIp6SetReceiveCallback(instance, NULL, NULL);
|
||||
otIp6SetAddressCallback(instance, NULL, NULL);
|
||||
if (s_packet_queue) {
|
||||
otMessage *msg = NULL;
|
||||
while (xQueueReceive(s_packet_queue, &msg, 0) == pdTRUE) {
|
||||
if (msg) {
|
||||
otMessageFree(msg);
|
||||
}
|
||||
}
|
||||
vQueueDelete(s_packet_queue);
|
||||
s_packet_queue = NULL;
|
||||
}
|
||||
s_openthread_netif = NULL;
|
||||
unregister_openthread_event_handlers();
|
||||
esp_openthread_platform_workflow_unregister(netif_glue_workflow);
|
||||
}
|
||||
|
||||
void esp_openthread_netif_glue_update(esp_openthread_mainloop_context_t *mainloop)
|
||||
|
||||
@@ -33,15 +33,18 @@ static esp_openthread_platform_workflow_t *s_workflow_list = NULL;
|
||||
esp_err_t esp_openthread_platform_workflow_register(esp_openthread_update_func update_func,
|
||||
esp_openthread_process_func process_func, const char *name)
|
||||
{
|
||||
uint8_t name_len = strnlen(name, WORKFLOW_MAX_NAMELEN - 1);
|
||||
assert(name != NULL);
|
||||
size_t name_len = strlen(name);
|
||||
ESP_RETURN_ON_FALSE(name_len > 0 && name_len < WORKFLOW_MAX_NAMELEN, ESP_ERR_INVALID_ARG, OT_PLAT_LOG_TAG,
|
||||
"Workflow name '%s' is invalid", name);
|
||||
|
||||
esp_openthread_platform_workflow_t *current_workflow = s_workflow_list;
|
||||
esp_openthread_platform_workflow_t *before_workflow = NULL;
|
||||
esp_openthread_platform_workflow_t *add_workflow =
|
||||
static_cast<esp_openthread_platform_workflow_t *>(calloc(1, sizeof(esp_openthread_platform_workflow_t)));
|
||||
ESP_RETURN_ON_FALSE(add_workflow != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG,
|
||||
"Failed to alloc memory for esp_openthread_workflow");
|
||||
strncpy(add_workflow->name, name, name_len);
|
||||
add_workflow->name[name_len] = '\0';
|
||||
memcpy(add_workflow->name, name, name_len + 1);
|
||||
add_workflow->update_func = update_func;
|
||||
add_workflow->process_func = process_func;
|
||||
add_workflow->next = NULL;
|
||||
@@ -67,6 +70,9 @@ esp_err_t esp_openthread_platform_workflow_register(esp_openthread_update_func u
|
||||
|
||||
void esp_openthread_platform_workflow_unregister(const char *name)
|
||||
{
|
||||
if (name == NULL) {
|
||||
return;
|
||||
}
|
||||
esp_openthread_platform_workflow_t *current_workflow = s_workflow_list;
|
||||
esp_openthread_platform_workflow_t *before_workflow = NULL;
|
||||
while (current_workflow) {
|
||||
@@ -206,13 +212,17 @@ void esp_openthread_platform_update(esp_openthread_mainloop_context_t *mainloop)
|
||||
|
||||
esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop)
|
||||
{
|
||||
esp_err_t error = ESP_OK;
|
||||
esp_openthread_platform_workflow_t *current_workflow = s_workflow_list;
|
||||
while (current_workflow) {
|
||||
ESP_RETURN_ON_ERROR(current_workflow->process_func(instance, mainloop), OT_PLAT_LOG_TAG, "process %s failed",
|
||||
current_workflow->name);
|
||||
esp_err_t ret = current_workflow->process_func(instance, mainloop);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(OT_PLAT_LOG_TAG, "process %s failed", current_workflow->name);
|
||||
error = ret;
|
||||
}
|
||||
current_workflow = current_workflow->next;
|
||||
}
|
||||
return ESP_OK;
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t esp_openthread_get_alloc_caps(void)
|
||||
|
||||
@@ -63,9 +63,13 @@ esp_err_t IRAM_ATTR esp_openthread_task_queue_post(esp_openthread_task_t task, v
|
||||
BaseType_t task_woken = pdFALSE;
|
||||
|
||||
if (!xPortCanYield()) {
|
||||
ESP_RETURN_ON_FALSE_ISR(s_task_queue != NULL && s_task_queue_event_fd >= 0, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG,
|
||||
"OpenThread task queue not initialized");
|
||||
ESP_RETURN_ON_FALSE_ISR(xQueueSendFromISR(s_task_queue, &task_storage, &task_woken), ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||
"Failed to post task to OpenThread task queue");
|
||||
} else {
|
||||
ESP_RETURN_ON_FALSE(s_task_queue != NULL && s_task_queue_event_fd >= 0, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG,
|
||||
"OpenThread task queue not initialized");
|
||||
ESP_RETURN_ON_FALSE(xQueueSend(s_task_queue, &task_storage, OT_TASK_QUEUE_SENDING_WAIT_TIME), ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||
"Failed to post task to OpenThread task queue");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user