feat(openthread): add openthread start stop APIs

This commit is contained in:
Xu Si Yu
2025-06-11 17:56:57 +08:00
parent 9fe51958ae
commit c3035bb382
5 changed files with 155 additions and 3 deletions
+31 -1
View File
@@ -6,6 +6,28 @@ menu "OpenThread"
help
Select this option to enable OpenThread and show the submenu with OpenThread configuration choices.
menu "Thread Task Parameters"
depends on OPENTHREAD_ENABLED
config OPENTHREAD_TASK_NAME
string "OpenThread task name"
default "ot_main"
help
The OpenThread task name.
config OPENTHREAD_TASK_SIZE
int "Size of OpenThread task"
default 8192
help
The size in bytes of OpenThread task.
config OPENTHREAD_TASK_PRIORITY
int "Priority of OpenThread task"
default 5
help
The priority of OpenThread task.
endmenu
menu "Thread Version Message"
depends on OPENTHREAD_ENABLED
@@ -23,10 +45,18 @@ menu "OpenThread"
endmenu
menu "Thread Console"
depends on OPENTHREAD_ENABLED
config OPENTHREAD_CONSOLE_ENABLE
bool "Enable OpenThread console"
depends on OPENTHREAD_ENABLED
default y
help
Enable the OpenThread-specific console provided by the SDK. This only controls whether
the SDK sets up a dedicated console for OpenThread. Even if disabled, the default
ESP-IDF console (if initialized elsewhere) can still be used independently.
choice OPENTHREAD_CONSOLE_TYPE
prompt "OpenThread console type"
depends on OPENTHREAD_CONSOLE_ENABLE
default OPENTHREAD_CONSOLE_TYPE_UART
help
Select OpenThread console type
@@ -7,6 +7,7 @@
#pragma once
#include "esp_err.h"
#include "esp_netif.h"
#include "esp_openthread_types.h"
#include "openthread/dataset.h"
#include "openthread/error.h"
@@ -89,6 +90,29 @@ otInstance *esp_openthread_get_instance(void);
*/
esp_err_t esp_openthread_mainloop_exit(void);
/**
* @brief Starts the full OpenThread stack and create a handle task.
*
* @note The OpenThread instance will also be initialized in this function.
*
* @param[in] config The OpenThread platform configuration.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if already initialized
*
*/
esp_err_t esp_openthread_start(esp_openthread_platform_config_t *config);
/**
* @brief This function performs OpenThread stack and platform driver deinitialization and delete the handle task.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if Thread is already active
*
*/
esp_err_t esp_openthread_stop(void);
#ifdef __cplusplus
} // end of extern "C"
#endif
@@ -1,10 +1,11 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <spinel.h>
#include <esp_openthread.h>
#if CONFIG_OPENTHREAD_NCP_VENDOR_HOOK
@@ -15,3 +16,13 @@
#define SPINEL_PROP_VENDOR_ESP_COEX_EVENT (SPINEL_PROP_VENDOR_ESP__BEGIN + 3)
#endif
#ifdef __cplusplus
extern "C" {
#endif
void otAppNcpInit(otInstance *aInstance);
#ifdef __cplusplus
}
#endif
@@ -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
*/
@@ -4,12 +4,17 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "esp_openthread.h"
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "esp_openthread_border_router.h"
#include "esp_openthread_common_macro.h"
#include "esp_openthread_cli.h"
#include "esp_openthread_dns64.h"
#include "esp_openthread_lock.h"
#include "esp_openthread_ncp.h"
#include "esp_openthread_netif_glue.h"
#include "esp_openthread_platform.h"
#include "esp_openthread_sleep.h"
#include "esp_openthread_state.h"
@@ -18,15 +23,19 @@
#include "freertos/FreeRTOS.h"
#include "lwip/dns.h"
#include "openthread/instance.h"
#include "openthread/logging.h"
#include "openthread/netdata.h"
#include "openthread/tasklet.h"
#include "openthread/thread.h"
#include <cstddef>
#if CONFIG_OPENTHREAD_FTD
#include "openthread/dataset_ftd.h"
#endif
static bool s_ot_mainloop_running = false;
static SemaphoreHandle_t s_ot_syn_semaphore = NULL;
static TaskHandle_t s_ot_task_handle = NULL;
static int hex_digit_to_int(char hex)
{
@@ -223,3 +232,81 @@ esp_err_t esp_openthread_deinit(void)
otInstanceFinalize(esp_openthread_get_instance());
return esp_openthread_platform_deinit();
}
static void ot_task_worker(void *aContext)
{
esp_openthread_platform_config_t* config = (esp_openthread_platform_config_t *)aContext;
// Initialize the OpenThread stack
ESP_ERROR_CHECK(esp_openthread_init(config));
#if CONFIG_OPENTHREAD_FTD || CONFIG_OPENTHREAD_MTD
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
esp_netif_t *openthread_netif = esp_netif_new(&cfg);
assert(openthread_netif != NULL);
ESP_ERROR_CHECK(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(config)));
#endif
#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC
// The OpenThread log level directly matches ESP log level
(void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL);
#endif // CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC
#if CONFIG_OPENTHREAD_CLI
esp_openthread_cli_init();
esp_openthread_cli_console_command_register();
#endif // CONFIG_OPENTHREAD_CLI
xSemaphoreGive(s_ot_syn_semaphore);
#if CONFIG_OPENTHREAD_RADIO
otAppNcpInit(esp_openthread_get_instance());
#endif
// Run the main loop
esp_openthread_launch_mainloop();
#if CONFIG_OPENTHREAD_RADIO
ESP_LOGE(OT_PLAT_LOG_TAG, "RCP deinitialization is not supported for now");
assert(false);
#endif
#if CONFIG_OPENTHREAD_CLI
esp_openthread_cli_console_command_unregister();
#endif // CONFIG_OPENTHREAD_CLI
#if CONFIG_OPENTHREAD_FTD || CONFIG_OPENTHREAD_MTD
// Clean up
esp_openthread_netif_glue_deinit();
esp_netif_destroy(openthread_netif);
#endif
ESP_ERROR_CHECK(esp_openthread_deinit());
xSemaphoreGive(s_ot_syn_semaphore);
vTaskDelay(portMAX_DELAY);
}
esp_err_t esp_openthread_start(esp_openthread_platform_config_t *config)
{
ESP_RETURN_ON_FALSE(s_ot_syn_semaphore == NULL, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OpenThread has been initialized");
s_ot_syn_semaphore = xSemaphoreCreateBinary();
ESP_RETURN_ON_FALSE(s_ot_syn_semaphore != NULL, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "Failed to create s_ot_syn_semaphore");
assert(xTaskCreate(ot_task_worker, CONFIG_OPENTHREAD_TASK_NAME, CONFIG_OPENTHREAD_TASK_SIZE, config, CONFIG_OPENTHREAD_TASK_PRIORITY, &s_ot_task_handle) == pdPASS);
xSemaphoreTake(s_ot_syn_semaphore, portMAX_DELAY);
return ESP_OK;
}
esp_err_t esp_openthread_stop(void)
{
ESP_RETURN_ON_FALSE(s_ot_syn_semaphore != NULL, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OpenThread is not initialized");
esp_openthread_lock_acquire(portMAX_DELAY);
otInstance *instance = esp_openthread_get_instance();
bool is_thread_not_active = (otThreadGetDeviceRole(instance) == OT_DEVICE_ROLE_DISABLED && otIp6IsEnabled(instance) == false);
esp_openthread_lock_release();
ESP_RETURN_ON_FALSE(is_thread_not_active, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "Thread interface is still active");
esp_openthread_mainloop_exit();
xSemaphoreTake(s_ot_syn_semaphore, portMAX_DELAY);
vTaskDelete(s_ot_task_handle);
vSemaphoreDelete(s_ot_syn_semaphore);
s_ot_task_handle = NULL;
s_ot_syn_semaphore = NULL;
return ESP_OK;
}