diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 7d7c0ff0ab..99ed9fd364 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -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 diff --git a/components/openthread/include/esp_openthread.h b/components/openthread/include/esp_openthread.h index a3f0528f93..ce96d18656 100644 --- a/components/openthread/include/esp_openthread.h +++ b/components/openthread/include/esp_openthread.h @@ -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 diff --git a/components/openthread/private_include/esp_openthread_ncp.h b/components/openthread/private_include/esp_openthread_ncp.h index 507d305daa..65053bb56a 100644 --- a/components/openthread/private_include/esp_openthread_ncp.h +++ b/components/openthread/private_include/esp_openthread_ncp.h @@ -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 +#include #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 diff --git a/components/openthread/private_include/esp_openthread_platform.h b/components/openthread/private_include/esp_openthread_platform.h index 3999322a8d..582599f5d7 100644 --- a/components/openthread/private_include/esp_openthread_platform.h +++ b/components/openthread/private_include/esp_openthread_platform.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 */ diff --git a/components/openthread/src/esp_openthread.cpp b/components/openthread/src/esp_openthread.cpp index d816cd121d..e779959d25 100644 --- a/components/openthread/src/esp_openthread.cpp +++ b/components/openthread/src/esp_openthread.cpp @@ -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 #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; +} diff --git a/examples/openthread/ot_br/README.md b/examples/openthread/ot_br/README.md index 29f4f7b060..5f7f8ac010 100644 --- a/examples/openthread/ot_br/README.md +++ b/examples/openthread/ot_br/README.md @@ -56,11 +56,11 @@ In order to run the example on single SoC which supports both Wi-Fi and Thread, Two ways are provided to setup the Thread Border Router in this example: - Auto Start -Enable `OPENTHREAD_BR_AUTO_START`, configure the `CONFIG_EXAMPLE_WIFI_SSID` and `CONFIG_EXAMPLE_WIFI_PASSWORD` with your access point's ssid and psk. +Enable `OPENTHREAD_NETWORK_AUTO_START`, configure the `CONFIG_EXAMPLE_WIFI_SSID` and `CONFIG_EXAMPLE_WIFI_PASSWORD` with your access point's ssid and psk. The device will connect to Wi-Fi and form a Thread network automatically after boot up. - Manual mode -Disable `OPENTHREAD_BR_AUTO_START` and enable `OPENTHREAD_CLI_ESP_EXTENSION`. `wifi` command will be added for connecting the device to the Wi-Fi network. +Disable `OPENTHREAD_NETWORK_AUTO_START` and enable `OPENTHREAD_CLI_ESP_EXTENSION`. `wifi` command will be added for connecting the device to the Wi-Fi network. If the `CONFIG_EXAMPLE_CONNECT_ETHERNET` option is enabled, the device will connect to `Ethernet`, form a Thread network and act as a Ethernet based Thread Border Router. @@ -71,14 +71,14 @@ Build the project and flash it to the board, then run monitor tool to view seria ``` idf.py -p PORT build flash monitor ``` -If the `OPENTHREAD_BR_AUTO_START` option is enabled, The device will be connected to the configured Wi-Fi and Thread network automatically then act as the border router. +If the `OPENTHREAD_NETWORK_AUTO_START` option is enabled, The device will be connected to the configured Wi-Fi and Thread network automatically then act as the border router. Otherwise, you need to manually configure the networks with CLI commands. `wifi` command can be used to configure the Wi-Fi network. ```bash -> wifi +esp32s3> ot wifi --wifi parameter--- connect -s : wifi ssid @@ -96,7 +96,7 @@ Done To join a Wi-Fi network, please use the `wifi connect` command: ```bash -> wifi connect -s threadcertAP -p threadcertAP +esp32s3> ot wifi connect -s threadcertAP -p threadcertAP ssid: threadcertAP psk: threadcertAP I (11331) wifi:wifi driver task: 3ffd06e4, prio:23, stack:6656, core=0 @@ -117,7 +117,7 @@ Done To get the state of the Wi-Fi network: ```bash -> wifi state +esp32s3> ot wifi state connected Done ``` @@ -165,7 +165,7 @@ For mobile devices, the route table rules will be automatically configured after Now in the Thread end device, check the IP addresses: ``` -> ipaddr +esp32h2> ot ipaddr fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5 fdde:ad00:beef:0:0:ff:fe00:c402 fdde:ad00:beef:0:ad4a:9a9a:3cd6:e423 @@ -192,13 +192,13 @@ The newly introduced service registration protocol([SRP](https://datatracker.iet Now we'll publish the service `my-service._test._udp` with hostname `test0` and port 12345 ``` -> srp client host name test0 +esp32h2> ot srp client host name test0 Done -> srp client host address fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5 +esp32h2> ot srp client host address fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5 Done -> srp client service add my-service _test._udp 12345 +esp32h2> ot srp client service add my-service _test._udp 12345 Done -> srp client autostart enable +esp32h2> ot srp client autostart enable Done ``` @@ -233,7 +233,7 @@ Then get the border router's OMR prefix global unicast address(or ML-EID), and c On the border router: ``` -> ipaddr +esp32s3> ot ipaddr fdde:ad00:beef:0:0:ff:fe00:fc10 fd9b:347f:93f7:1:1003:8f00:bcc1:3038 fdde:ad00:beef:0:0:ff:fe00:fc00 @@ -245,19 +245,19 @@ Done On the Thread end device: ``` -> dns config fd9b:347f:93f7:1:1003:8f00:bcc1:3038 +esp32h2> ot dns config fd9b:347f:93f7:1:1003:8f00:bcc1:3038 (or -> dns config fdde:ad00:beef:0:f891:287:866:776) +esp32h2> ot dns config fdde:ad00:beef:0:f891:287:866:776) Done ``` Now the service published on the Host can be discovered on the Thread end device. ``` -> dns resolve FA001208.default.service.arpa. +esp32h2> ot dns resolve FA001208.default.service.arpa. DNS response for FA001208.default.service.arpa. - fdde:ad00:beef:cafe:b939:26be:7516:b87e TTL:120 Done -> dns browse _test._udp.default.service.arpa. +esp32h2> ot dns browse _test._udp.default.service.arpa. DNS browse response for _test._udp.default.service.arpa. testhost Port:5683, Priority:0, Weight:0, TTL:120 @@ -266,7 +266,7 @@ testhost TXT:[test=31, dn=616162626262] TTL:120 Done -> dns service testhost _test._udp.default.service.arpa. +esp32h2> ot dns service testhost _test._udp.default.service.arpa. DNS service resolution response for testhost for service _test._udp.default.service.arpa. Port:5683, Priority:0, Weight:0, TTL:120 Host:FA001208.default.service.arpa. diff --git a/examples/openthread/ot_br/main/Kconfig.projbuild b/examples/openthread/ot_br/main/Kconfig.projbuild index 45e682cb92..ca427f3498 100644 --- a/examples/openthread/ot_br/main/Kconfig.projbuild +++ b/examples/openthread/ot_br/main/Kconfig.projbuild @@ -1,13 +1,5 @@ menu "OpenThread Border Router Example" - config OPENTHREAD_BR_AUTO_START - bool 'Enable the automatic start mode in Thread Border Router.' - default n - help - If enabled, The Thread Border Router will connect to Wi-Fi with pre-configured - SSID and PSK, and then form a Thread network automatically. Otherwise, user need - to configure Wi-Fi and Thread manually. - config OPENTHREAD_SUPPORT_HW_RESET_RCP bool 'Enable hardware RCP resetting' default n @@ -20,33 +12,4 @@ menu "OpenThread Border Router Example" depends on OPENTHREAD_SUPPORT_HW_RESET_RCP default 7 - menu "External coexist wire type and pin config" - config EXTERNAL_COEX_WIRE_TYPE - int "The wire_type of external coexist" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE - default 3 - range 0 3 - help - Select wire_type for external coexist, the wire_type define in external_coex_wire_t. - - config EXTERNAL_COEX_REQUEST_PIN - int "The number of external coexist request pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 0) - default 0 - - config EXTERNAL_COEX_GRANT_PIN - int "The number of external coexist grant pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 1) - default 1 - - config EXTERNAL_COEX_PRIORITY_PIN - int "The number of external coexist priority pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 2) - default 2 - - config EXTERNAL_COEX_TX_LINE_PIN - int "The number of external coexist tx_line pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE = 3) - default 3 - endmenu # External coexist wire type and pin config endmenu diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index ffcfd39157..10da75c855 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -17,50 +17,31 @@ #include "sdkconfig.h" #include "esp_check.h" +#include "esp_coexist.h" #include "esp_err.h" #include "esp_event.h" #include "esp_log.h" #include "esp_netif.h" #include "esp_openthread.h" -#include "esp_openthread_border_router.h" -#include "esp_openthread_cli.h" #include "esp_openthread_lock.h" #include "esp_openthread_netif_glue.h" +#include "esp_openthread_spinel.h" #include "esp_openthread_types.h" #if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION #include "esp_ot_cli_extension.h" #endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION #include "esp_ot_config.h" -#include "esp_ot_wifi_cmd.h" #include "esp_vfs_dev.h" #include "esp_vfs_eventfd.h" -#include "esp_wifi.h" #include "mdns.h" #include "nvs_flash.h" -#include "protocol_examples_common.h" -#include "driver/gpio.h" -#include "driver/uart.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "hal/uart_types.h" -#include "openthread/error.h" -#include "openthread/logging.h" -#include "openthread/tasklet.h" +#include "ot_examples_br.h" +#include "ot_examples_common.h" #if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE #include "ot_led_strip.h" #endif -#if CONFIG_OPENTHREAD_BR_AUTO_START -#include "example_common_private.h" -#include "protocol_examples_common.h" -#endif - -#if !CONFIG_OPENTHREAD_BR_AUTO_START && CONFIG_EXAMPLE_CONNECT_ETHERNET -// TZ-1109: Add a menchanism for connecting ETH manually. -#error Currently we do not support a manual way to connect ETH, if you want to use ETH, please enable OPENTHREAD_BR_AUTO_START. -#endif - #define TAG "esp_ot_br" #if CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP @@ -83,116 +64,6 @@ static void rcp_failure_hardware_reset_handler(void) } #endif -#if CONFIG_EXTERNAL_COEX_ENABLE -static void ot_br_external_coexist_init(void) -{ - esp_external_coex_gpio_set_t gpio_pin = ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG(); - esp_external_coex_set_work_mode(EXTERNAL_COEX_LEADER_ROLE); - ESP_ERROR_CHECK(esp_enable_extern_coex_gpio_pin(CONFIG_EXTERNAL_COEX_WIRE_TYPE, gpio_pin)); -} -#endif /* CONFIG_EXTERNAL_COEX_ENABLE */ - -static void ot_task_worker(void *aContext) -{ - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), - }; - - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - esp_netif_t *openthread_netif = esp_netif_new(&cfg); - assert(openthread_netif != NULL); - - // Initialize the OpenThread stack - ESP_ERROR_CHECK(esp_openthread_init(&config)); - ESP_ERROR_CHECK(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&config))); - esp_openthread_lock_acquire(portMAX_DELAY); -#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(); -#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - esp_cli_custom_command_init(); -#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - esp_openthread_cli_create_task(); -#endif // CONFIG_OPENTHREAD_CLI - esp_openthread_lock_release(); - - // Run the main loop - esp_openthread_launch_mainloop(); - - // Clean up - esp_openthread_netif_glue_deinit(); - esp_netif_destroy(openthread_netif); - esp_vfs_eventfd_unregister(); - vTaskDelete(NULL); -} - -void ot_br_init(void *ctx) -{ -#if CONFIG_OPENTHREAD_CLI_WIFI - ESP_ERROR_CHECK(esp_ot_wifi_config_init()); -#endif -#if CONFIG_OPENTHREAD_BR_AUTO_START -#if CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET - bool wifi_or_ethernet_connected = false; -#else -#error No backbone netif! -#endif -#if CONFIG_EXAMPLE_CONNECT_WIFI - char wifi_ssid[32] = ""; - char wifi_password[64] = ""; - if (esp_ot_wifi_config_get_ssid(wifi_ssid) == ESP_OK) { - ESP_LOGI(TAG, "use the Wi-Fi config from NVS"); - esp_ot_wifi_config_get_password(wifi_password); - } else { - ESP_LOGI(TAG, "use the Wi-Fi config from Kconfig"); - strcpy(wifi_ssid, CONFIG_EXAMPLE_WIFI_SSID); - strcpy(wifi_password, CONFIG_EXAMPLE_WIFI_PASSWORD); - } - if (esp_ot_wifi_connect(wifi_ssid, wifi_password) == ESP_OK) { - wifi_or_ethernet_connected = true; - } else { - ESP_LOGE(TAG, "Fail to connect to Wi-Fi, please try again manually"); - } -#endif -#if CONFIG_EXAMPLE_CONNECT_ETHERNET - ESP_ERROR_CHECK(example_ethernet_connect()); - wifi_or_ethernet_connected = true; -#endif -#endif // CONFIG_OPENTHREAD_BR_AUTO_START - -#if CONFIG_EXTERNAL_COEX_ENABLE - ot_br_external_coexist_init(); -#endif // CONFIG_EXTERNAL_COEX_ENABLE - ESP_ERROR_CHECK(mdns_init()); - ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br")); - - esp_openthread_lock_acquire(portMAX_DELAY); -#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE - ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); -#endif -#if CONFIG_OPENTHREAD_BR_AUTO_START - if (wifi_or_ethernet_connected) { - esp_openthread_set_backbone_netif(get_example_netif()); - ESP_ERROR_CHECK(esp_openthread_border_router_init()); -#if CONFIG_EXAMPLE_CONNECT_WIFI - esp_ot_wifi_border_router_init_flag_set(true); -#endif - otOperationalDatasetTlvs dataset; - otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); - ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); - } else { - ESP_LOGE(TAG, "Auto-start mode failed, please try to start manually"); - } -#endif // CONFIG_OPENTHREAD_BR_AUTO_START - esp_openthread_lock_release(); - vTaskDelete(NULL); -} - void app_main(void) { // Used eventfds: @@ -218,9 +89,38 @@ void app_main(void) ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(mdns_init()); + ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br")); #if CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP esp_openthread_register_rcp_failure_handler(rcp_failure_hardware_reset_handler); #endif - xTaskCreate(ot_task_worker, "ot_br_main", 8192, xTaskGetCurrentTaskHandle(), 5, NULL); - xTaskCreate(ot_br_init, "ot_br_init", 6144, NULL, 4, NULL); + +#if CONFIG_OPENTHREAD_CLI + ot_console_start(); +#endif + +#if CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE + ot_external_coexist_init(); +#endif + + static esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + + ESP_ERROR_CHECK(esp_openthread_start(&config)); + esp_netif_set_default_netif(esp_openthread_get_netif()); +#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION + esp_cli_custom_command_init(); +#endif +#if CONFIG_OPENTHREAD_BORDER_ROUTER_AUTO_START + ESP_ERROR_CHECK(esp_openthread_border_router_start()); +#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE && CONFIG_SOC_IEEE802154_SUPPORTED + ESP_ERROR_CHECK(esp_coex_wifi_i154_enable()); +#endif +#endif +#if CONFIG_OPENTHREAD_NETWORK_AUTO_START + ot_network_auto_start(); +#endif } diff --git a/examples/openthread/ot_br/main/esp_ot_config.h b/examples/openthread/ot_br/main/esp_ot_config.h index b7372f4943..a1670b0c18 100644 --- a/examples/openthread/ot_br/main/esp_ot_config.h +++ b/examples/openthread/ot_br/main/esp_ot_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -68,39 +68,10 @@ } #endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI -#if CONFIG_IDF_TARGET_ESP32C2 && CONFIG_XTAL_FREQ_26 -#define HOST_BAUD_RATE 74880 -#else -#define HOST_BAUD_RATE 115200 -#endif - -#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART -#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ - .host_uart_config = { \ - .port = 0, \ - .uart_config = \ - { \ - .baud_rate = HOST_BAUD_RATE, \ - .data_bits = UART_DATA_8_BITS, \ - .parity = UART_PARITY_DISABLE, \ - .stop_bits = UART_STOP_BITS_1, \ - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ - .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_DEFAULT, \ - }, \ - .rx_pin = UART_PIN_NO_CHANGE, \ - .tx_pin = UART_PIN_NO_CHANGE, \ - }, \ - } -#elif CONFIG_OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG #define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_USB, \ - .host_usb_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(), \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ } -#endif #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \ @@ -108,33 +79,3 @@ .netif_queue_size = 10, \ .task_queue_size = 10, \ } - -#if CONFIG_EXTERNAL_COEX_ENABLE -#if CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_1 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - } -#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_2 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ - } -#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_3 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - .priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \ - .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ - } -#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_4 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - .priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \ - .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ - .tx_line = CONFIG_EXTERNAL_COEX_TX_LINE_PIN, \ - } -#endif -#endif // CONFIG_EXTERNAL_COEX_ENABLE diff --git a/examples/openthread/ot_br/main/idf_component.yml b/examples/openthread/ot_br/main/idf_component.yml index dff9291048..b00b26c7bb 100644 --- a/examples/openthread/ot_br/main/idf_component.yml +++ b/examples/openthread/ot_br/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.3.0" + version: "~1.4.0" espressif/mdns: "^1.0.3" ## Required IDF version idf: @@ -10,3 +10,7 @@ dependencies: path: ${IDF_PATH}/examples/common_components/protocol_examples_common ot_led: path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led + ot_examples_br: + path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_examples_br + ot_examples_common: + path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_examples_common diff --git a/examples/openthread/ot_br/sdkconfig.ci.ext_coex b/examples/openthread/ot_br/sdkconfig.ci.ext_coex index 10e03f180e..aa39569575 100644 --- a/examples/openthread/ot_br/sdkconfig.ci.ext_coex +++ b/examples/openthread/ot_br/sdkconfig.ci.ext_coex @@ -1,2 +1,2 @@ -CONFIG_EXTERNAL_COEX_ENABLE=y +CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE=y CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n diff --git a/examples/openthread/ot_br/sdkconfig.ci.spinel_trel_ext_coex b/examples/openthread/ot_br/sdkconfig.ci.spinel_trel_ext_coex index 571881d7f6..8fd4485992 100644 --- a/examples/openthread/ot_br/sdkconfig.ci.spinel_trel_ext_coex +++ b/examples/openthread/ot_br/sdkconfig.ci.spinel_trel_ext_coex @@ -1,2 +1,2 @@ CONFIG_OPENTHREAD_RADIO_TREL=y -CONFIG_EXTERNAL_COEX_ENABLE=y +CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE=y diff --git a/examples/openthread/ot_br/sdkconfig.defaults b/examples/openthread/ot_br/sdkconfig.defaults index 2b17031c2b..7fe886d91f 100644 --- a/examples/openthread/ot_br/sdkconfig.defaults +++ b/examples/openthread/ot_br/sdkconfig.defaults @@ -25,6 +25,8 @@ CONFIG_MBEDTLS_ECJPAKE_C=y CONFIG_OPENTHREAD_ENABLED=y CONFIG_OPENTHREAD_BORDER_ROUTER=y CONFIG_OPENTHREAD_RADIO_SPINEL_UART=y +CONFIG_OPENTHREAD_TASK_SIZE=8192 +CONFIG_OPENTHREAD_CONSOLE_ENABLE=n # end of OpenThread # @@ -54,4 +56,5 @@ CONFIG_EXAMPLE_CONNECT_THREAD=n # ESP System Settings # CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6144 # end of ESP System Settings diff --git a/examples/openthread/ot_br/sdkconfig.defaults.esp32p4 b/examples/openthread/ot_br/sdkconfig.defaults.esp32p4 index 0bf7855bcc..3b161864c7 100644 --- a/examples/openthread/ot_br/sdkconfig.defaults.esp32p4 +++ b/examples/openthread/ot_br/sdkconfig.defaults.esp32p4 @@ -1,5 +1,6 @@ # Enable BR auto start for Ethernet builds -CONFIG_OPENTHREAD_BR_AUTO_START=y +CONFIG_OPENTHREAD_NETWORK_AUTO_START=y +CONFIG_OPENTHREAD_BORDER_ROUTER_AUTO_START=y # Enable PPP support as a workaround to ensure LWIP thread-lib compatibility for Ethernet builds CONFIG_LWIP_PPP_SUPPORT=y diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index 6b8e9567f5..2b267e62ec 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -8,9 +8,8 @@ import socket import struct import subprocess import time +from collections.abc import Callable from functools import wraps -from typing import Callable -from typing import Tuple import netifaces import pexpect @@ -133,7 +132,7 @@ def wait_for_join(dut: IdfDut, role: str) -> bool: return False -def joinWiFiNetwork(dut: IdfDut, wifi: wifi_parameter) -> Tuple[str, int]: +def joinWiFiNetwork(dut: IdfDut, wifi: wifi_parameter) -> tuple[str, int]: clean_buffer(dut) ip_address = '' for order in range(1, wifi.retry_times): @@ -168,7 +167,7 @@ def getDataset(dut: IdfDut) -> str: def init_thread(dut: IdfDut) -> None: - dut.expect('>', timeout=10) + dut.expect('OpenThread attached to netif', timeout=10) wait(dut, 3) reset_thread(dut) @@ -176,7 +175,6 @@ def init_thread(dut: IdfDut) -> None: def reset_thread(dut: IdfDut) -> None: execute_command(dut, 'factoryreset') dut.expect('OpenThread attached to netif', timeout=20) - dut.expect('>', timeout=10) wait(dut, 3) clean_buffer(dut) @@ -186,7 +184,7 @@ def get_mleid_addr(dut: IdfDut) -> str: dut_adress = '' execute_command(dut, 'ipaddr mleid') dut_adress = dut.expect(r'\n((?:\w+:){7}\w+)\r', timeout=5)[1].decode() - return dut_adress + return str(dut_adress) # get the rloc address of the thread @@ -194,7 +192,7 @@ def get_rloc_addr(dut: IdfDut) -> str: dut_adress = '' execute_command(dut, 'ipaddr rloc') dut_adress = dut.expect(r'\n((?:\w+:){7}\w+)\r', timeout=5)[1].decode() - return dut_adress + return str(dut_adress) # get the linklocal address of the thread @@ -202,7 +200,7 @@ def get_linklocal_addr(dut: IdfDut) -> str: dut_adress = '' execute_command(dut, 'ipaddr linklocal') dut_adress = dut.expect(r'\n((?:\w+:){7}\w+)\r', timeout=5)[1].decode() - return dut_adress + return str(dut_adress) # get the global unicast address of the thread: @@ -211,8 +209,8 @@ def get_global_unicast_addr(dut: IdfDut, br: IdfDut) -> str: clean_buffer(br) omrprefix = get_omrprefix(br) execute_command(dut, 'ipaddr') - dut_adress = dut.expect(r'(%s(?:\w+:){3}\w+)\r' % str(omrprefix), timeout=5)[1].decode() - return dut_adress + dut_adress = dut.expect(rf'({omrprefix}(?:\w+:){{3}}\w+)\r', timeout=5)[1].decode() + return str(dut_adress) @extract_address('rloc16', r'(\w{4})') @@ -223,7 +221,7 @@ def get_rloc16_addr(rloc16: str) -> str: # ping of thread def ot_ping( dut: IdfDut, target: str, timeout: int = 5, count: int = 1, size: int = 56, interval: int = 1, hoplimit: int = 64 -) -> Tuple[int, int]: +) -> tuple[int, int]: command = f'ping {str(target)} {size} {count} {interval} {hoplimit} {str(timeout)}' execute_command(dut, command) transmitted = dut.expect(r'(\d+) packets transmitted', timeout=60)[1].decode() @@ -307,7 +305,7 @@ def get_host_interface_name() -> str: config_path = os.path.join(home_dir, 'config', 'env_config.yml') try: if os.path.exists(config_path): - with open(config_path, 'r') as file: + with open(config_path) as file: config = yaml.safe_load(file) interface_name = config.get('interface_name') if interface_name: @@ -331,7 +329,7 @@ def get_host_interface_name() -> str: def clean_buffer(dut: IdfDut) -> None: str_length = str(len(dut.expect(pexpect.TIMEOUT, timeout=0.1))) - dut.expect(r'[\s\S]{%s}' % str(str_length), timeout=10) + dut.expect(rf'[\s\S]{{{str_length}}}', timeout=10) def check_if_host_receive_ra(br: IdfDut) -> bool: @@ -422,7 +420,7 @@ def create_host_udp_server(myudp: udp_parameter) -> None: print('The host start to receive message!') myudp.udp_bytes = (sock.recvfrom(1024))[0] print('The host has received message: ', myudp.udp_bytes) - except socket.error: + except OSError: print('The host did not receive message!') finally: print('Close the socket.') @@ -442,7 +440,7 @@ def host_udp_send_message(udp_target: udp_parameter) -> None: sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 32) print('Host is sending message') sock.sendto(udp_target.udp_bytes, (udp_target.addr, udp_target.port)) - except socket.error: + except OSError: print('Host cannot send message') finally: sock.close() @@ -459,7 +457,7 @@ def get_host_ipv4_address() -> str: out_str = out_bytes.decode('utf-8') host_ipv4_address = '' host_ipv4_address = re.findall(r'((?:\d+.){3}\d+)', str(out_str))[0] - return host_ipv4_address + return str(host_ipv4_address) def restart_avahi() -> None: @@ -592,7 +590,7 @@ def create_host_tcp_server(mytcp: tcp_parameter) -> None: mytcp.tcp_bytes = connfd.recv(1024) print('The tcp server has received message: ', mytcp.tcp_bytes) - except socket.error: + except OSError: if mytcp.recv_flag: print('The tcp server did not receive message!') else: @@ -636,9 +634,9 @@ def get_nat64prefix(br: IdfDut) -> str: return str(nat64prefix) -def execute_command(dut: IdfDut, command: str) -> None: +def execute_command(dut: IdfDut, command: str, prefix: str = 'ot ') -> None: clean_buffer(dut) - dut.write(command) + dut.write(prefix + command) def get_ouput_string(dut: IdfDut, command: str, wait_time: int) -> str: diff --git a/examples/openthread/ot_cli/README.md b/examples/openthread/ot_cli/README.md index 2a02e8b89b..4ffe0a0131 100644 --- a/examples/openthread/ot_cli/README.md +++ b/examples/openthread/ot_cli/README.md @@ -37,7 +37,7 @@ Now you'll get an OpenThread command line shell. The `help` command will print all of the supported commands. ```bash -> help +esp32h2> ot help I(7058) OPENTHREAD:[INFO]-CLI-----: execute command: help bbr bufferinfo @@ -71,51 +71,51 @@ To run this example, at least two ESP32-H2 boards flashed with this ot_cli examp On the first device, run the following commands: ```bash -> factoryreset +esp32h2> ot factoryreset ... # the device will reboot -> dataset init new +esp32h2> ot dataset init new Done -> dataset commit active +esp32h2> ot dataset commit active Done -> ifconfig up +esp32h2> ot ifconfig up Done -> thread start +esp32h2> ot thread start Done # After some seconds -> state +esp32h2> ot state leader Done ``` Now the first device has formed a Thread network as a leader. Get some information which will be used in next steps: ```bash -> ipaddr +esp32h2> ot ipaddr fdde:ad00:beef:0:0:ff:fe00:fc00 fdde:ad00:beef:0:0:ff:fe00:8000 fdde:ad00:beef:0:a7c6:6311:9c8c:271b fe80:0:0:0:5c27:a723:7115:c8f8 # Get the Active Dataset -> dataset active -x +esp32h2> ot dataset active -x 0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 ``` On the second device, set the active dataset from leader, and start Thread interface: ```bash -> factoryreset +esp32h2> ot factoryreset ... # the device will reboot -> dataset set active 0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 -> ifconfig up +esp32h2> ot dataset set active 0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 +esp32h2> ot ifconfig up Done -> thread start +esp32h2> ot thread start Done # After some seconds -> state +esp32h2> ot state router # child is also a valid state Done ``` diff --git a/examples/openthread/ot_cli/main/Kconfig.projbuild b/examples/openthread/ot_cli/main/Kconfig.projbuild deleted file mode 100644 index 23aba5e8ce..0000000000 --- a/examples/openthread/ot_cli/main/Kconfig.projbuild +++ /dev/null @@ -1,9 +0,0 @@ -menu "OpenThread CLI Example" - - config OPENTHREAD_AUTO_START - bool 'Enable the automatic start mode.' - default n - help - If enabled, the Openthread Device will create or connect to thread network with pre-configured - network parameters automatically. Otherwise, user need to configure Thread via CLI command manually. -endmenu diff --git a/examples/openthread/ot_cli/main/esp_ot_cli.c b/examples/openthread/ot_cli/main/esp_ot_cli.c index 96a8d1e22c..c2717a4c21 100644 --- a/examples/openthread/ot_cli/main/esp_ot_cli.c +++ b/examples/openthread/ot_cli/main/esp_ot_cli.c @@ -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: CC0-1.0 * @@ -23,21 +23,12 @@ #include "esp_netif.h" #include "esp_netif_types.h" #include "esp_openthread.h" -#include "esp_openthread_cli.h" #include "esp_openthread_lock.h" -#include "esp_openthread_netif_glue.h" #include "esp_openthread_types.h" #include "esp_ot_config.h" #include "esp_vfs_eventfd.h" -#include "driver/uart.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "hal/uart_types.h" #include "nvs_flash.h" -#include "openthread/cli.h" -#include "openthread/instance.h" -#include "openthread/logging.h" -#include "openthread/tasklet.h" +#include "ot_examples_common.h" #if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE #include "ot_led_strip.h" @@ -49,68 +40,6 @@ #define TAG "ot_esp_cli" -static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) -{ - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - esp_netif_t *netif = esp_netif_new(&cfg); - assert(netif != NULL); - ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config))); - - return netif; -} - -static void ot_task_worker(void *aContext) -{ - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), - }; - - // Initialize the OpenThread stack - ESP_ERROR_CHECK(esp_openthread_init(&config)); - -#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE - ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); -#endif - -#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC - // The OpenThread log level directly matches ESP log level - (void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL); -#endif - // Initialize the OpenThread cli -#if CONFIG_OPENTHREAD_CLI - esp_openthread_cli_init(); -#endif - - esp_netif_t *openthread_netif; - // Initialize the esp_netif bindings - openthread_netif = init_openthread_netif(&config); - esp_netif_set_default_netif(openthread_netif); - -#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - esp_cli_custom_command_init(); -#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - - // Run the main loop -#if CONFIG_OPENTHREAD_CLI - esp_openthread_cli_create_task(); -#endif -#if CONFIG_OPENTHREAD_AUTO_START - otOperationalDatasetTlvs dataset; - otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); - ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); -#endif - esp_openthread_launch_mainloop(); - - // Clean up - esp_openthread_netif_glue_deinit(); - esp_netif_destroy(openthread_netif); - - esp_vfs_eventfd_unregister(); - vTaskDelete(NULL); -} - void app_main(void) { // Used eventfds: @@ -125,5 +54,22 @@ void app_main(void) ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); - xTaskCreate(ot_task_worker, "ot_cli_main", 10240, xTaskGetCurrentTaskHandle(), 5, NULL); + +#if CONFIG_OPENTHREAD_CLI + ot_console_start(); +#endif + + esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + + ESP_ERROR_CHECK(esp_openthread_start(&config)); +#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION + esp_cli_custom_command_init(); +#endif +#if CONFIG_OPENTHREAD_NETWORK_AUTO_START + ot_network_auto_start(); +#endif } diff --git a/examples/openthread/ot_cli/main/esp_ot_config.h b/examples/openthread/ot_cli/main/esp_ot_config.h index 0248a39af1..cd509e9e17 100644 --- a/examples/openthread/ot_cli/main/esp_ot_config.h +++ b/examples/openthread/ot_cli/main/esp_ot_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -44,33 +44,10 @@ } #endif -#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART -#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ - .host_uart_config = { \ - .port = 0, \ - .uart_config = \ - { \ - .baud_rate = 115200, \ - .data_bits = UART_DATA_8_BITS, \ - .parity = UART_PARITY_DISABLE, \ - .stop_bits = UART_STOP_BITS_1, \ - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ - .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_DEFAULT, \ - }, \ - .rx_pin = UART_PIN_NO_CHANGE, \ - .tx_pin = UART_PIN_NO_CHANGE, \ - }, \ - } -#elif CONFIG_OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG #define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_USB, \ - .host_usb_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(), \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ } -#endif #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \ diff --git a/examples/openthread/ot_cli/main/idf_component.yml b/examples/openthread/ot_cli/main/idf_component.yml index 06b75f0c81..079266490f 100644 --- a/examples/openthread/ot_cli/main/idf_component.yml +++ b/examples/openthread/ot_cli/main/idf_component.yml @@ -1,8 +1,10 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.2.0" + version: "~1.4.0" idf: version: ">=4.1.0" ot_led: path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led + ot_examples_common: + path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_examples_common diff --git a/examples/openthread/ot_cli/sdkconfig.ci.ext_coex b/examples/openthread/ot_cli/sdkconfig.ci.ext_coex index 55c9b2374f..6b04e74e9d 100644 --- a/examples/openthread/ot_cli/sdkconfig.ci.ext_coex +++ b/examples/openthread/ot_cli/sdkconfig.ci.ext_coex @@ -1 +1 @@ -CONFIG_EXTERNAL_COEX_ENABLE=y +CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE=y diff --git a/examples/openthread/ot_cli/sdkconfig.defaults b/examples/openthread/ot_cli/sdkconfig.defaults index 7b724c1c89..f8fd9ed374 100644 --- a/examples/openthread/ot_cli/sdkconfig.defaults +++ b/examples/openthread/ot_cli/sdkconfig.defaults @@ -23,6 +23,8 @@ CONFIG_MBEDTLS_ECJPAKE_C=y CONFIG_OPENTHREAD_ENABLED=y CONFIG_OPENTHREAD_BORDER_ROUTER=n CONFIG_OPENTHREAD_DNS64_CLIENT=y +CONFIG_OPENTHREAD_TASK_SIZE=10240 +CONFIG_OPENTHREAD_CONSOLE_ENABLE=n # end of OpenThread # @@ -33,3 +35,9 @@ CONFIG_LWIP_IPV6_NUM_ADDRESSES=8 CONFIG_LWIP_MULTICAST_PING=y CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM=y # end of lwIP + +# +# ESP System Settings +# +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6144 +# end of ESP System Settings diff --git a/examples/openthread/ot_common_components/ot_examples_br/CMakeLists.txt b/examples/openthread/ot_common_components/ot_examples_br/CMakeLists.txt new file mode 100644 index 0000000000..fbda672d96 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_br/CMakeLists.txt @@ -0,0 +1,9 @@ +set(srcs "") + +if(CONFIG_OPENTHREAD_BORDER_ROUTER_AUTO_START) + list(APPEND srcs "ot_examples_br.c") +endif() + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "include" + PRIV_REQUIRES openthread protocol_examples_common) diff --git a/examples/openthread/ot_common_components/ot_examples_br/Kconfig.projbuild b/examples/openthread/ot_common_components/ot_examples_br/Kconfig.projbuild new file mode 100644 index 0000000000..2835110a1f --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_br/Kconfig.projbuild @@ -0,0 +1,12 @@ +menu "OpenThread Border Router Config" + depends on OPENTHREAD_BORDER_ROUTER + + config OPENTHREAD_BORDER_ROUTER_AUTO_START + depends on OPENTHREAD_BORDER_ROUTER + bool 'Enable the border router auto start' + default n + help + If enabled, the program will automatically connect to the backbone network and + initialize the border router at startup. + +endmenu diff --git a/examples/openthread/ot_common_components/ot_examples_br/include/ot_examples_br.h b/examples/openthread/ot_common_components/ot_examples_br/include/ot_examples_br.h new file mode 100644 index 0000000000..6851bfdbb7 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_br/include/ot_examples_br.h @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * OpenThread Command Line Example + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "esp_err.h" +#include "esp_openthread.h" + +/** + * @brief Start the border router features of OpenThread. + * + * @note Calling this function will make the device connect to the Wi-Fi or Ethernet, + * and initialize the border router feature. + * + * @return + * - ESP_OK on success. + * - ESP_FAIL on failure. + * + */ +esp_err_t esp_openthread_border_router_start(void); + +/** + * @brief Stop the border router features of OpenThread. + * + * @note Calling this function will make the device deinitialize the border router feature. + * + */ +void esp_openthread_border_router_stop(void); diff --git a/examples/openthread/ot_common_components/ot_examples_br/ot_examples_br.c b/examples/openthread/ot_common_components/ot_examples_br/ot_examples_br.c new file mode 100644 index 0000000000..77ef1d1900 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_br/ot_examples_br.c @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * OpenThread Command Line Example + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "ot_examples_br.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_openthread.h" +#include "esp_openthread_lock.h" +#include "esp_openthread_border_router.h" +#include "protocol_examples_common.h" + +#define TAG "ot_examples_br" + +#if CONFIG_OPENTHREAD_CLI_WIFI +#error "CONFIG_OPENTHREAD_CLI_WIFI conflicts with the border router auto-initialization feature" +#endif + +static bool s_border_router_started = false; + +static void ot_br_init(void *ctx) +{ + ESP_ERROR_CHECK(example_connect()); + esp_openthread_lock_acquire(portMAX_DELAY); + esp_openthread_set_backbone_netif(get_example_netif()); + ESP_ERROR_CHECK(esp_openthread_border_router_init()); + esp_openthread_lock_release(); + s_border_router_started = true; + vTaskDelete(NULL); +} + +esp_err_t esp_openthread_border_router_start(void) +{ + return (xTaskCreate(ot_br_init, "ot_br_init", 6144, NULL, 4, NULL) == pdPASS) ? ESP_OK : ESP_FAIL; +} + +void esp_openthread_border_router_stop(void) +{ + if (s_border_router_started) { + esp_openthread_lock_acquire(portMAX_DELAY); + ESP_ERROR_CHECK(esp_openthread_border_router_deinit()); + esp_openthread_lock_release(); + s_border_router_started =false; + } +} diff --git a/examples/openthread/ot_common_components/ot_examples_common/CMakeLists.txt b/examples/openthread/ot_common_components/ot_examples_common/CMakeLists.txt new file mode 100644 index 0000000000..321063eb94 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_common/CMakeLists.txt @@ -0,0 +1,19 @@ +set(srcs "") + +if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD) + list(APPEND srcs "ot_network.c") +endif() + +if(CONFIG_OPENTHREAD_CLI) + list(APPEND srcs "ot_console.c") +endif() + +if(CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE) + list(APPEND srcs "ot_external_coexist.c") +endif() + +idf_component_register( + SRCS "${srcs}" + INCLUDE_DIRS "include" + PRIV_REQUIRES console cmd_system esp_coex openthread +) diff --git a/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild b/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild new file mode 100644 index 0000000000..94e38cf6c1 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild @@ -0,0 +1,67 @@ +menu "Config for OpenThread Examples" + depends on OPENTHREAD_ENABLED + + config OPENTHREAD_NETWORK_AUTO_START + bool 'Enable the automatic start mode of Thread network.' + depends on OPENTHREAD_FTD || OPENTHREAD_MTD + default n + help + If enabled, the Openthread Device will create or connect to Thread network with pre-configured + network parameters automatically. Otherwise, user need to configure Thread via CLI command manually. + + menu "External coexist wire type and pin config" + depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE + + choice EXTERNAL_COEX_WORK_MODE + prompt "The work mode of external coexist" + default EXTERNAL_COEX_WORK_MODE_FOLLOWER if SOC_IEEE802154_SUPPORTED + default EXTERNAL_COEX_WORK_MODE_LEADER if !SOC_IEEE802154_SUPPORTED && SOC_WIFI_SUPPORTED + help + Select work mode for external coexist, the work mode defined in esp_extern_coex_work_mode_t. + + config EXTERNAL_COEX_WORK_MODE_LEADER + bool "Leader mode" + help + Select this to set the external coexistence work mode to leader mode. + + config EXTERNAL_COEX_WORK_MODE_FOLLOWER + bool "Follower mode" + help + Select this to set the external coexistence work mode to follower mode. + + config EXTERNAL_COEX_WORK_MODE_UNKNOWN + bool "Unknown mode" + help + Select this to set the external coexistence work mode to unknown mode. + endchoice + + config EXTERNAL_COEX_WIRE_TYPE + int "The wire_type of external coexist" + depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE + default 3 + range 0 3 + help + Select wire_type for external coexist, the wire_type define in external_coex_wire_t. + + config EXTERNAL_COEX_REQUEST_PIN + int "The number of external coexist request pin" + depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 0) + default 0 + + config EXTERNAL_COEX_GRANT_PIN + int "The number of external coexist grant pin" + depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 1) + default 1 + + config EXTERNAL_COEX_PRIORITY_PIN + int "The number of external coexist priority pin" + depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 2) + default 2 + + config EXTERNAL_COEX_TX_LINE_PIN + int "The number of external coexist tx_line pin" + depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE = 3) + default 3 + endmenu # External coexist wire type and pin config + +endmenu diff --git a/examples/openthread/ot_common_components/ot_examples_common/idf_component.yml b/examples/openthread/ot_common_components/ot_examples_common/idf_component.yml new file mode 100644 index 0000000000..77b231f2a7 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_common/idf_component.yml @@ -0,0 +1,4 @@ +## IDF Component Manager Manifest File +dependencies: + cmd_system: + path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system diff --git a/examples/openthread/ot_common_components/ot_examples_common/include/ot_examples_common.h b/examples/openthread/ot_common_components/ot_examples_common/include/ot_examples_common.h new file mode 100644 index 0000000000..9c7ab22964 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_common/include/ot_examples_common.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * OpenThread Command Line Example + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "sdkconfig.h" + +#if CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE +#if CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_1 +#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ + { \ + .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ + } +#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_2 +#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ + { \ + .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ + .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ + } +#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_3 +#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ + { \ + .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ + .priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \ + .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ + } +#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_4 +#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ + { \ + .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ + .priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \ + .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ + .tx_line = CONFIG_EXTERNAL_COEX_TX_LINE_PIN, \ + } +#endif +#endif // CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE + +/** + * @brief Initializes the external coexistence. + * + */ +void ot_external_coexist_init(void); + +/** + * @brief Initializes the console. + * + */ +void ot_console_start(void); + +/** + * @brief Form or join the Thread network automatically. + * + */ +void ot_network_auto_start(void); diff --git a/examples/openthread/ot_common_components/ot_examples_common/ot_console.c b/examples/openthread/ot_common_components/ot_examples_common/ot_console.c new file mode 100644 index 0000000000..a293adf38c --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_common/ot_console.c @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * OpenThread Command Line Example + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "ot_examples_common.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_console.h" +#include "cmd_system.h" + +void ot_console_start(void) +{ + esp_console_repl_t *repl = NULL; + esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); + /* Prompt to be printed before each line. + * This can be customized, made dynamic, etc. + */ + repl_config.prompt = CONFIG_IDF_TARGET ">"; + repl_config.max_cmdline_length = 256; + repl_config.max_history_len = 10; + +#if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) || defined(CONFIG_ESP_CONSOLE_UART_CUSTOM) + esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl)); +#elif defined(CONFIG_ESP_CONSOLE_USB_CDC) + esp_console_dev_usb_cdc_config_t hw_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&hw_config, &repl_config, &repl)); + +#elif defined(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) + esp_console_dev_usb_serial_jtag_config_t hw_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl)); +#else +#error Unsupported console type +#endif + ESP_ERROR_CHECK(esp_console_start_repl(repl)); + + register_system(); +} diff --git a/examples/openthread/ot_common_components/ot_examples_common/ot_external_coexist.c b/examples/openthread/ot_common_components/ot_examples_common/ot_external_coexist.c new file mode 100644 index 0000000000..463ee56d8f --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_common/ot_external_coexist.c @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * OpenThread Command Line Example + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "sdkconfig.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_coexist.h" +#include "ot_examples_common.h" + +void ot_external_coexist_init(void) +{ + esp_extern_coex_work_mode_t mode = +#if CONFIG_EXTERNAL_COEX_WORK_MODE_LEADER + EXTERNAL_COEX_LEADER_ROLE; +#elif CONFIG_EXTERNAL_COEX_WORK_MODE_FOLLOWER + EXTERNAL_COEX_FOLLOWER_ROLE; +#else + EXTERNAL_COEX_UNKNOWN_ROLE; +#endif + + esp_external_coex_gpio_set_t gpio_pin = ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG(); + ESP_ERROR_CHECK(esp_external_coex_set_work_mode(mode)); + ESP_ERROR_CHECK(esp_enable_extern_coex_gpio_pin(CONFIG_EXTERNAL_COEX_WIRE_TYPE, gpio_pin)); +} diff --git a/examples/openthread/ot_common_components/ot_examples_common/ot_network.c b/examples/openthread/ot_common_components/ot_examples_common/ot_network.c new file mode 100644 index 0000000000..1b4fe9c872 --- /dev/null +++ b/examples/openthread/ot_common_components/ot_examples_common/ot_network.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * OpenThread Command Line Example + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "ot_examples_common.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_openthread.h" +#include "esp_openthread_lock.h" + +void ot_network_auto_start(void) +{ + otOperationalDatasetTlvs dataset; + esp_openthread_lock_acquire(portMAX_DELAY); + otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); + ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); + esp_openthread_lock_release(); +} diff --git a/examples/openthread/ot_rcp/main/Kconfig.projbuild b/examples/openthread/ot_rcp/main/Kconfig.projbuild index 2fa5dc99dd..3bff9f0920 100644 --- a/examples/openthread/ot_rcp/main/Kconfig.projbuild +++ b/examples/openthread/ot_rcp/main/Kconfig.projbuild @@ -18,33 +18,4 @@ menu "OpenThread RCP Example" default 5 range 0 25 - menu "External coexist wire type and pin config" - config EXTERNAL_COEX_WIRE_TYPE - int "The wire_type of external coexist" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE - default 3 - range 0 3 - help - Select wire_type for external coexist, the wire_type define in external_coex_wire_t. - - config EXTERNAL_COEX_REQUEST_PIN - int "The number of external coexist request pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 0) - default 0 - - config EXTERNAL_COEX_GRANT_PIN - int "The number of external coexist grant pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 1) - default 1 - - config EXTERNAL_COEX_PRIORITY_PIN - int "The number of external coexist priority pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 2) - default 2 - - config EXTERNAL_COEX_TX_LINE_PIN - int "The number of external coexist tx_line pin" - depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE = 3) - default 3 - endmenu # External coexist wire type and pin config endmenu diff --git a/examples/openthread/ot_rcp/main/esp_ot_config.h b/examples/openthread/ot_rcp/main/esp_ot_config.h index d7a1150329..69e1805e96 100644 --- a/examples/openthread/ot_rcp/main/esp_ot_config.h +++ b/examples/openthread/ot_rcp/main/esp_ot_config.h @@ -14,10 +14,6 @@ #pragma once -#if CONFIG_EXTERNAL_COEX_ENABLE -#include "esp_coexist.h" -#endif - #include "esp_openthread_types.h" #define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ { \ @@ -89,33 +85,3 @@ .netif_queue_size = 10, \ .task_queue_size = 10, \ } - -#if CONFIG_EXTERNAL_COEX_ENABLE -#if CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_1 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - } -#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_2 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ - } -#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_3 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - .priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \ - .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ - } -#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_4 -#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \ - { \ - .request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \ - .priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \ - .grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \ - .tx_line = CONFIG_EXTERNAL_COEX_TX_LINE_PIN, \ - } -#endif -#endif // CONFIG_EXTERNAL_COEX_ENABLE diff --git a/examples/openthread/ot_rcp/main/esp_ot_rcp.c b/examples/openthread/ot_rcp/main/esp_ot_rcp.c index ccb9988f67..765fef58a2 100644 --- a/examples/openthread/ot_rcp/main/esp_ot_rcp.c +++ b/examples/openthread/ot_rcp/main/esp_ot_rcp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -20,10 +20,9 @@ #include "esp_openthread.h" #include "esp_ot_config.h" #include "esp_vfs_eventfd.h" -#include "driver/uart.h" -#if CONFIG_EXTERNAL_COEX_ENABLE -#include "esp_coexist.h" +#if CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE +#include "ot_examples_common.h" #endif #if !SOC_IEEE802154_SUPPORTED @@ -34,43 +33,6 @@ extern void otAppNcpInit(otInstance *instance); -#if CONFIG_EXTERNAL_COEX_ENABLE -#if SOC_EXTERNAL_COEX_ADVANCE -static void ot_external_coexist_init(void) -{ - esp_external_coex_gpio_set_t gpio_pin = ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG(); - esp_external_coex_set_work_mode(EXTERNAL_COEX_FOLLOWER_ROLE); - ESP_ERROR_CHECK(esp_enable_extern_coex_gpio_pin(CONFIG_EXTERNAL_COEX_WIRE_TYPE, gpio_pin)); -} -#endif // SOC_EXTERNAL_COEX_ADVANCE -#endif // CONFIG_EXTERNAL_COEX_ENABLE - -static void ot_task_worker(void *aContext) -{ - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), - }; - - // Initialize the OpenThread stack - ESP_ERROR_CHECK(esp_openthread_init(&config)); - -#if CONFIG_EXTERNAL_COEX_ENABLE - ot_external_coexist_init(); -#endif // CONFIG_EXTERNAL_COEX_ENABLE - - // Initialize the OpenThread ncp - otAppNcpInit(esp_openthread_get_instance()); - - // Run the main loop - esp_openthread_launch_mainloop(); - - // Clean up - esp_vfs_eventfd_unregister(); - vTaskDelete(NULL); -} - void app_main(void) { // Used eventfds: @@ -83,5 +45,16 @@ void app_main(void) ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); - xTaskCreate(ot_task_worker, "ot_rcp_main", 3072, xTaskGetCurrentTaskHandle(), 5, NULL); + +#if CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE + ot_external_coexist_init(); +#endif + + static esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + + ESP_ERROR_CHECK(esp_openthread_start(&config)); } diff --git a/examples/openthread/ot_rcp/main/idf_component.yml b/examples/openthread/ot_rcp/main/idf_component.yml new file mode 100644 index 0000000000..92e0e5b649 --- /dev/null +++ b/examples/openthread/ot_rcp/main/idf_component.yml @@ -0,0 +1,4 @@ +## IDF Component Manager Manifest File +dependencies: + ot_examples_common: + path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_examples_common diff --git a/examples/openthread/ot_rcp/sdkconfig.ci.ext_coex b/examples/openthread/ot_rcp/sdkconfig.ci.ext_coex index 10e03f180e..fdd48dc0bc 100644 --- a/examples/openthread/ot_rcp/sdkconfig.ci.ext_coex +++ b/examples/openthread/ot_rcp/sdkconfig.ci.ext_coex @@ -1,2 +1,3 @@ -CONFIG_EXTERNAL_COEX_ENABLE=y +CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE=y CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n +CONFIG_EXTERNAL_COEX_WORK_MODE_FOLLOWER=y diff --git a/examples/openthread/ot_rcp/sdkconfig.defaults b/examples/openthread/ot_rcp/sdkconfig.defaults index 009e2dadfd..7a4583d972 100644 --- a/examples/openthread/ot_rcp/sdkconfig.defaults +++ b/examples/openthread/ot_rcp/sdkconfig.defaults @@ -25,6 +25,8 @@ CONFIG_OPENTHREAD_BORDER_ROUTER=n CONFIG_OPENTHREAD_CLI=n CONFIG_OPENTHREAD_SRP_CLIENT=n CONFIG_OPENTHREAD_DNS_CLIENT=n +CONFIG_OPENTHREAD_TASK_SIZE=3072 +CONFIG_OPENTHREAD_CONSOLE_ENABLE=n # end of OpenThread diff --git a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c index cdb7799f04..5be8c610f4 100644 --- a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c +++ b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c @@ -27,9 +27,6 @@ #include "esp_vfs_eventfd.h" #include "nvs_flash.h" #include "driver/rtc_io.h" -#include "driver/uart.h" -#include "openthread/logging.h" -#include "openthread/thread.h" #if !SOC_IEEE802154_SUPPORTED #error "Openthread sleepy device is only supported for the SoCs which have IEEE 802.15.4 module" @@ -60,16 +57,6 @@ static void create_config_network(otInstance *instance) ESP_ERROR_CHECK(esp_openthread_auto_start(NULL)); } -static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) -{ - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - esp_netif_t *netif = esp_netif_new(&cfg); - assert(netif != NULL); - ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config))); - - return netif; -} - static void ot_state_change_callback(otChangedFlags changed_flags, void* ctx) { OT_UNUSED_VARIABLE(ctx); @@ -160,44 +147,6 @@ static void ot_deep_sleep_init(void) ESP_ERROR_CHECK(gpio_pulldown_dis(gpio_wakeup_pin)); } - -static void ot_task_worker(void *aContext) -{ - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), - }; - - // Initialize the OpenThread stack - ESP_ERROR_CHECK(esp_openthread_init(&config)); - - ot_deep_sleep_init(); - -#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC - // The OpenThread log level directly matches ESP log level - (void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL); -#endif - esp_netif_t *openthread_netif; - // Initialize the esp_netif bindings - openthread_netif = init_openthread_netif(&config); - esp_netif_set_default_netif(openthread_netif); - otSetStateChangedCallback(esp_openthread_get_instance(), ot_state_change_callback, NULL); - - create_config_network(esp_openthread_get_instance()); - - // Run the main loop - esp_openthread_launch_mainloop(); - - // Clean up - esp_openthread_netif_glue_deinit(); - esp_netif_destroy(openthread_netif); - - esp_vfs_eventfd_unregister(); - vTaskDelete(NULL); -} - - void app_main(void) { // Used eventfds: @@ -212,6 +161,16 @@ void app_main(void) ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); + ot_deep_sleep_init(); - xTaskCreate(ot_task_worker, "ot_power_save_main", 4096, NULL, 5, NULL); + esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + ESP_ERROR_CHECK(esp_openthread_start(&config)); + esp_netif_set_default_netif(esp_openthread_get_netif()); + + otSetStateChangedCallback(esp_openthread_get_instance(), ot_state_change_callback, NULL); + create_config_network(esp_openthread_get_instance()); } diff --git a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device_config.h b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device_config.h index 145bb245cc..5f82ae0ed6 100644 --- a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device_config.h +++ b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -25,24 +25,9 @@ } #endif -#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ - .host_uart_config = { \ - .port = 0, \ - .uart_config = \ - { \ - .baud_rate = 115200, \ - .data_bits = UART_DATA_8_BITS, \ - .parity = UART_PARITY_DISABLE, \ - .stop_bits = UART_STOP_BITS_1, \ - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ - .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_DEFAULT, \ - }, \ - .rx_pin = UART_PIN_NO_CHANGE, \ - .tx_pin = UART_PIN_NO_CHANGE, \ - }, \ +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ } #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ diff --git a/examples/openthread/ot_sleepy_device/deep_sleep/sdkconfig.defaults b/examples/openthread/ot_sleepy_device/deep_sleep/sdkconfig.defaults index 72d3f81921..18d548c09c 100644 --- a/examples/openthread/ot_sleepy_device/deep_sleep/sdkconfig.defaults +++ b/examples/openthread/ot_sleepy_device/deep_sleep/sdkconfig.defaults @@ -21,6 +21,7 @@ CONFIG_MBEDTLS_ECJPAKE_C=y CONFIG_OPENTHREAD_ENABLED=y CONFIG_OPENTHREAD_BORDER_ROUTER=n CONFIG_OPENTHREAD_DNS64_CLIENT=y +CONFIG_OPENTHREAD_CONSOLE_ENABLE=n # end of OpenThread # diff --git a/examples/openthread/ot_sleepy_device/light_sleep/README.md b/examples/openthread/ot_sleepy_device/light_sleep/README.md index 01e8259d2b..24ed4aa192 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/README.md +++ b/examples/openthread/ot_sleepy_device/light_sleep/README.md @@ -15,8 +15,8 @@ Set the chip target: `idf.py set-target `, then configure the project There are two options to configure Openthread Dataset: -* Auto start mode: Enable `OPENTHREAD_AUTO_START` under `OpenThread Sleepy Example---> Enable the automatic start mode`, and configure the dataset under `Component config ---> Openthread ---> Thread Operation Dataset`. -* Manual mode: Disable `OPENTHREAD_AUTO_START`, use the CLI command to configure the dataset and start network. +* Auto start mode: Enable `OPENTHREAD_NETWORK_AUTO_START` under `OpenThread Sleepy Example---> Enable the automatic start mode`, and configure the dataset under `Component config ---> Openthread ---> Thread Operation Dataset`. +* Manual mode: Disable `OPENTHREAD_NETWORK_AUTO_START`, use the CLI command to configure the dataset and start network. ### Build and Flash @@ -24,11 +24,11 @@ Build the project and flash it to the board. Use the following command: `idf.py ### Configure the Openthread sleepy device ``` -> mode - -> pollperiod 3000 -> dataset set active -> ifconfig up -> thread start +esp32h2> ot mode - +esp32h2> ot pollperiod 3000 +esp32h2> ot dataset set active +esp32h2> ot ifconfig up +esp32h2> ot thread start ``` ### Example Output @@ -62,23 +62,23 @@ I (652) gdma: GDMA pair (0, 0) retention initialization I(660) OPENTHREAD:[I] ChildSupervsn-: Timeout: 0 -> 190 > I (664) OPENTHREAD: OpenThread attached to netif I (635) main_task: Returned from app_main() -> mode - +esp32h2> ot mode - I(2250683) OPENTHREAD:[N] Mle-----------: Mode 0x0f -> 0x04 [rx-on:no ftd:no full-net:no] Done -> pollperiod 3000 +esp32h2> ot pollperiod 3000 Done -> dataset set active 0e080000000000010000000300001a35060004001fffe00208dead00beef00cafe0708fd000db800a00000051000112233445566778899aabbccdd0000030e4f70656e5468726561642d455350010212340410104810e2315100afd6bc9215a6bfac530c0402a0f7f8 +esp32h2> ot dataset set active 0e080000000000010000000300001a35060004001fffe00208dead00beef00cafe0708fd000db800a00000051000112233445566778899aabbccdd0000030e4f70656e5468726561642d455350010212340410104810e2315100afd6bc9215a6bfac530c0402a0f7f8 Done -> ifconfig up +esp32h2> ot ifconfig up Done I (2274801) OT_STATE: netif up -> thread start +esp32h2> ot thread start I(2279917) OPENTHREAD:[N] Mle-----------: Role disabled -> detached Done diff --git a/examples/openthread/ot_sleepy_device/light_sleep/main/Kconfig.projbuild b/examples/openthread/ot_sleepy_device/light_sleep/main/Kconfig.projbuild deleted file mode 100644 index 27aa83ff0c..0000000000 --- a/examples/openthread/ot_sleepy_device/light_sleep/main/Kconfig.projbuild +++ /dev/null @@ -1,9 +0,0 @@ -menu "OpenThread Sleepy Example" - - config OPENTHREAD_AUTO_START - bool 'Enable the automatic start mode.' - default n - help - If enabled, the Openthread Device will create or connect to thread network with pre-configured - network parameters automatically. Otherwise, user need to configure Thread via CLI command manually. -endmenu diff --git a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c index d4e1892273..633f40b094 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c +++ b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c @@ -19,17 +19,15 @@ #include "esp_err.h" #include "esp_event.h" #include "esp_log.h" +#include "esp_netif.h" #include "esp_openthread.h" -#include "esp_openthread_cli.h" #include "esp_openthread_lock.h" #include "esp_openthread_netif_glue.h" #include "esp_ot_sleepy_device_config.h" #include "esp_vfs_eventfd.h" #include "esp_private/esp_clk.h" -#include "driver/uart.h" #include "nvs_flash.h" -#include "openthread/logging.h" -#include "openthread/thread.h" +#include "ot_examples_common.h" #if CONFIG_ESP_SLEEP_DEBUG #include "esp_private/esp_pmu.h" #include "esp_private/esp_sleep_internal.h" @@ -50,7 +48,7 @@ static esp_pm_lock_handle_t s_cli_pm_lock = NULL; TimerHandle_t xTimer; -#if CONFIG_OPENTHREAD_AUTO_START +#if CONFIG_OPENTHREAD_NETWORK_AUTO_START static void create_config_network(otInstance *instance) { otLinkModeConfig linkMode = { 0 }; @@ -73,7 +71,7 @@ static void create_config_network(otInstance *instance) otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); } -#endif // CONFIG_OPENTHREAD_AUTO_START +#endif // CONFIG_OPENTHREAD_NETWORK_AUTO_START static esp_err_t esp_openthread_sleep_device_init(void) { @@ -105,16 +103,6 @@ static void process_state_change(otChangedFlags flags, void* context) } } -static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) -{ - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - esp_netif_t *netif = esp_netif_new(&cfg); - assert(netif != NULL); - ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config))); - - return netif; -} - #if CONFIG_ESP_SLEEP_DEBUG static esp_sleep_context_t s_sleep_ctx; @@ -128,63 +116,6 @@ void vTimerCallback( TimerHandle_t xTimer ) } #endif -static void ot_task_worker(void *aContext) -{ - otError ret; - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), - }; - - // Initialize the OpenThread stack - ESP_ERROR_CHECK(esp_openthread_init(&config)); - - esp_openthread_lock_acquire(portMAX_DELAY); - ret = otSetStateChangedCallback(esp_openthread_get_instance(), process_state_change, esp_openthread_get_instance()); - esp_openthread_lock_release(); - if(ret != OT_ERROR_NONE) { - ESP_LOGE(TAG, "Failed to set state changed callback"); - } -#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC - // The OpenThread log level directly matches ESP log level - (void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL); -#endif - // Initialize the OpenThread cli -#if CONFIG_OPENTHREAD_CLI - esp_openthread_cli_init(); -#endif - esp_netif_t *openthread_netif; - // Initialize the esp_netif bindings - openthread_netif = init_openthread_netif(&config); - esp_netif_set_default_netif(openthread_netif); -#if CONFIG_OPENTHREAD_AUTO_START - create_config_network(esp_openthread_get_instance()); -#endif // CONFIG_OPENTHREAD_AUTO_START - -#if CONFIG_OPENTHREAD_CLI - esp_openthread_cli_create_task(); -#endif -#if CONFIG_ESP_SLEEP_DEBUG - esp_sleep_set_sleep_context(&s_sleep_ctx); - esp_log_level_set(TAG, ESP_LOG_DEBUG); - - // Use freeRTOS timer so that it is lower priority than OpenThread - xTimer = xTimerCreate("print_sleep_flag", pdMS_TO_TICKS(2000), pdTRUE, NULL, vTimerCallback); - xTimerStart( xTimer, 0 ); -#endif - - // Run the main loop - esp_openthread_launch_mainloop(); - - // Clean up - esp_openthread_netif_glue_deinit(); - esp_netif_destroy(openthread_netif); - - esp_vfs_eventfd_unregister(); - vTaskDelete(NULL); -} - static esp_err_t ot_power_save_init(void) { esp_err_t rc = ESP_OK; @@ -227,5 +158,31 @@ void app_main(void) ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); ESP_ERROR_CHECK(ot_power_save_init()); ESP_ERROR_CHECK(esp_openthread_sleep_device_init()); - xTaskCreate(ot_task_worker, "ot_power_save_main", 4096, NULL, 5, NULL); + +#if CONFIG_OPENTHREAD_CLI + ot_console_start(); +#endif + + static esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + ESP_ERROR_CHECK(esp_openthread_start(&config)); + esp_netif_set_default_netif(esp_openthread_get_netif()); + + otSetStateChangedCallback(esp_openthread_get_instance(), process_state_change, esp_openthread_get_instance()); + +#if CONFIG_OPENTHREAD_NETWORK_AUTO_START + create_config_network(esp_openthread_get_instance()); +#endif + +#if CONFIG_ESP_SLEEP_DEBUG + esp_sleep_set_sleep_context(&s_sleep_ctx); + esp_log_level_set(TAG, ESP_LOG_DEBUG); + + // Use freeRTOS timer so that it is lower priority than OpenThread + xTimer = xTimerCreate("print_sleep_flag", pdMS_TO_TICKS(2000), pdTRUE, NULL, vTimerCallback); + xTimerStart( xTimer, 0 ); +#endif } diff --git a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device_config.h b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device_config.h index 73bd029b27..716433c605 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device_config.h +++ b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -25,25 +25,9 @@ } #endif -// When JIRA PM-3 is fixed, the UART clock will automatically switch. -#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ - .host_uart_config = { \ - .port = 0, \ - .uart_config = \ - { \ - .baud_rate = 115200, \ - .data_bits = UART_DATA_8_BITS, \ - .parity = UART_PARITY_DISABLE, \ - .stop_bits = UART_STOP_BITS_1, \ - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ - .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_XTAL, \ - }, \ - .rx_pin = UART_PIN_NO_CHANGE, \ - .tx_pin = UART_PIN_NO_CHANGE, \ - }, \ +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ } #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ diff --git a/examples/openthread/ot_sleepy_device/light_sleep/main/idf_component.yml b/examples/openthread/ot_sleepy_device/light_sleep/main/idf_component.yml new file mode 100644 index 0000000000..72f76924fe --- /dev/null +++ b/examples/openthread/ot_sleepy_device/light_sleep/main/idf_component.yml @@ -0,0 +1,6 @@ +## IDF Component Manager Manifest File +dependencies: + idf: + version: ">=4.1.0" + ot_examples_common: + path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_examples_common diff --git a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults index 1b7c25c723..355e9dd3aa 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults +++ b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults @@ -23,6 +23,8 @@ CONFIG_OPENTHREAD_BORDER_ROUTER=n CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_DNS64_CLIENT=y CONFIG_OPENTHREAD_CLI=y +CONFIG_OPENTHREAD_TASK_SIZE=4096 +CONFIG_OPENTHREAD_CONSOLE_ENABLE=n # end of OpenThread # @@ -51,3 +53,9 @@ CONFIG_IEEE802154_SLEEP_ENABLE=y CONFIG_FREERTOS_HZ=1000 CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y # end of light sleep + +# +# ESP System Settings +# +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6144 +# end of ESP System Settings diff --git a/examples/openthread/ot_trel/README.md b/examples/openthread/ot_trel/README.md index 5cc60dfa2f..6fcb37e96e 100644 --- a/examples/openthread/ot_trel/README.md +++ b/examples/openthread/ot_trel/README.md @@ -44,7 +44,7 @@ Now you'll get an OpenThread command line shell. The `help` command will print all of the supported commands. ```bash -> help +esp32s3> ot help I(7058) OPENTHREAD:[INFO]-CLI-----: execute command: help bbr bufferinfo @@ -78,51 +78,51 @@ To run this example, at least two ESP32-S3 boards flashed with this ot_trel exam On the first device, run the following commands: ```bash -> factoryreset +esp32s3> ot factoryreset ... # the device will reboot -> dataset init new +esp32s3> ot dataset init new Done -> dataset commit active +esp32s3> ot dataset commit active Done -> ifconfig up +esp32s3> ot ifconfig up Done -> thread start +esp32s3> ot thread start Done # After some seconds -> state +esp32s3> ot state leader Done ``` Now the first device has formed a Thread network as a leader. Get some information which will be used in next steps: ```bash -> ipaddr +esp32s3> ot ipaddr fdde:ad00:beef:0:0:ff:fe00:fc00 fdde:ad00:beef:0:0:ff:fe00:8000 fdde:ad00:beef:0:a7c6:6311:9c8c:271b fe80:0:0:0:5c27:a723:7115:c8f8 # Get the Active Dataset -> dataset active -x +esp32s3> ot dataset active -x 0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 ``` On the second device, set the active dataset from leader, and start Thread interface: ```bash -> factoryreset +esp32s3> ot factoryreset ... # the device will reboot -> dataset set active 0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 -> ifconfig up +esp32s3> ot dataset set active 0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 +esp32s3> ot ifconfig up Done -> thread start +esp32s3> ot thread start Done # After some seconds -> state +esp32s3> ot state router # child is also a valid state Done ``` diff --git a/examples/openthread/ot_trel/main/Kconfig.projbuild b/examples/openthread/ot_trel/main/Kconfig.projbuild deleted file mode 100644 index a00fd87591..0000000000 --- a/examples/openthread/ot_trel/main/Kconfig.projbuild +++ /dev/null @@ -1,9 +0,0 @@ -menu "OpenThread TREL Example" - - config OPENTHREAD_AUTO_START - bool 'Enable the automatic start mode.' - default n - help - If enabled, the Openthread Device will create or connect to thread network with pre-configured - network parameters automatically. Otherwise, user need to configure Thread via CLI command manually. -endmenu diff --git a/examples/openthread/ot_trel/main/esp_ot_config.h b/examples/openthread/ot_trel/main/esp_ot_config.h index be8eff0e21..f72a321ee6 100644 --- a/examples/openthread/ot_trel/main/esp_ot_config.h +++ b/examples/openthread/ot_trel/main/esp_ot_config.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: CC0-1.0 * @@ -22,33 +22,10 @@ .radio_mode = RADIO_MODE_TREL, \ } -#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART -#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ - .host_uart_config = { \ - .port = 0, \ - .uart_config = \ - { \ - .baud_rate = 115200, \ - .data_bits = UART_DATA_8_BITS, \ - .parity = UART_PARITY_DISABLE, \ - .stop_bits = UART_STOP_BITS_1, \ - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ - .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_DEFAULT, \ - }, \ - .rx_pin = UART_PIN_NO_CHANGE, \ - .tx_pin = UART_PIN_NO_CHANGE, \ - }, \ - } -#elif CONFIG_OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG #define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ - .host_connection_mode = HOST_CONNECTION_MODE_CLI_USB, \ - .host_usb_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(), \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ } -#endif #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \ diff --git a/examples/openthread/ot_trel/main/esp_ot_trel.c b/examples/openthread/ot_trel/main/esp_ot_trel.c index a333eface5..fc59497c2a 100644 --- a/examples/openthread/ot_trel/main/esp_ot_trel.c +++ b/examples/openthread/ot_trel/main/esp_ot_trel.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -23,23 +23,14 @@ #include "esp_netif.h" #include "esp_netif_types.h" #include "esp_openthread.h" -#include "esp_openthread_cli.h" #include "esp_openthread_lock.h" #include "esp_openthread_netif_glue.h" -#include "esp_openthread_types.h" #include "esp_ot_config.h" #include "esp_vfs_eventfd.h" -#include "driver/uart.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "hal/uart_types.h" #include "nvs_flash.h" -#include "openthread/cli.h" -#include "openthread/instance.h" -#include "openthread/logging.h" -#include "openthread/tasklet.h" #include "protocol_examples_common.h" #include "mdns.h" +#include "ot_examples_common.h" #if !CONFIG_EXAMPLE_CONNECT_WIFI && !CONFIG_EXAMPLE_CONNECT_ETHERNET #error No netif for TREL! @@ -56,70 +47,6 @@ #define TAG "ot_esp_trel" -static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) -{ - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - esp_netif_t *netif = esp_netif_new(&cfg); - assert(netif != NULL); - ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config))); - - return netif; -} - -static void ot_task_worker(void *aContext) -{ - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), - }; - - ESP_ERROR_CHECK(example_connect()); - - // Initialize the OpenThread stack - ESP_ERROR_CHECK(esp_openthread_init(&config)); - -#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE - ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); -#endif - -#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC - // The OpenThread log level directly matches ESP log level - (void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL); -#endif - // Initialize the OpenThread cli -#if CONFIG_OPENTHREAD_CLI - esp_openthread_cli_init(); -#endif - - esp_netif_t *openthread_netif; - // Initialize the esp_netif bindings - openthread_netif = init_openthread_netif(&config); - esp_netif_set_default_netif(openthread_netif); - -#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - esp_cli_custom_command_init(); -#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - - // Run the main loop -#if CONFIG_OPENTHREAD_CLI - esp_openthread_cli_create_task(); -#endif -#if CONFIG_OPENTHREAD_AUTO_START - otOperationalDatasetTlvs dataset; - otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); - ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); -#endif - esp_openthread_launch_mainloop(); - - // Clean up - esp_openthread_netif_glue_deinit(); - esp_netif_destroy(openthread_netif); - - esp_vfs_eventfd_unregister(); - vTaskDelete(NULL); -} - void app_main(void) { // Used eventfds: @@ -136,5 +63,24 @@ void app_main(void) ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); ESP_ERROR_CHECK(mdns_init()); ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-trel")); - xTaskCreate(ot_task_worker, "ot_trel_main", 8192, xTaskGetCurrentTaskHandle(), 5, NULL); + + ESP_ERROR_CHECK(example_connect()); + +#if CONFIG_OPENTHREAD_CLI + ot_console_start(); +#endif + + static esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + ESP_ERROR_CHECK(esp_openthread_start(&config)); + esp_netif_set_default_netif(esp_openthread_get_netif()); +#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION + esp_cli_custom_command_init(); +#endif +#if CONFIG_OPENTHREAD_NETWORK_AUTO_START + ot_network_auto_start(); +#endif } diff --git a/examples/openthread/ot_trel/main/idf_component.yml b/examples/openthread/ot_trel/main/idf_component.yml index a52a17085f..4318a41630 100644 --- a/examples/openthread/ot_trel/main/idf_component.yml +++ b/examples/openthread/ot_trel/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.2.0" + version: "~1.4.0" espressif/mdns: "^1.0.3" idf: version: ">=4.1.0" @@ -9,3 +9,5 @@ dependencies: path: ${IDF_PATH}/examples/common_components/protocol_examples_common ot_led: path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led + ot_examples_common: + path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_examples_common diff --git a/examples/openthread/ot_trel/sdkconfig.defaults b/examples/openthread/ot_trel/sdkconfig.defaults index 0e5eb34891..92fc2c7df0 100644 --- a/examples/openthread/ot_trel/sdkconfig.defaults +++ b/examples/openthread/ot_trel/sdkconfig.defaults @@ -25,6 +25,8 @@ CONFIG_OPENTHREAD_BORDER_ROUTER=n CONFIG_OPENTHREAD_DNS64_CLIENT=y CONFIG_OPENTHREAD_RADIO_154_NONE=y CONFIG_OPENTHREAD_RADIO_TREL=y +CONFIG_OPENTHREAD_TASK_SIZE=10240 +CONFIG_OPENTHREAD_CONSOLE_ENABLE=n # end of OpenThread # @@ -49,4 +51,10 @@ CONFIG_EXAMPLE_CONNECT_THREAD=n # Wireless Coexistence # CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n -CONFIG_EXTERNAL_COEX_ENABLE=n +CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE=n + +# +# ESP System Settings +# +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6144 +# end of ESP System Settings