Merge branch 'feature/console_repl_on_usb_cdc' into 'master'

console repl over usb cdc

Closes IDF-1644

See merge request espressif/esp-idf!8969
This commit is contained in:
Angus Gratton
2020-11-17 07:14:16 +08:00
7 changed files with 157 additions and 8 deletions

View File

@@ -100,6 +100,20 @@ typedef struct {
}
#endif
/**
* @brief Parameters for console device: USB CDC
*
* @note It's an empty structure for now, reserved for future
*
*/
typedef struct {
} esp_console_dev_usb_cdc_config_t;
#define ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT() \
{ \
}
/**
* @brief initialize console module
* @param config console configuration
@@ -304,6 +318,27 @@ struct esp_console_repl_s {
*/
esp_err_t esp_console_new_repl_uart(const esp_console_dev_uart_config_t *dev_config, const esp_console_repl_config_t *repl_config, esp_console_repl_t **ret_repl);
/**
* @brief Establish a console REPL environment over USB CDC
*
* @param[in] dev_config USB CDC configuration
* @param[in] repl_config REPL configuration
* @param[out] ret_repl return REPL handle after initialization succeed, return NULL otherwise
*
* @note This is a all-in-one function to establish the environment needed for REPL, includes:
* - Initializes linenoise
* - Spawn new thread to run REPL in the background
*
* @attention This function is meant to be used in the examples to make the code more compact.
* Applications which use console functionality should be based on
* the underlying linenoise and esp_console functions.
*
* @return
* - ESP_OK on success
* - ESP_FAIL Parameter error
*/
esp_err_t esp_console_new_repl_usb_cdc(const esp_console_dev_usb_cdc_config_t *dev_config, const esp_console_repl_config_t *repl_config, esp_console_repl_t **ret_repl);
/**
* @brief Start REPL environment
* @param[in] repl REPL handle returned from esp_console_new_repl_xxx

View File

@@ -14,18 +14,20 @@
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/cdefs.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_console.h"
#include "esp_vfs_dev.h"
#include "esp_vfs_cdcacm.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "linenoise/linenoise.h"
static const char *TAG = "console.repl.uart";
static const char *TAG = "console.repl";
#define CONSOLE_PROMPT_MAX_LEN (32)
@@ -48,12 +50,81 @@ typedef struct {
int uart_channel; // uart channel number
} esp_console_repl_uart_t;
typedef struct {
esp_console_repl_com_t repl_com; // base class
} esp_console_repl_usb_cdc_t;
static void esp_console_repl_task(void *args);
static esp_err_t esp_console_repl_uart_delete(esp_console_repl_t *repl);
static esp_err_t esp_console_repl_usb_cdc_delete(esp_console_repl_t *repl);
static esp_err_t esp_console_common_init(esp_console_repl_com_t *repl_com);
static esp_err_t esp_console_setup_prompt(const char *prompt, esp_console_repl_com_t *repl_com);
static esp_err_t esp_console_setup_history(const char *history_path, uint32_t max_history_len, esp_console_repl_com_t *repl_com);
esp_err_t esp_console_new_repl_usb_cdc(const esp_console_dev_usb_cdc_config_t *dev_config, const esp_console_repl_config_t *repl_config, esp_console_repl_t **ret_repl)
{
esp_err_t ret = ESP_OK;
esp_console_repl_usb_cdc_t *cdc_repl = NULL;
if (!repl_config | !dev_config | !ret_repl) {
ret = ESP_ERR_INVALID_ARG;
goto _exit;
}
// allocate memory for console REPL context
cdc_repl = calloc(1, sizeof(esp_console_repl_usb_cdc_t));
if (!cdc_repl) {
ret = ESP_ERR_NO_MEM;
goto _exit;
}
/* Disable buffering on stdin */
setvbuf(stdin, NULL, _IONBF, 0);
/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
esp_vfs_dev_cdcacm_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
/* Move the caret to the beginning of the next line on '\n' */
esp_vfs_dev_cdcacm_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
/* Enable non-blocking mode on stdin and stdout */
fcntl(fileno(stdout), F_SETFL, 0);
fcntl(fileno(stdin), F_SETFL, 0);
// initialize console, common part
ret = esp_console_common_init(&cdc_repl->repl_com);
if (ret != ESP_OK) {
goto _exit;
}
// setup history
ret = esp_console_setup_history(repl_config->history_save_path, repl_config->max_history_len, &cdc_repl->repl_com);
if (ret != ESP_OK) {
goto _exit;
}
// setup prompt
esp_console_setup_prompt(repl_config->prompt, &cdc_repl->repl_com);
/* spawn a single thread to run REPL */
if (xTaskCreate(esp_console_repl_task, "console_repl", repl_config->task_stack_size,
&cdc_repl->repl_com, repl_config->task_priority, &cdc_repl->repl_com.task_hdl) != pdTRUE) {
ret = ESP_FAIL;
goto _exit;
}
cdc_repl->repl_com.state = CONSOLE_REPL_STATE_INIT;
cdc_repl->repl_com.repl_core.del = esp_console_repl_usb_cdc_delete;
*ret_repl = &cdc_repl->repl_com.repl_core;
return ESP_OK;
_exit:
if (cdc_repl) {
esp_console_deinit();
free(cdc_repl);
}
if (ret_repl) {
*ret_repl = NULL;
}
return ret;
}
esp_err_t esp_console_new_repl_uart(const esp_console_dev_uart_config_t *dev_config, const esp_console_repl_config_t *repl_config, esp_console_repl_t **ret_repl)
{
esp_err_t ret = ESP_OK;
@@ -266,6 +337,24 @@ _exit:
return ret;
}
static esp_err_t esp_console_repl_usb_cdc_delete(esp_console_repl_t *repl)
{
esp_err_t ret = ESP_OK;
esp_console_repl_com_t *repl_com = __containerof(repl, esp_console_repl_com_t, repl_core);
esp_console_repl_usb_cdc_t *cdc_repl = __containerof(repl_com, esp_console_repl_usb_cdc_t, repl_com);
// check if already de-initialized
if (repl_com->state == CONSOLE_REPL_STATE_DEINIT) {
ESP_LOGE(TAG, "already de-initialized");
ret = ESP_ERR_INVALID_STATE;
goto _exit;
}
repl_com->state = CONSOLE_REPL_STATE_DEINIT;
esp_console_deinit();
free(cdc_repl);
_exit:
return ret;
}
static void esp_console_repl_task(void *args)
{
esp_console_repl_com_t *repl_com = (esp_console_repl_com_t *)args;

View File

@@ -15,7 +15,7 @@
#endif
#define SHUTDOWN_HANDLERS_NO 2
#define SHUTDOWN_HANDLERS_NO 3
static shutdown_handler_t shutdown_handlers[SHUTDOWN_HANDLERS_NO];
esp_err_t esp_register_shutdown_handler(shutdown_handler_t handler)

View File

@@ -42,14 +42,21 @@ void app_main(void)
{
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
#if CONFIG_EXAMPLE_STORE_HISTORY
initialize_filesystem();
repl_config.history_save_path = HISTORY_PATH;
#endif
repl_config.prompt = "i2c-tools>";
// init console REPL environment
// install console REPL environment
#if CONFIG_ESP_CONSOLE_UART
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
#elif CONFIG_ESP_CONSOLE_USB_CDC
esp_console_dev_usb_cdc_config_t cdc_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&cdc_config, &repl_config, &repl));
#endif
register_i2ctools();
register_system();

View File

@@ -197,9 +197,14 @@ void app_main(void)
ESP_ERROR_CHECK(example_connect());
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
// install console REPL environment
#if CONFIG_ESP_CONSOLE_UART
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
// init console REPL environment
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
#elif CONFIG_ESP_CONSOLE_USB_CDC
esp_console_dev_usb_cdc_config_t cdc_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&cdc_config, &repl_config, &s_repl));
#endif
/* register command `ping` */
register_ping();

View File

@@ -29,10 +29,17 @@ void app_main(void)
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
repl_config.prompt = "iperf>";
// init console REPL environment
#if CONFIG_ESP_CONSOLE_UART
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
#elif CONFIG_ESP_CONSOLE_USB_CDC
esp_console_dev_usb_cdc_config_t cdc_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&cdc_config, &repl_config, &repl));
#endif
/* Register commands */
register_system();
register_wifi();

View File

@@ -181,14 +181,20 @@ void app_main(void)
initialize_wifi();
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
#if CONFIG_SNIFFER_STORE_HISTORY
initialize_filesystem();
repl_config.history_save_path = HISTORY_FILE_PATH;
#endif
repl_config.prompt = "sniffer>";
// init console REPL environment
// install console REPL environment
#if CONFIG_ESP_CONSOLE_UART
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
#elif CONFIG_ESP_CONSOLE_USB_CDC
esp_console_dev_usb_cdc_config_t cdc_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&cdc_config, &repl_config, &repl));
#endif
/* Register commands */
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD