From 3bb89e116a1d9301c741cc5db0a4e6750117925e Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Tue, 26 Sep 2023 12:18:08 +0800 Subject: [PATCH] feat(openthread): Host connection logic refactor --- components/openthread/Kconfig | 15 +++++ .../openthread/include/esp_openthread_types.h | 17 ++++-- .../esp_openthread_spi_slave.h | 2 +- .../private_include/esp_openthread_uart.h | 32 ++++++++-- .../src/esp_openthread_platform.cpp | 61 +++++++++++++------ .../src/port/esp_openthread_spi_slave.c | 2 +- .../openthread/src/port/esp_openthread_uart.c | 58 +++++++++++++----- examples/openthread/ot_br/README.md | 6 ++ .../openthread/ot_br/main/esp_ot_config.h | 8 +++ examples/openthread/ot_cli/README.md | 6 +- .../openthread/ot_cli/main/esp_ot_config.h | 10 ++- 11 files changed, 170 insertions(+), 47 deletions(-) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index d253f61942..3f0300f07c 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -13,6 +13,21 @@ menu "OpenThread" help Select this option to enable dynamic log level control for OpenThread + choice OPENTHREAD_CONSOLE_TYPE + prompt "OpenThread console type" + depends on OPENTHREAD_ENABLED + default OPENTHREAD_CONSOLE_TYPE_UART + help + Select OpenThread console type + + config OPENTHREAD_CONSOLE_TYPE_UART + depends on ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM + bool "OpenThread console type UART" + config OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG + depends on ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG + bool "OpenThread console type USB Serial/JTAG Controller" + endchoice #OPENTHREAD_CONSOLE_TYPE + choice OPENTHREAD_LOG_LEVEL prompt "OpenThread log verbosity" depends on OPENTHREAD_ENABLED && !OPENTHREAD_LOG_LEVEL_DYNAMIC diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index 936dd6d542..28595d3fa0 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,7 @@ #include "driver/spi_master.h" #include "driver/spi_slave.h" #include "driver/uart.h" +#include "driver/usb_serial_jtag.h" #include "hal/gpio_types.h" #include "hal/uart_types.h" #include "openthread/thread.h" @@ -112,8 +113,9 @@ typedef struct { */ typedef enum { RADIO_MODE_NATIVE = 0x0, /*!< Use the native 15.4 radio */ - RADIO_MODE_UART_RCP = 0x1, /*!< UART connection to a 15.4 capable radio co-processor (RCP) */ - RADIO_MODE_SPI_RCP = 0x2, /*!< SPI connection to a 15.4 capable radio co-processor (RCP) */ + RADIO_MODE_UART_RCP, /*!< UART connection to a 15.4 capable radio co-processor (RCP) */ + RADIO_MODE_SPI_RCP, /*!< SPI connection to a 15.4 capable radio co-processor (RCP) */ + RADIO_MODE_MAX, /*!< Using for parameter check */ } esp_openthread_radio_mode_t; /** @@ -122,9 +124,11 @@ typedef enum { */ typedef enum { HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection */ - HOST_CONNECTION_MODE_CLI_UART = 0x1, /*!< CLI UART connection to the host */ - HOST_CONNECTION_MODE_RCP_UART = 0x2, /*!< RCP UART connection to the host */ - HOST_CONNECTION_MODE_RCP_SPI = 0x3, /*!< RCP SPI connection to the host */ + HOST_CONNECTION_MODE_CLI_UART, /*!< CLI UART connection to the host */ + HOST_CONNECTION_MODE_CLI_USB, /*!< CLI USB connection to the host */ + HOST_CONNECTION_MODE_RCP_UART, /*!< RCP UART connection to the host */ + HOST_CONNECTION_MODE_RCP_SPI, /*!< RCP SPI connection to the host */ + HOST_CONNECTION_MODE_MAX, /*!< Using for parameter check */ } esp_openthread_host_connection_mode_t; /** @@ -147,6 +151,7 @@ typedef struct { esp_openthread_host_connection_mode_t host_connection_mode; /*!< The host connection mode */ union { esp_openthread_uart_config_t host_uart_config; /*!< The uart configuration to host */ + usb_serial_jtag_driver_config_t host_usb_config; /*!< The usb configuration to host */ esp_openthread_spi_slave_config_t spi_slave_config; /*!< The spi configuration to host */ }; } esp_openthread_host_connection_config_t; diff --git a/components/openthread/private_include/esp_openthread_spi_slave.h b/components/openthread/private_include/esp_openthread_spi_slave.h index c776ef083e..d55bf662ce 100644 --- a/components/openthread/private_include/esp_openthread_spi_slave.h +++ b/components/openthread/private_include/esp_openthread_spi_slave.h @@ -18,7 +18,7 @@ extern "C" { * @brief This function initializes the OpenThread spinel SPI slave. * */ -esp_err_t esp_openthread_spi_slave_init(const esp_openthread_platform_config_t *config); +esp_err_t esp_openthread_host_rcp_spi_init(const esp_openthread_platform_config_t *config); /** * @brief This function deinitializes the OpenThread spinel SPI slave. diff --git a/components/openthread/private_include/esp_openthread_uart.h b/components/openthread/private_include/esp_openthread_uart.h index 3d2352d82d..50b5f44706 100644 --- a/components/openthread/private_include/esp_openthread_uart.h +++ b/components/openthread/private_include/esp_openthread_uart.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,16 +29,40 @@ extern "C" { esp_err_t esp_openthread_uart_init_port(const esp_openthread_uart_config_t *config); /** - * @brief Initializes the uart for OpenThread host connection. + * @brief Initializes the console UART for OpenThread host connection. * - * @param[in] config The uart configuration. + * @param[in] config The platform configuration. * * @return * - ESP_OK on success * - ESP_ERROR on failure * */ -esp_err_t esp_openthread_uart_init(const esp_openthread_platform_config_t *config); +esp_err_t esp_openthread_host_cli_uart_init(const esp_openthread_platform_config_t *config); + +/** + * @brief Initializes the console USB JTAG for OpenThread host connection. + * + * @param[in] config The platform configuration. + * + * @return + * - ESP_OK on success + * - ESP_ERROR on failure + * + */ +esp_err_t esp_openthread_host_cli_usb_init(const esp_openthread_platform_config_t *config); + +/** + * @brief Initializes the RCP UART for OpenThread host connection. + * + * @param[in] config The platform configuration. + * + * @return + * - ESP_OK on success + * - ESP_ERROR on failure + * + */ +esp_err_t esp_openthread_host_rcp_uart_init(const esp_openthread_platform_config_t *config); /** * @brief Deintializes the uart for OpenThread host connection. diff --git a/components/openthread/src/esp_openthread_platform.cpp b/components/openthread/src/esp_openthread_platform.cpp index fbeba5b2b8..92d50a078b 100644 --- a/components/openthread/src/esp_openthread_platform.cpp +++ b/components/openthread/src/esp_openthread_platform.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -84,16 +84,46 @@ void esp_openthread_platform_workflow_unregister(const char *name) } } +static inline esp_openthread_host_connection_mode_t get_host_connection_mode(void) +{ + return s_platform_config.host_config.host_connection_mode; +} + +static esp_err_t esp_openthread_host_interface_init(const esp_openthread_platform_config_t *config) +{ + esp_openthread_host_connection_mode_t host_mode = get_host_connection_mode(); + switch (host_mode) { + case HOST_CONNECTION_MODE_RCP_SPI: + ESP_RETURN_ON_ERROR(esp_openthread_host_rcp_spi_init(config), OT_PLAT_LOG_TAG, + "esp_openthread_host_rcp_spi_init failed"); + break; + case HOST_CONNECTION_MODE_RCP_UART: + ESP_RETURN_ON_ERROR(esp_openthread_host_rcp_uart_init(config), OT_PLAT_LOG_TAG, + "esp_openthread_host_rcp_uart_init failed"); + break; +#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART + case HOST_CONNECTION_MODE_CLI_UART: + ESP_RETURN_ON_ERROR(esp_openthread_host_cli_uart_init(config), OT_PLAT_LOG_TAG, + "esp_openthread_host_cli_uart_init failed"); + break; +#endif +#if CONFIG_OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG + case HOST_CONNECTION_MODE_CLI_USB: + ESP_RETURN_ON_ERROR(esp_openthread_host_cli_usb_init(config), OT_PLAT_LOG_TAG, + "esp_openthread_host_cli_usb_init failed"); + break; +#endif + default: + return ESP_FAIL; + } + return ESP_OK; +} + esp_err_t esp_openthread_platform_init(const esp_openthread_platform_config_t *config) { - ESP_RETURN_ON_FALSE(config->radio_config.radio_mode == RADIO_MODE_NATIVE || - config->radio_config.radio_mode == RADIO_MODE_UART_RCP || - config->radio_config.radio_mode == RADIO_MODE_SPI_RCP, + ESP_RETURN_ON_FALSE(config->radio_config.radio_mode < RADIO_MODE_MAX, ESP_ERR_INVALID_ARG, OT_PLAT_LOG_TAG, "Radio mode not supported"); - ESP_RETURN_ON_FALSE(config->host_config.host_connection_mode == HOST_CONNECTION_MODE_NONE || - config->host_config.host_connection_mode == HOST_CONNECTION_MODE_CLI_UART || - config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART || - config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI, + ESP_RETURN_ON_FALSE(config->host_config.host_connection_mode < HOST_CONNECTION_MODE_MAX, ESP_ERR_INVALID_ARG, OT_PLAT_LOG_TAG, "Host connection mode not supported"); ESP_RETURN_ON_FALSE(!s_openthread_platform_initialized, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OpenThread platform already initialized"); @@ -107,13 +137,8 @@ esp_err_t esp_openthread_platform_init(const esp_openthread_platform_config_t *c esp_openthread_set_storage_name(config->port_config.storage_partition_name); - if (config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI) { - ESP_GOTO_ON_ERROR(esp_openthread_spi_slave_init(config), exit, OT_PLAT_LOG_TAG, - "esp_openthread_spi_slave_init failed"); - }else if (config->host_config.host_connection_mode == HOST_CONNECTION_MODE_CLI_UART || - config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART) { - ESP_GOTO_ON_ERROR(esp_openthread_uart_init(config), exit, OT_PLAT_LOG_TAG, "esp_openthread_uart_init failed"); - } + ESP_GOTO_ON_ERROR(esp_openthread_host_interface_init(config), exit, OT_PLAT_LOG_TAG, + "esp_openthread_host_interface_init failed"); ESP_GOTO_ON_ERROR(esp_openthread_task_queue_init(config), exit, OT_PLAT_LOG_TAG, "esp_openthread_task_queue_init failed"); @@ -140,10 +165,10 @@ esp_err_t esp_openthread_platform_deinit(void) esp_openthread_task_queue_deinit(); esp_openthread_radio_deinit(); - if (s_platform_config.host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI){ + if (get_host_connection_mode() == HOST_CONNECTION_MODE_RCP_SPI){ esp_openthread_spi_slave_deinit(); - }else if (s_platform_config.host_config.host_connection_mode == HOST_CONNECTION_MODE_CLI_UART || - s_platform_config.host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART) { + } else if (get_host_connection_mode() == HOST_CONNECTION_MODE_CLI_UART || + get_host_connection_mode() == HOST_CONNECTION_MODE_RCP_UART) { esp_openthread_uart_deinit(); } diff --git a/components/openthread/src/port/esp_openthread_spi_slave.c b/components/openthread/src/port/esp_openthread_spi_slave.c index eb864d7f9a..33268bb8c5 100644 --- a/components/openthread/src/port/esp_openthread_spi_slave.c +++ b/components/openthread/src/port/esp_openthread_spi_slave.c @@ -70,7 +70,7 @@ static void IRAM_ATTR handle_spi_transaction_done(spi_slave_transaction_t *trans trans = NULL; } -esp_err_t esp_openthread_spi_slave_init(const esp_openthread_platform_config_t *config) +esp_err_t esp_openthread_host_rcp_spi_init(const esp_openthread_platform_config_t *config) { s_spi_config = config->host_config.spi_slave_config; gpio_config_t io_conf = { diff --git a/components/openthread/src/port/esp_openthread_uart.c b/components/openthread/src/port/esp_openthread_uart.c index e3bbe75dd2..9c8ef64cde 100644 --- a/components/openthread/src/port/esp_openthread_uart.c +++ b/components/openthread/src/port/esp_openthread_uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,8 @@ #include "common/logging.hpp" #include "driver/uart.h" #include "utils/uart.h" +#include "esp_vfs_usb_serial_jtag.h" +#include "driver/usb_serial_jtag.h" static int s_uart_port; static int s_uart_fd; @@ -70,28 +72,54 @@ esp_err_t esp_openthread_uart_init_port(const esp_openthread_uart_config_t *conf return ESP_OK; } -esp_err_t esp_openthread_uart_init(const esp_openthread_platform_config_t *config) +#if CONFIG_OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG +esp_err_t esp_openthread_host_cli_usb_init(const esp_openthread_platform_config_t *config) { - char uart_path[16]; esp_err_t ret = ESP_OK; + /* Disable buffering on stdin */ + setvbuf(stdin, NULL, _IONBF, 0); + /* Minicom, screen, idf_monitor send CR when ENTER key is pressed */ + esp_vfs_dev_usb_serial_jtag_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_usb_serial_jtag_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + /* Enable non-blocking mode on stdin and stdout */ + fcntl(fileno(stdout), F_SETFL, O_NONBLOCK); + fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); + + ret = usb_serial_jtag_driver_install((usb_serial_jtag_driver_config_t *)&config->host_config.host_usb_config); + esp_vfs_usb_serial_jtag_use_driver(); + esp_vfs_dev_uart_register(); + return ret; +} +#endif + +#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART +esp_err_t esp_openthread_host_cli_uart_init(const esp_openthread_platform_config_t *config) +{ + ESP_RETURN_ON_ERROR(esp_openthread_uart_init_port(&config->host_config.host_uart_config), OT_PLAT_LOG_TAG, + "esp_openthread_uart_init_port failed"); + return ESP_OK; +} +#endif + +esp_err_t esp_openthread_host_rcp_uart_init(const esp_openthread_platform_config_t *config) +{ + esp_err_t ret = ESP_OK; // Install UART driver for interrupt-driven reads and writes. - ESP_RETURN_ON_FALSE(config->host_config.host_connection_mode == HOST_CONNECTION_MODE_CLI_UART || - config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART, - ESP_FAIL, OT_PLAT_LOG_TAG, "unsupport host connect mode"); + char uart_path[16]; s_uart_port = config->host_config.host_uart_config.port; ESP_RETURN_ON_ERROR(esp_openthread_uart_init_port(&config->host_config.host_uart_config), OT_PLAT_LOG_TAG, "esp_openthread_uart_init_port failed"); - if (config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART) { - esp_vfs_dev_uart_port_set_rx_line_endings(s_uart_port, ESP_LINE_ENDINGS_LF); - esp_vfs_dev_uart_port_set_tx_line_endings(s_uart_port, ESP_LINE_ENDINGS_LF); - snprintf(uart_path, sizeof(uart_path), "/dev/uart/%d", s_uart_port); - s_uart_fd = open(uart_path, O_RDWR | O_NONBLOCK); - ESP_RETURN_ON_FALSE(s_uart_fd >= 0, ESP_FAIL, OT_PLAT_LOG_TAG, "open uart_path failed"); - ret = esp_openthread_platform_workflow_register(&esp_openthread_uart_update, &esp_openthread_uart_process, - uart_workflow); - } + esp_vfs_dev_uart_port_set_rx_line_endings(s_uart_port, ESP_LINE_ENDINGS_LF); + esp_vfs_dev_uart_port_set_tx_line_endings(s_uart_port, ESP_LINE_ENDINGS_LF); + snprintf(uart_path, sizeof(uart_path), "/dev/uart/%d", s_uart_port); + s_uart_fd = open(uart_path, O_RDWR | O_NONBLOCK); + ESP_RETURN_ON_FALSE(s_uart_fd >= 0, ESP_FAIL, OT_PLAT_LOG_TAG, "open uart_path failed"); + ret = esp_openthread_platform_workflow_register(&esp_openthread_uart_update, &esp_openthread_uart_process, + uart_workflow); return ret; } diff --git a/examples/openthread/ot_br/README.md b/examples/openthread/ot_br/README.md index 33ca9837c9..1e8af0bddb 100644 --- a/examples/openthread/ot_br/README.md +++ b/examples/openthread/ot_br/README.md @@ -40,6 +40,12 @@ Similar to the previous Wi-Fi based Thread Border Route setup, but a device with ``` idf.py menuconfig ``` +OpenThread Command Line is enabled with UART as the default interface. Additionally, USB JTAG is also supported and can be activated through the menuconfig: + +``` +Component config → ESP System Settings → Channel for console output → USB Serial/JTAG Controller +``` + In order to run the example on single SoC which supports both Wi-Fi and Thread, the option `CONFIG_ESP_COEX_SW_COEXIST_ENABLE` and option `CONFIG_OPENTHREAD_RADIO_NATIVE` should be enabled. The two options are enabled by default for ESP32-C6 target. Two ways are provided to setup the Thread Border Router in this example: diff --git a/examples/openthread/ot_br/main/esp_ot_config.h b/examples/openthread/ot_br/main/esp_ot_config.h index f60aadc14e..b7372f4943 100644 --- a/examples/openthread/ot_br/main/esp_ot_config.h +++ b/examples/openthread/ot_br/main/esp_ot_config.h @@ -74,6 +74,7 @@ #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, \ @@ -93,6 +94,13 @@ .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(), \ + } +#endif #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \ diff --git a/examples/openthread/ot_cli/README.md b/examples/openthread/ot_cli/README.md index cce0fa4e66..8535276959 100644 --- a/examples/openthread/ot_cli/README.md +++ b/examples/openthread/ot_cli/README.md @@ -17,7 +17,11 @@ To run this example, a board with IEEE 802.15.4 module (for example ESP32-H2) is idf.py menuconfig ``` -The example can run with the default configuration. +The example can run with the default configuration. OpenThread Command Line is enabled with UART as the default interface. Additionally, USB JTAG is also supported and can be activated through the menuconfig: + +``` +Component config → ESP System Settings → Channel for console output → USB Serial/JTAG Controller +``` ### Build, Flash, and Run diff --git a/examples/openthread/ot_cli/main/esp_ot_config.h b/examples/openthread/ot_cli/main/esp_ot_config.h index a0a1a37a9e..0248a39af1 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-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -44,6 +44,7 @@ } #endif +#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART #define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ @@ -63,6 +64,13 @@ .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(), \ + } +#endif #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \