Merge branch 'feature/console_repl_over_uart_v4.2' into 'release/v4.2'

console_repl over UART (v4.2)

See merge request espressif/esp-idf!9422
This commit is contained in:
Angus Gratton 2020-07-08 16:10:37 +08:00
commit 0cb87f67da
13 changed files with 404 additions and 334 deletions

View file

@ -56,60 +56,49 @@ typedef struct {
uint32_t task_stack_size; //!< repl task stack size uint32_t task_stack_size; //!< repl task stack size
uint32_t task_priority; //!< repl task priority uint32_t task_priority; //!< repl task priority
const char *prompt; //!< prompt (NULL represents default: "esp> ") const char *prompt; //!< prompt (NULL represents default: "esp> ")
union {
struct {
int channel; //!< UART channel
uint32_t baud_rate; //!< Comunication baud rate
int tx_gpio; //!< GPIO number for TX path, -1 means using the default
int rx_gpio; //!< GPIO number for RX path, -1 means using the default
} uart; //!< UART specific configuration
} device; //!< device configuration
} esp_console_repl_config_t; } esp_console_repl_config_t;
#ifdef CONFIG_ESP_CONSOLE_UART_NUM
#define CONSOLE_DEFAULT_UART_CHANNEL CONFIG_ESP_CONSOLE_UART_NUM
#else
#define CONSOLE_DEFAULT_UART_CHANNEL 0
#endif
#ifdef CONFIG_ESP_CONSOLE_UART_BAUDRATE
#define CONSOLE_DEFAULT_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE
#else
#define CONSOLE_DEFAULT_UART_BAUDRATE 115200
#endif
#ifdef CONFIG_ESP_CONSOLE_UART_TX_GPIO
#define CONSOLE_DEFAULT_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO
#else
#define CONSOLE_DEFAULT_UART_TX_GPIO 1
#endif
#ifdef CONFIG_ESP_CONSOLE_UART_RX_GPIO
#define CONSOLE_DEFAULT_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO
#else
#define CONSOLE_DEFAULT_UART_RX_GPIO 3
#endif
/** /**
* @brief Default console repl configuration value * @brief Default console repl configuration value
* *
*/ */
#define ESP_CONSOLE_REPL_CONFIG_DEFAULT() \ #define ESP_CONSOLE_REPL_CONFIG_DEFAULT() \
{ \ { \
.max_history_len = 32, \ .max_history_len = 32, \
.history_save_path = NULL, \ .history_save_path = NULL, \
.task_stack_size = 4096, \ .task_stack_size = 4096, \
.task_priority = 2, \ .task_priority = 2, \
.prompt = NULL, \ .prompt = NULL, \
.device = { \ }
.uart = { \
.channel = CONSOLE_DEFAULT_UART_CHANNEL, \ /**
.baud_rate = CONSOLE_DEFAULT_UART_BAUDRATE, \ * @brief Parameters for console device: UART
.tx_gpio = CONSOLE_DEFAULT_UART_TX_GPIO, \ *
.rx_gpio = CONSOLE_DEFAULT_UART_RX_GPIO, \ */
} \ typedef struct {
} \ int channel; //!< UART channel number (count from zero)
} int baud_rate; //!< Comunication baud rate
int tx_gpio_num; //!< GPIO number for TX path, -1 means using default one
int rx_gpio_num; //!< GPIO number for RX path, -1 means using default one
} esp_console_dev_uart_config_t;
#ifdef CONFIG_ESP_CONSOLE_UART_CUSTOM
#define ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT() \
{ \
.channel = CONFIG_ESP_CONSOLE_UART_NUM, \
.baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, \
.tx_gpio_num = CONFIG_ESP_CONSOLE_UART_TX_GPIO, \
.rx_gpio_num = CONFIG_ESP_CONSOLE_UART_RX_GPIO, \
}
#else
#define ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT() \
{ \
.channel = CONFIG_ESP_CONSOLE_UART_NUM, \
.baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, \
.tx_gpio_num = -1, \
.rx_gpio_num = -1, \
}
#endif
/** /**
* @brief initialize console module * @brief initialize console module
@ -270,10 +259,34 @@ esp_err_t esp_console_register_help_command(void);
/****************************************************************************** /******************************************************************************
* Console REPL * Console REPL
******************************************************************************/ ******************************************************************************/
/** /**
* @brief Initialize console REPL environment * @brief Type defined for console REPL
* *
* @param config REPL configuration */
typedef struct esp_console_repl_s esp_console_repl_t;
/**
* @brief Console REPL base structure
*
*/
struct esp_console_repl_s {
/**
* @brief Delete console REPL environment
* @param[in] repl REPL handle returned from esp_console_new_repl_xxx
* @return
* - ESP_OK on success
* - ESP_FAIL on errors
*/
esp_err_t (*del)(esp_console_repl_t *repl);
};
/**
* @brief Establish a console REPL environment over UART driver
*
* @param[in] dev_config UART device 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: * @note This is a all-in-one function to establish the environment needed for REPL, includes:
* - Install the UART driver on the console UART (8n1, 115200, REF_TICK clock source) * - Install the UART driver on the console UART (8n1, 115200, REF_TICK clock source)
@ -289,27 +302,17 @@ esp_err_t esp_console_register_help_command(void);
* - ESP_OK on success * - ESP_OK on success
* - ESP_FAIL Parameter error * - ESP_FAIL Parameter error
*/ */
esp_err_t esp_console_repl_init(const esp_console_repl_config_t *config); 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 Start REPL task * @brief Start REPL environment
* * @param[in] repl REPL handle returned from esp_console_new_repl_xxx
* @note Once the REPL got started, it won't be stopped until user call repl->del(repl) to destory the REPL environment.
* @return * @return
* - ESP_OK on success * - ESP_OK on success
* - ESP_ERR_INVALID_STATE, if repl has started already * - ESP_ERR_INVALID_STATE, if repl has started already
*/ */
esp_err_t esp_console_repl_start(void); esp_err_t esp_console_start_repl(esp_console_repl_t *repl);
/**
* @brief Register a 'quit' command
*
* Default 'quit' command will destory resources and exit REPL environment.
*
* @return
* - ESP_OK on success
* - others on failed
*/
esp_err_t esp_console_register_quit_command(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,4 +1,4 @@
// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD // Copyright 2016-2020 Espressif Systems (Shanghai) PTE LTD
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -14,6 +14,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <sys/cdefs.h>
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
@ -24,9 +25,9 @@
#include "driver/uart.h" #include "driver/uart.h"
#include "linenoise/linenoise.h" #include "linenoise/linenoise.h"
static const char *TAG = "console.repl"; static const char *TAG = "console.repl.uart";
#define CONSOLE_PROMPT_LEN_MAX (32) #define CONSOLE_PROMPT_MAX_LEN (32)
typedef enum { typedef enum {
CONSOLE_REPL_STATE_DEINIT, CONSOLE_REPL_STATE_DEINIT,
@ -34,38 +35,244 @@ typedef enum {
CONSOLE_REPL_STATE_START, CONSOLE_REPL_STATE_START,
} repl_state_t; } repl_state_t;
static repl_state_t s_repl_state = CONSOLE_REPL_STATE_DEINIT; typedef struct {
esp_console_repl_t repl_core; // base class
char prompt[CONSOLE_PROMPT_MAX_LEN]; // Prompt to be printed before each line
repl_state_t state;
const char *history_save_path;
TaskHandle_t task_hdl; // REPL task handle
} esp_console_repl_com_t;
/** typedef struct {
* @brief Prompt to be printed before each line. esp_console_repl_com_t repl_com; // base class
* int uart_channel; // uart channel number
*/ } esp_console_repl_uart_t;
static char s_prompt[CONSOLE_PROMPT_LEN_MAX];
/** static void esp_console_repl_task(void *args);
* @brief path to save history commands in file system static esp_err_t esp_console_repl_uart_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 const char *s_history_save_path = NULL; 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_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 default uart channel number
*
*/
static int s_uart_channel = -1;
/**
* @brief REPL task handle
*
*/
static TaskHandle_t s_repl_task_hdl = NULL;
static void esp_console_repl_thread(void *param)
{ {
esp_err_t ret = ESP_OK;
esp_console_repl_uart_t *uart_repl = NULL;
if (!repl_config | !dev_config | !ret_repl) {
ret = ESP_ERR_INVALID_ARG;
goto _exit;
}
// allocate memory for console REPL context
uart_repl = calloc(1, sizeof(esp_console_repl_uart_t));
if (!uart_repl) {
ret = ESP_ERR_NO_MEM;
goto _exit;
}
/* Drain stdout before reconfiguring it */
fflush(stdout);
fsync(fileno(stdout));
/* Disable buffering on stdin */
setvbuf(stdin, NULL, _IONBF, 0);
/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
/* Move the caret to the beginning of the next line on '\n' */
esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
/* Configure UART. Note that REF_TICK is used so that the baud rate remains
* correct while APB frequency is changing in light sleep mode.
*/
const uart_config_t uart_config = {
.baud_rate = dev_config->baud_rate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.source_clk = UART_SCLK_REF_TICK,
};
uart_param_config(dev_config->channel, &uart_config);
uart_set_pin(dev_config->channel, dev_config->tx_gpio_num, dev_config->rx_gpio_num, -1, -1);
/* Install UART driver for interrupt-driven reads and writes */
ret = uart_driver_install(dev_config->channel, 256, 0, 0, NULL, 0);
if (ret != ESP_OK) {
goto _exit;
}
/* Tell VFS to use UART driver */
esp_vfs_dev_uart_use_driver(dev_config->channel);
// initialize console, common part
ret = esp_console_common_init(&uart_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, &uart_repl->repl_com);
if (ret != ESP_OK) {
goto _exit;
}
// setup prompt
esp_console_setup_prompt(repl_config->prompt, &uart_repl->repl_com);
/* spawn a single thread to run REPL */
if (xTaskCreate(esp_console_repl_task, "console_repl", repl_config->task_stack_size,
&uart_repl->repl_com, repl_config->task_priority, &uart_repl->repl_com.task_hdl) != pdTRUE) {
ret = ESP_FAIL;
goto _exit;
}
uart_repl->uart_channel = dev_config->channel;
uart_repl->repl_com.state = CONSOLE_REPL_STATE_INIT;
uart_repl->repl_com.repl_core.del = esp_console_repl_uart_delete;
*ret_repl = &uart_repl->repl_com.repl_core;
return ESP_OK;
_exit:
if (uart_repl) {
esp_console_deinit();
uart_driver_delete(dev_config->channel);
free(uart_repl);
}
if (ret_repl) {
*ret_repl = NULL;
}
return ret;
}
esp_err_t esp_console_start_repl(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);
// check if already initialized
if (repl_com->state != CONSOLE_REPL_STATE_INIT) {
ret = ESP_ERR_INVALID_STATE;
goto _exit;
}
repl_com->state = CONSOLE_REPL_STATE_START;
xTaskNotifyGive(repl_com->task_hdl);
return ESP_OK;
_exit:
return ret;
}
static esp_err_t esp_console_setup_prompt(const char *prompt, esp_console_repl_com_t *repl_com)
{
/* set command line prompt */
const char *prompt_temp = "esp>";
if (prompt) {
prompt_temp = prompt;
}
snprintf(repl_com->prompt, CONSOLE_PROMPT_MAX_LEN - 1, LOG_COLOR_I "%s " LOG_RESET_COLOR, prompt_temp);
printf("\r\n"
"Type 'help' to get the list of commands.\r\n"
"Use UP/DOWN arrows to navigate through command history.\r\n"
"Press TAB when typing command name to auto-complete.\r\n");
/* Figure out if the terminal supports escape sequences */
int probe_status = linenoiseProbe();
if (probe_status) {
/* zero indicates success */
printf("\r\n"
"Your terminal application does not support escape sequences.\n\n"
"Line editing and history features are disabled.\n\n"
"On Windows, try using Putty instead.\r\n");
linenoiseSetDumbMode(1);
#if CONFIG_LOG_COLORS
/* Since the terminal doesn't support escape sequences,
* don't use color codes in the s_prompt.
*/
snprintf(repl_com->prompt, CONSOLE_PROMPT_MAX_LEN - 1, "%s ", prompt_temp);
#endif //CONFIG_LOG_COLORS
}
return ESP_OK;
}
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 ret = ESP_OK;
repl_com->history_save_path = history_path;
if (history_path) {
/* Load command history from filesystem */
linenoiseHistoryLoad(history_path);
}
/* Set command history size */
if (linenoiseHistorySetMaxLen(max_history_len) != 1) {
ESP_LOGE(TAG, "set max history length to %d failed", max_history_len);
ret = ESP_FAIL;
goto _exit;
}
return ESP_OK;
_exit:
return ret;
}
static esp_err_t esp_console_common_init(esp_console_repl_com_t *repl_com)
{
esp_err_t ret = ESP_OK;
/* Initialize the console */
esp_console_config_t console_config = ESP_CONSOLE_CONFIG_DEFAULT();
#if CONFIG_LOG_COLORS
console_config.hint_color = atoi(LOG_COLOR_CYAN);
#endif
ret = esp_console_init(&console_config);
if (ret != ESP_OK) {
goto _exit;
}
ret = esp_console_register_help_command();
if (ret != ESP_OK) {
goto _exit;
}
/* Configure linenoise line completion library */
/* Enable multiline editing. If not set, long commands will scroll within single line */
linenoiseSetMultiLine(1);
/* Tell linenoise where to get command completions and hints */
linenoiseSetCompletionCallback(&esp_console_get_completion);
linenoiseSetHintsCallback((linenoiseHintsCallback *)&esp_console_get_hint);
return ESP_OK;
_exit:
return ret;
}
static esp_err_t esp_console_repl_uart_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_uart_t *uart_repl = __containerof(repl_com, esp_console_repl_uart_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();
esp_vfs_dev_uart_use_nonblocking(uart_repl->uart_channel);
uart_driver_delete(uart_repl->uart_channel);
free(uart_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;
// waiting for task notify // waiting for task notify
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
while (s_repl_state == CONSOLE_REPL_STATE_START) { while (repl_com->state == CONSOLE_REPL_STATE_START) {
char *line = linenoise(s_prompt); char *line = linenoise(repl_com->prompt);
if (line == NULL) { if (line == NULL) {
ESP_LOGD(TAG, "empty line"); ESP_LOGD(TAG, "empty line");
/* Ignore empty lines */ /* Ignore empty lines */
@ -74,8 +281,8 @@ static void esp_console_repl_thread(void *param)
/* Add the command to the history */ /* Add the command to the history */
linenoiseHistoryAdd(line); linenoiseHistoryAdd(line);
/* Save command history to filesystem */ /* Save command history to filesystem */
if (s_history_save_path) { if (repl_com->history_save_path) {
linenoiseHistorySave(s_history_save_path); linenoiseHistorySave(repl_com->history_save_path);
} }
/* Try to run the command */ /* Try to run the command */
@ -96,199 +303,3 @@ static void esp_console_repl_thread(void *param)
ESP_LOGD(TAG, "The End"); ESP_LOGD(TAG, "The End");
vTaskDelete(NULL); vTaskDelete(NULL);
} }
esp_err_t esp_console_repl_init(const esp_console_repl_config_t *config)
{
esp_err_t ret = ESP_OK;
if (!config) {
ret = ESP_ERR_INVALID_ARG;
goto _exit;
}
// check if already initialized
if (s_repl_state != CONSOLE_REPL_STATE_DEINIT) {
ESP_LOGE(TAG, "already initialized");
ret = ESP_ERR_INVALID_STATE;
goto _exit;
}
/* Drain stdout before reconfiguring it */
fflush(stdout);
fsync(fileno(stdout));
/* Disable buffering on stdin */
setvbuf(stdin, NULL, _IONBF, 0);
/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
/* Move the caret to the beginning of the next line on '\n' */
esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
/* Configure UART. Note that REF_TICK is used so that the baud rate remains
* correct while APB frequency is changing in light sleep mode.
*/
const uart_config_t uart_config = {
.baud_rate = config->device.uart.baud_rate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.source_clk = UART_SCLK_REF_TICK,
};
/* Install UART driver for interrupt-driven reads and writes */
ret = uart_driver_install(config->device.uart.channel, 256, 0, 0, NULL, 0);
if (ret != ESP_OK) {
goto _exit;
}
s_uart_channel = config->device.uart.channel;
uart_param_config(s_uart_channel, &uart_config);
uart_set_pin(s_uart_channel, config->device.uart.tx_gpio, config->device.uart.rx_gpio, -1, -1);
/* Tell VFS to use UART driver */
esp_vfs_dev_uart_use_driver(s_uart_channel);
/* Initialize the console */
esp_console_config_t console_config = ESP_CONSOLE_CONFIG_DEFAULT();
#if CONFIG_LOG_COLORS
console_config.hint_color = atoi(LOG_COLOR_CYAN);
#endif
ret = esp_console_init(&console_config);
if (ret != ESP_OK) {
goto _console_del;
}
ret = esp_console_register_help_command();
if (ret != ESP_OK) {
goto _console_del;
}
ret = esp_console_register_quit_command();
if (ret != ESP_OK) {
goto _console_del;
}
/* Configure linenoise line completion library */
/* Enable multiline editing. If not set, long commands will scroll within single line */
linenoiseSetMultiLine(1);
/* Tell linenoise where to get command completions and hints */
linenoiseSetCompletionCallback(&esp_console_get_completion);
linenoiseSetHintsCallback((linenoiseHintsCallback *)&esp_console_get_hint);
if (config->history_save_path) {
s_history_save_path = config->history_save_path;
/* Load command history from filesystem */
linenoiseHistoryLoad(s_history_save_path);
}
/* Set command history size */
if (linenoiseHistorySetMaxLen(config->max_history_len) != 1) {
ESP_LOGE(TAG, "set max history length to %d failed", config->max_history_len);
ret = ESP_FAIL;
goto _console_del;
}
/* set command line prompt */
const char *prompt_temp = "esp>";
if (config->prompt) {
prompt_temp = config->prompt;
}
snprintf(s_prompt, CONSOLE_PROMPT_LEN_MAX - 1, LOG_COLOR_I "%s " LOG_RESET_COLOR, prompt_temp);
printf("\r\n"
"Type 'help' to get the list of commands.\r\n"
"Use UP/DOWN arrows to navigate through command history.\r\n"
"Press TAB when typing command name to auto-complete.\r\n");
/* Figure out if the terminal supports escape sequences */
int probe_status = linenoiseProbe();
if (probe_status) {
/* zero indicates success */
printf("\r\n"
"Your terminal application does not support escape sequences.\n\n"
"Line editing and history features are disabled.\n\n"
"On Windows, try using Putty instead.\r\n");
linenoiseSetDumbMode(1);
#if CONFIG_LOG_COLORS
/* Since the terminal doesn't support escape sequences,
* don't use color codes in the s_prompt.
*/
snprintf(s_prompt, CONSOLE_PROMPT_LEN_MAX - 1, "%s ", prompt_temp);
#endif //CONFIG_LOG_COLORS
}
/* spawn a single thread to run REPL */
if (xTaskCreate(esp_console_repl_thread, "console_repl", config->task_stack_size,
NULL, config->task_priority, &s_repl_task_hdl) != pdTRUE) {
ret = ESP_FAIL;
goto _console_del;
}
s_repl_state = CONSOLE_REPL_STATE_INIT;
return ret;
_console_del:
esp_console_deinit();
esp_vfs_dev_uart_use_nonblocking(s_uart_channel);
uart_driver_delete(s_uart_channel);
s_uart_channel = -1;
s_repl_state = CONSOLE_REPL_STATE_DEINIT;
_exit:
return ret;
}
esp_err_t esp_console_repl_deinit(void)
{
esp_err_t ret = ESP_OK;
// check if already de-initialized
if (s_repl_state == CONSOLE_REPL_STATE_DEINIT) {
ESP_LOGE(TAG, "not initialized yet");
ret = ESP_ERR_INVALID_STATE;
goto _exit;
}
s_repl_state = CONSOLE_REPL_STATE_DEINIT;
esp_console_deinit();
esp_vfs_dev_uart_use_nonblocking(s_uart_channel);
uart_driver_delete(s_uart_channel);
s_uart_channel = -1;
s_repl_task_hdl = NULL;
s_history_save_path = NULL;
_exit:
return ret;
}
esp_err_t esp_console_repl_start(void)
{
esp_err_t ret = ESP_OK;
// check if already initialized
if (s_repl_state != CONSOLE_REPL_STATE_INIT) {
ret = ESP_ERR_INVALID_STATE;
goto _exit;
}
s_repl_state = CONSOLE_REPL_STATE_START;
xTaskNotifyGive(s_repl_task_hdl);
_exit:
return ret;
}
/* handle 'quit' command */
static int do_cmd_quit(int argc, char **argv)
{
printf("ByeBye\r\n");
esp_console_repl_deinit();
return 0;
}
esp_err_t esp_console_register_quit_command(void)
{
esp_console_cmd_t command = {
.command = "quit",
.help = "Quit REPL environment",
.func = &do_cmd_quit
};
return esp_console_cmd_register(&command);
}

View file

@ -30,11 +30,30 @@ TEST_CASE("esp console init/deinit test", "[console]")
TEST_ESP_OK(esp_console_deinit()); TEST_ESP_OK(esp_console_deinit());
} }
static esp_console_repl_t *s_repl = NULL;
/* handle 'quit' command */
static int do_cmd_quit(int argc, char **argv)
{
printf("ByeBye\r\n");
s_repl->del(s_repl);
return 0;
}
// Enter "quit" to exit REPL environment // Enter "quit" to exit REPL environment
TEST_CASE("esp console repl test", "[console][ignore]") TEST_CASE("esp console repl test", "[console][ignore]")
{ {
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
TEST_ESP_OK(esp_console_repl_init(&repl_config)); esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
TEST_ESP_OK(esp_console_repl_start()); TEST_ESP_OK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
esp_console_cmd_t cmd = {
.command = "quit",
.help = "Quit REPL environment",
.func = &do_cmd_quit
};
TEST_ESP_OK(esp_console_cmd_register(&cmd));
TEST_ESP_OK(esp_console_start_repl(s_repl));
vTaskDelay(pdMS_TO_TICKS(2000)); vTaskDelay(pdMS_TO_TICKS(2000));
} }

View file

@ -148,9 +148,9 @@ Initialize console REPL environment
To establish a basic REPL environment, ``console`` component provides several useful APIs, combining those functions described above. To establish a basic REPL environment, ``console`` component provides several useful APIs, combining those functions described above.
In a typical application, you only need to call :cpp:func:`esp_console_repl_init` to initialize the REPL environment, including UART driver install, basic console configuration, spawning a thread to do REPL task and register several useful commands (e.g. `help`, `quit`). In a typical application, you only need to call :cpp:func:`esp_console_new_repl_uart` to initialize the REPL environment based on UART device, including driver install, basic console configuration, spawning a thread to do REPL task and register several useful commands (e.g. `help`).
After that, you can register your own commands with :cpp:func:`esp_console_cmd_register`. The REPL environment keeps in init state until you call :cpp:func:`esp_console_repl_start`. After that, you can register your own commands with :cpp:func:`esp_console_cmd_register`. The REPL environment keeps in init state until you call :cpp:func:`esp_console_start_repl`.
Application Example Application Example
------------------- -------------------

View file

@ -162,9 +162,9 @@ Linenoise 库不需要显式地初始化,但是在调用行编辑函数之前
``console`` 组建还提供了一些 API 来帮助创建一个基本的 REPL 环境。 ``console`` 组建还提供了一些 API 来帮助创建一个基本的 REPL 环境。
在一个典型的 console 应用中,你只需要调用 :cpp:func:`esp_console_repl_init`,它会为你初始化好 REPL 环境,其中包括安装 UART 驱动,基本的 console 配置,创建一个新的线程来执行 REPL 任务,注册一些基本的命令(比如 `help``quit` 命令)。 在一个典型的 console 应用中,你只需要调用 :cpp:func:`esp_console_new_repl_uart`,它会为你初始化好构建在 UART 基础上的 REPL 环境,其中包括安装 UART 驱动,基本的 console 配置,创建一个新的线程来执行 REPL 任务,注册一些基本的命令(比如 `help` 命令)。
完了之后你可以使用 :cpp:func:`esp_console_cmd_register` 来注册其它命令。REPL 环境在初始化后需要再调用 :cpp:func:`esp_console_repl_start` 函数才能开始运行。 完了之后你可以使用 :cpp:func:`esp_console_cmd_register` 来注册其它命令。REPL 环境在初始化后需要再调用 :cpp:func:`esp_console_start_repl` 函数才能开始运行。
应用程序示例 应用程序示例

View file

@ -91,14 +91,16 @@ void app_main(void)
printf("esp32_bluetooth_init failed (ret %d)", res); printf("esp32_bluetooth_init failed (ret %d)", res);
} }
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
const char* prompt = LOG_COLOR_I "esp32> " LOG_RESET_COLOR; esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
repl_config.prompt = prompt;
#if CONFIG_STORE_HISTORY #if CONFIG_STORE_HISTORY
initialize_filesystem(); initialize_filesystem();
repl_config.his_save_path = HISTORY_PATH; repl_config.history_save_path = HISTORY_PATH;
#endif #endif
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); repl_config.prompt = "ble_mesh_node>";
// init console REPL environment
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
/* Register commands */ /* Register commands */
register_system(); register_system();
@ -110,5 +112,5 @@ void app_main(void)
#endif #endif
// start console REPL // start console REPL
ESP_ERROR_CHECK(esp_console_repl_start()); ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }

View file

@ -95,15 +95,16 @@ void app_main(void)
printf("esp32_bluetooth_init failed (ret %d)", res); printf("esp32_bluetooth_init failed (ret %d)", res);
} }
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
const char* prompt = LOG_COLOR_I "esp32> " LOG_RESET_COLOR; esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
repl_config.prompt = prompt;
#if CONFIG_STORE_HISTORY #if CONFIG_STORE_HISTORY
initialize_filesystem(); initialize_filesystem();
repl_config.his_save_path = HISTORY_PATH; repl_config.history_save_path = HISTORY_PATH;
#endif #endif
repl_config.prompt = "ble_mesh_prov>";
// init console REPL environment // init console REPL environment
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
/* Register commands */ /* Register commands */
register_system(); register_system();
@ -121,5 +122,5 @@ void app_main(void)
#endif #endif
// start console REPL // start console REPL
ESP_ERROR_CHECK(esp_console_repl_start()); ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }

View file

@ -141,9 +141,9 @@ static esp_ble_mesh_model_t root_models[] = {
static esp_ble_mesh_model_t vnd_models[] = { static esp_ble_mesh_model_t vnd_models[] = {
ESP_BLE_MESH_VENDOR_MODEL(CID_ESP, ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_SRV, ESP_BLE_MESH_VENDOR_MODEL(CID_ESP, ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_SRV,
fast_prov_srv_op, NULL, &fast_prov_server), fast_prov_srv_op, NULL, &fast_prov_server),
ESP_BLE_MESH_VENDOR_MODEL(CID_ESP, ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI, ESP_BLE_MESH_VENDOR_MODEL(CID_ESP, ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI,
fast_prov_cli_op, NULL, &fast_prov_client), fast_prov_cli_op, NULL, &fast_prov_client),
}; };
static esp_ble_mesh_elem_t elements[] = { static esp_ble_mesh_elem_t elements[] = {
@ -249,7 +249,7 @@ static void provisioner_prov_complete(int node_idx, const uint8_t uuid[16], uint
return; return;
} }
if (fast_prov_server.node_addr_cnt != FAST_PROV_NODE_COUNT_MIN && if (fast_prov_server.node_addr_cnt != FAST_PROV_NODE_COUNT_MIN &&
fast_prov_server.node_addr_cnt <= fast_prov_server.max_node_num) { fast_prov_server.node_addr_cnt <= fast_prov_server.max_node_num) {
if (bt_mesh_atomic_test_and_clear_bit(fast_prov_server.srv_flags, GATT_PROXY_ENABLE_START)) { if (bt_mesh_atomic_test_and_clear_bit(fast_prov_server.srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_cancel(&fast_prov_server.gatt_proxy_enable_timer); k_delayed_work_cancel(&fast_prov_server.gatt_proxy_enable_timer);
} }
@ -355,7 +355,7 @@ static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT: case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT"); ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT");
node_prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr, node_prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr,
param->node_prov_complete.flags, param->node_prov_complete.iv_index); param->node_prov_complete.flags, param->node_prov_complete.iv_index);
break; break;
case ESP_BLE_MESH_NODE_PROXY_GATT_DISABLE_COMP_EVT: case ESP_BLE_MESH_NODE_PROXY_GATT_DISABLE_COMP_EVT:
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROXY_GATT_DISABLE_COMP_EVT"); ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROXY_GATT_DISABLE_COMP_EVT");
@ -665,7 +665,7 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t
err = example_handle_config_app_key_add_evt(param->value.state_change.appkey_add.app_idx); err = example_handle_config_app_key_add_evt(param->value.state_change.appkey_add.app_idx);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: Failed to bind app_idx 0x%04x with non-config models", ESP_LOGE(TAG, "%s: Failed to bind app_idx 0x%04x with non-config models",
__func__, param->value.state_change.appkey_add.app_idx); __func__, param->value.state_change.appkey_add.app_idx);
return; return;
} }
break; break;
@ -679,16 +679,16 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t
} }
static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event, static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event,
esp_ble_mesh_generic_server_cb_param_t *param) esp_ble_mesh_generic_server_cb_param_t *param)
{ {
ESP_LOGI(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x", ESP_LOGI(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x",
event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst); event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst);
switch (event) { switch (event) {
case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT: case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT"); ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT");
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET || if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||
param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) { param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
ESP_LOGI(TAG, "onoff 0x%02x", param->value.state_change.onoff_set.onoff); ESP_LOGI(TAG, "onoff 0x%02x", param->value.state_change.onoff_set.onoff);
example_change_led_state(param->value.state_change.onoff_set.onoff); example_change_led_state(param->value.state_change.onoff_set.onoff);
} }
@ -748,9 +748,11 @@ static void wifi_console_init(void)
{ {
initialise_wifi(); initialise_wifi();
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); 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();
// init console REPL environment // init console REPL environment
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
/* Register commands */ /* Register commands */
register_wifi(); register_wifi();
@ -766,7 +768,7 @@ static void wifi_console_init(void)
printf(" =================================================\n\n"); printf(" =================================================\n\n");
// start console REPL // start console REPL
ESP_ERROR_CHECK(esp_console_repl_start()); ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }
void app_main(void) void app_main(void)

View file

@ -40,13 +40,16 @@ static void initialize_filesystem(void)
void app_main(void) void app_main(void)
{ {
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); 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 #if CONFIG_EXAMPLE_STORE_HISTORY
initialize_filesystem(); initialize_filesystem();
repl_config.history_save_path = HISTORY_PATH; repl_config.history_save_path = HISTORY_PATH;
#endif #endif
// initialize console REPL environment repl_config.prompt = "iperf>";
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); // init console REPL environment
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
/* Register commands */ /* Register commands */
register_system(); register_system();
@ -64,5 +67,5 @@ void app_main(void)
printf(" =======================================================\n\n"); printf(" =======================================================\n\n");
// start console REPL // start console REPL
ESP_ERROR_CHECK(esp_console_repl_start()); ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }

View file

@ -40,14 +40,16 @@ static void initialize_filesystem(void)
void app_main(void) void app_main(void)
{ {
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); 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 #if CONFIG_EXAMPLE_STORE_HISTORY
initialize_filesystem(); initialize_filesystem();
repl_config.history_save_path = HISTORY_PATH; repl_config.history_save_path = HISTORY_PATH;
#endif #endif
repl_config.prompt = "i2c-tools>"; repl_config.prompt = "i2c-tools>";
// initialize console REPL environment // init console REPL environment
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
register_i2ctools(); register_i2ctools();
register_system(); register_system();
@ -65,5 +67,5 @@ void app_main(void)
printf(" ==============================================================\n\n"); printf(" ==============================================================\n\n");
// start console REPL // start console REPL
ESP_ERROR_CHECK(esp_console_repl_start()); ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }

View file

@ -75,7 +75,7 @@ static struct {
struct arg_int *tos; struct arg_int *tos;
struct arg_str *host; struct arg_str *host;
struct arg_end *end; struct arg_end *end;
} ping_args;; } ping_args;
static int do_ping_cmd(int argc, char **argv) static int do_ping_cmd(int argc, char **argv)
{ {
@ -161,6 +161,26 @@ static void register_ping(void)
ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd)); ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd));
} }
static esp_console_repl_t *s_repl = NULL;
/* handle 'quit' command */
static int do_cmd_quit(int argc, char **argv)
{
printf("ByeBye\r\n");
s_repl->del(s_repl);
return 0;
}
static esp_err_t register_quit(void)
{
esp_console_cmd_t command = {
.command = "quit",
.help = "Quit REPL environment",
.func = &do_cmd_quit
};
return esp_console_cmd_register(&command);
}
void app_main(void) void app_main(void)
{ {
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
@ -170,12 +190,15 @@ void app_main(void)
ESP_ERROR_CHECK(example_connect()); ESP_ERROR_CHECK(example_connect());
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); 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();
// init console REPL environment // init console REPL environment
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
/* register command `ping` */ /* register command `ping` */
register_ping(); register_ping();
/* register command `quit` */
register_quit();
// start console REPL // start console REPL
ESP_ERROR_CHECK(esp_console_repl_start()); ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
} }

View file

@ -27,10 +27,12 @@ void app_main(void)
initialise_wifi(); initialise_wifi();
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); 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>"; repl_config.prompt = "iperf>";
// init console REPL // init console REPL environment
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
/* Register commands */ /* Register commands */
register_system(); register_system();
register_wifi(); register_wifi();
@ -46,6 +48,6 @@ void app_main(void)
printf(" =================================================\n\n"); printf(" =================================================\n\n");
// start console REPL // start console REPL
ESP_ERROR_CHECK(esp_console_repl_start()); ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }

View file

@ -179,15 +179,16 @@ void app_main(void)
/* Initialize WiFi */ /* Initialize WiFi */
initialize_wifi(); initialize_wifi();
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); 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 #if CONFIG_SNIFFER_STORE_HISTORY
initialize_filesystem(); initialize_filesystem();
repl_config.history_save_path = HISTORY_FILE_PATH; repl_config.history_save_path = HISTORY_FILE_PATH;
#endif #endif
repl_config.prompt = "sniffer>"; repl_config.prompt = "sniffer>";
/* Initialize Console REPL environment */ // init console REPL environment
ESP_ERROR_CHECK(esp_console_repl_init(&repl_config)); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
/* Register commands */ /* Register commands */
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD #if CONFIG_SNIFFER_PCAP_DESTINATION_SD
@ -207,5 +208,6 @@ void app_main(void)
printf(" | |\n"); printf(" | |\n");
printf(" =======================================================\n\n"); printf(" =======================================================\n\n");
ESP_ERROR_CHECK(esp_console_repl_start()); // start console REPL
ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }