Skip to content

Commit

Permalink
Merge branch 'feature/openthread_uart_api_refactor' into 'master'
Browse files Browse the repository at this point in the history
feat(openthread): Host connection logic refactor

See merge request espressif/esp-idf!26215
  • Loading branch information
chshu committed Oct 16, 2023
2 parents 3d064c4 + 8ba1f55 commit fbf8d06
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 47 deletions.
15 changes: 15 additions & 0 deletions components/openthread/Kconfig
Expand Up @@ -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
Expand Down
17 changes: 11 additions & 6 deletions 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
*/
Expand All @@ -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"
Expand Down Expand Up @@ -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;

/**
Expand All @@ -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;

/**
Expand All @@ -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;
Expand Down
Expand Up @@ -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.
Expand Down
32 changes: 28 additions & 4 deletions 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
*/
Expand Down Expand Up @@ -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_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_uart_init(const esp_openthread_platform_config_t *config);
esp_err_t esp_openthread_host_rcp_uart_init(const esp_openthread_platform_config_t *config);

/**
* @brief Deintializes the uart for OpenThread host connection.
Expand Down
61 changes: 43 additions & 18 deletions 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
*/
Expand Down Expand Up @@ -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");
Expand All @@ -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");
Expand All @@ -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();
}

Expand Down
2 changes: 1 addition & 1 deletion components/openthread/src/port/esp_openthread_spi_slave.c
Expand Up @@ -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 = {
Expand Down
58 changes: 43 additions & 15 deletions 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
*/
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions examples/openthread/ot_br/README.md
Expand Up @@ -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:
Expand Down
8 changes: 8 additions & 0 deletions examples/openthread/ot_br/main/esp_ot_config.h
Expand Up @@ -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, \
Expand All @@ -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() \
{ \
Expand Down
6 changes: 5 additions & 1 deletion examples/openthread/ot_cli/README.md
Expand Up @@ -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

Expand Down
10 changes: 9 additions & 1 deletion 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
*
Expand Down Expand Up @@ -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, \
Expand All @@ -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() \
{ \
Expand Down

0 comments on commit fbf8d06

Please sign in to comment.