Merge branch 'refactor/console_examples' into 'master'

console examples cleanup and refactoring

See merge request espressif/esp-idf!17984
pull/8968/head
Ivan Grokhotkov 2022-05-04 18:10:31 +08:00
commit e350fac374
18 zmienionych plików z 111 dodań i 255 usunięć

Wyświetl plik

@ -0,0 +1,27 @@
# Console examples
(See the README.md file in the upper level 'examples' directory for more information about examples.)
Examples in this directory illustrate the usage of the [Console Component](https://docs.espressif.com/projects/esp-idf/en/stable/api-guides/console.html#console) to create an interactive shell on the ESP chip.
## basic example
This example illustrates high-level Read-Eval-Print Loop API (`esp_console_repl`).
This example can be used with UART, USB_OTG or USB_SERIAL_JTAG peripherals. It works on all ESP chips.
It is the recommended starting point when getting familiar with console component.
## advanced example
This example illustrates lower-level APIs for line editing and autocompletion (`linenoise`), argument parsing (`argparse3`) and command registration (`esp_console`).
These APIs allow for a lot of flexibility when building a console application, but require more code to be written.
While these APIs allow for a console to be implemented over various interfaces (UART, USB, TCP), this example works with UART only.
## advanced_usb_cdc example
This example is similar to the one above, except it works over USB CDC provided by USB_OTG peripheral.
Currently it can be used on ESP32-S2.

Wyświetl plik

@ -0,0 +1,3 @@
idf_component_register(SRCS "cmd_wifi.c"
INCLUDE_DIRS .
REQUIRES console esp_wifi)

Wyświetl plik

@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Console example — WiFi commands
This example code is in the Public Domain (or CC0 licensed, at your option.)
@ -12,7 +17,6 @@
#include "esp_log.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "cmd_decl.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"

Wyświetl plik

@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Console example — declarations of command registration functions.
This example code is in the Public Domain (or CC0 licensed, at your option.)

Wyświetl plik

@ -1,3 +1,2 @@
idf_component_register(SRCS "cmd_wifi.c"
"console_example_main.c"
idf_component_register(SRCS "console_example_main.c"
INCLUDE_DIRS ".")

Wyświetl plik

@ -1,21 +0,0 @@
/* Console example — declarations of command registration functions.
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.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "cmd_system.h"
#include "cmd_wifi.h"
#include "cmd_nvs.h"
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -1,132 +0,0 @@
/* Console example — WiFi commands
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 <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "cmd_decl.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "cmd_wifi.h"
#define JOIN_TIMEOUT_MS (10000)
static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
}
}
static void initialise_wifi(void)
{
esp_log_level_set("wifi", ESP_LOG_WARN);
static bool initialized = false;
if (initialized) {
return;
}
ESP_ERROR_CHECK(esp_netif_init());
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
assert(ap_netif);
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &event_handler, NULL) );
ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
ESP_ERROR_CHECK( esp_wifi_start() );
initialized = true;
}
static bool wifi_join(const char *ssid, const char *pass, int timeout_ms)
{
initialise_wifi();
wifi_config_t wifi_config = { 0 };
strlcpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
if (pass) {
strlcpy((char *) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password));
}
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
esp_wifi_connect();
int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
pdFALSE, pdTRUE, timeout_ms / portTICK_PERIOD_MS);
return (bits & CONNECTED_BIT) != 0;
}
/** Arguments used by 'join' function */
static struct {
struct arg_int *timeout;
struct arg_str *ssid;
struct arg_str *password;
struct arg_end *end;
} join_args;
static int connect(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &join_args);
if (nerrors != 0) {
arg_print_errors(stderr, join_args.end, argv[0]);
return 1;
}
ESP_LOGI(__func__, "Connecting to '%s'",
join_args.ssid->sval[0]);
/* set default value*/
if (join_args.timeout->count == 0) {
join_args.timeout->ival[0] = JOIN_TIMEOUT_MS;
}
bool connected = wifi_join(join_args.ssid->sval[0],
join_args.password->sval[0],
join_args.timeout->ival[0]);
if (!connected) {
ESP_LOGW(__func__, "Connection timed out");
return 1;
}
ESP_LOGI(__func__, "Connected");
return 0;
}
void register_wifi(void)
{
join_args.timeout = arg_int0(NULL, "timeout", "<t>", "Connection timeout, ms");
join_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
join_args.password = arg_str0(NULL, NULL, "<pass>", "PSK of AP");
join_args.end = arg_end(2);
const esp_console_cmd_t join_cmd = {
.command = "join",
.help = "Join WiFi AP as a station",
.hint = NULL,
.func = &connect,
.argtable = &join_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&join_cmd) );
}

Wyświetl plik

@ -1,20 +0,0 @@
/* Console example — declarations of command registration functions.
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.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// Register WiFi functions
void register_wifi(void);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -16,10 +16,12 @@
#include "driver/uart.h"
#include "linenoise/linenoise.h"
#include "argtable3/argtable3.h"
#include "cmd_decl.h"
#include "esp_vfs_fat.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "cmd_system.h"
#include "cmd_wifi.h"
#include "cmd_nvs.h"
#ifdef CONFIG_ESP_CONSOLE_USB_CDC
#error This example is incompatible with USB CDC console. Please try "console_usb" example instead.

Wyświetl plik

@ -1,11 +1,11 @@
| Supported Targets | ESP32-S2 |
| ----------------- | -------- |
# USB Console Example
# USB_OTG CDC Console Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example is similar to the [console example](../console/advanced/README.md), but instead of the UART it uses USB CDC for console output.
This example is similar to the [advanced console example](../advanced/README.md), but instead of the UART it uses the USB CDC port provided by USB_OTG peripheral for console output.
The example uses the [Console Component](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/console.html#console) to create an interactive shell.
The interactive shell implemented in this example contains a wide variety of commands, and can act as a basis for applications that require a command-line interface (CLI).

Wyświetl plik

@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* USB console example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@ -15,11 +20,12 @@
#include "esp_console.h"
#include "linenoise/linenoise.h"
#include "argtable3/argtable3.h"
#include "cmd_nvs.h"
#include "cmd_system.h"
#include "esp_vfs_cdcacm.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "cmd_nvs.h"
#include "cmd_system.h"
#include "cmd_wifi.h"
static void initialize_nvs(void)
{
@ -80,6 +86,7 @@ void app_main(void)
register_system_common();
register_system_sleep();
register_nvs();
register_wifi();
/* Prompt to be printed before each line.
* This can be customized, made dynamic, etc.

Wyświetl plik

@ -1,24 +1,48 @@
# Console Example
# Basic Console Example (`esp_console_repl`)
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example illustrates the usage of the [Console Component](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/console.html#console) to create an interactive shell on the ESP chip. The interactive shell running on the ESP chip can then be controlled/interacted with over a serial port (UART).
This example illustrates the usage of the REPL (Read-Eval-Print Loop) APIs of the [Console Component](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/console.html#console) to create an interactive shell on the ESP chip. The interactive shell running on the ESP chip can then be controlled/interacted with over a serial interface. This example supports UART and USB interfaces.
The interactive shell implemented in this example contains a wide variety of commands, and can act as a basis for applications that require a command-line interface (CLI).
Compared to the [advanced console example](../advanced), this example requires less code to initialize and run the console. `esp_console_repl` API handles most of the details. If you'd like to customize the way console works (for example, process console commands in an existing task), please check the advanced console example.
## How to use example
### Hardware Required
This example can be used on boards with UART and USB interfaces. The sections below explain how to set up the board and configure the example.
This example should be able to run on any commonly available Espressif development board.
### Using with UART
### Configure the project
When UART interface is used, this example should run on any commonly available Espressif development board. UART interface is enabled by default (`CONFIG_ESP_CONSOLE_UART_DEFAULT` option in menuconfig). No extra configuration is required.
```
idf.py menuconfig
```
### Using with USB_SERIAL_JTAG
* Enable/disable `Example Configuration > Store command history in flash` as necessary
On chips with USB_SERIAL_JTAG peripheral, console example can be used over the USB serial port.
* First, connect the USB cable to the USB_SERIAL_JTAG interface.
* Second, run `idf.py menuconfig` and enable `CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG` option.
For more details about connecting and configuring USB_SERIAL_JTAG (including pin numbers), see the IDF Programming Guide:
* [ESP32-C3 USB_SERIAL_JTAG](https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-guides/usb-serial-jtag-console.html)
* [ESP32-S3 USB_SERIAL_JTAG](https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-guides/usb-serial-jtag-console.html)
### Using with USB CDC (USB_OTG peripheral)
USB_OTG peripheral can also provide a USB serial port which works with this example.
* First, connect the USB cable to the USB_OTG peripheral interface.
* Second, run `idf.py menuconfig` and enable `CONFIG_ESP_CONSOLE_USB_CDC` option.
For more details about connecting and configuring USB_OTG (including pin numbers), see the IDF Programming Guide:
* [ESP32-S2 USB_OTG](https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-guides/usb-otg-console.html)
* [ESP32-S3 USB_OTG](https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-guides/usb-otg-console.html)
### Other configuration options
This example has an option to store the command history in Flash. This option is enabled by default.
To disable this, run `idf.py menuconfig` and disable `CONFIG_CONSOLE_STORE_HISTORY` option.
### Build and Flash
@ -36,7 +60,9 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
## Example Output
Enter the `help` command get a full list of all available commands. The following is a sample session of the Console Example where a variety of commands provided by the Console Example are used. Note that GPIO15 is connected to GND to remove the boot log output.
Enter the `help` command get a full list of all available commands. The following is a sample session of the Console Example where a variety of commands provided by the Console Example are used.
On ESP32, GPIO15 may be connected to GND to remove the boot log output.
```
This is an example of ESP-IDF console component.
@ -119,33 +145,3 @@ Line editing and history features are disabled.
On Windows, try using Putty instead.
esp32>
```
## Example Breakdown
### Configuring UART
The ``initialize_console()`` function in the example configures some aspects of UART relevant to the operation of the console.
- **Line Endings**: The default line endings are configured to match those expected/generated by common serial monitor programs, such as `screen`, `minicom`, and the `idf_monitor.py` included in the SDK. The default behavior for these commands are:
- When 'enter' key is pressed on the keyboard, `CR` (0x13) code is sent to the serial device.
- To move the cursor to the beginning of the next line, serial device needs to send `CR LF` (0x13 0x10) sequence.
### Line editing
The main source file of the example illustrates how to use `linenoise` library, including line completion, hints, and history.
### Commands
Several commands are registered using `esp_console_cmd_register()` function. See the `register_wifi()` and `register_system()` functions in `cmd_wifi.c` and `cmd_system.c` files.
### Command handling
Main loop inside `app_main()` function illustrates how to use `linenoise` and `esp_console_run()` to implement read/eval loop.
### Argument parsing
Several commands implemented in `cmd_wifi.c` and `cmd_system.c` use the Argtable3 library to parse and check the arguments.
### Command history
Each time a new command line is obtained from `linenoise`, it is written into history and the history is saved into a file in flash memory. On reset, history is initialized from that file.

Wyświetl plik

@ -1,3 +1,2 @@
idf_component_register(SRCS "cmd_wifi.c"
"console_example_main.c"
idf_component_register(SRCS "console_example_main.c"
INCLUDE_DIRS ".")

Wyświetl plik

@ -1,21 +0,0 @@
/* Console example — declarations of command registration functions.
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.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "cmd_system.h"
#include "cmd_wifi.h"
#include "cmd_nvs.h"
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -1,4 +1,4 @@
/* Console example
/* Basic console example (esp_console_repl API)
This example code is in the Public Domain (or CC0 licensed, at your option.)
@ -13,17 +13,12 @@
#include "esp_log.h"
#include "esp_console.h"
#include "esp_vfs_dev.h"
#include "driver/uart.h"
#include "linenoise/linenoise.h"
#include "argtable3/argtable3.h"
#include "cmd_decl.h"
#include "esp_vfs_fat.h"
#include "nvs.h"
#include "nvs_flash.h"
#ifdef CONFIG_ESP_CONSOLE_USB_CDC
#error This example is incompatible with USB CDC console. Please try "console_usb" example instead.
#endif // CONFIG_ESP_CONSOLE_USB_CDC
#include "cmd_system.h"
#include "cmd_wifi.h"
#include "cmd_nvs.h"
static const char* TAG = "example";
#define PROMPT_STR CONFIG_IDF_TARGET
@ -66,7 +61,6 @@ 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();
/* Prompt to be printed before each line.
* This can be customized, made dynamic, etc.
*/
@ -89,7 +83,21 @@ void app_main(void)
register_wifi();
register_nvs();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
#if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) || defined(CONFIG_ESP_CONSOLE_UART_CUSTOM)
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
#elif defined(CONFIG_ESP_CONSOLE_USB_CDC)
esp_console_dev_usb_cdc_config_t hw_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&hw_config, &repl_config, &repl));
#elif defined(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG)
esp_console_dev_usb_serial_jtag_config_t hw_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl));
#else
#error Unsupported console type
#endif
ESP_ERROR_CHECK(esp_console_start_repl(repl));
}