/* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * * OpenThread Border Router 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 #include #include "sdkconfig.h" #include "esp_check.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_types.h" #include "esp_ot_cli_extension.h" #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/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" #if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE #include "ot_led_strip.h" #endif #define TAG "esp_ot_br" #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); (void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL); esp_openthread_cli_init(); esp_cli_custom_command_init(); esp_openthread_cli_create_task(); 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_EXAMPLE_CONNECT_WIFI #if CONFIG_OPENTHREAD_BR_AUTO_START ESP_ERROR_CHECK(example_connect()); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_MAX_MODEM)); #if CONFIG_ESP_COEX_SW_COEXIST_ENABLE && CONFIG_OPENTHREAD_RADIO_NATIVE ESP_ERROR_CHECK(esp_coex_wifi_i154_enable()); #else #if CONFIG_EXTERNAL_COEX_ENABLE ot_br_external_coexist_init(); #endif // CONFIG_EXTERNAL_COEX_ENABLE #endif esp_openthread_set_backbone_netif(get_example_netif()); #else esp_ot_wifi_netif_init(); esp_openthread_set_backbone_netif(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")); #endif // CONFIG_OPENTHREAD_BR_AUTO_START #elif CONFIG_EXAMPLE_CONNECT_ETHERNET ESP_ERROR_CHECK(example_connect()); esp_openthread_set_backbone_netif(get_example_netif()); #else ESP_LOGE(TAG, "ESP-Openthread has not set backbone netif"); #endif // CONFIG_EXAMPLE_CONNECT_WIFI ESP_ERROR_CHECK(mdns_init()); ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br")); // Initialize border routing features 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 ESP_ERROR_CHECK(esp_openthread_border_router_init()); otOperationalDatasetTlvs dataset; otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); #endif // CONFIG_OPENTHREAD_BR_AUTO_START esp_openthread_lock_release(); vTaskDelete(NULL); } void app_main(void) { // Used eventfds: // * netif // * task queue // * border router esp_vfs_eventfd_config_t eventfd_config = { #if CONFIG_OPENTHREAD_RADIO_NATIVE || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI // * radio driver (A native radio device needs a eventfd for radio driver.) // * SpiSpinelInterface (The Spi Spinel Interface needs a eventfd.) // The above will not exist at the same time. .max_fds = 4, #else .max_fds = 3, #endif }; ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); xTaskCreate(ot_task_worker, "ot_br_main", 8192, xTaskGetCurrentTaskHandle(), 5, NULL); xTaskCreate(ot_br_init, "ot_br_init", 6144, NULL, 4, NULL); }