diff --git a/examples/system/console_usb/CMakeLists.txt b/examples/system/console_usb/CMakeLists.txt new file mode 100644 index 0000000000..e3fd240d48 --- /dev/null +++ b/examples/system/console_usb/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/system/console/components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(console_usb) diff --git a/examples/system/console_usb/README.md b/examples/system/console_usb/README.md new file mode 100644 index 0000000000..e2dc5b192f --- /dev/null +++ b/examples/system/console_usb/README.md @@ -0,0 +1,146 @@ +| Supported Targets | ESP32-S2 | +| ----------------- | -------- | + +# USB 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/README.md), but instead of the UART it uses USB CDC 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). + +## How to use example + +### Hardware Required + +This example can run on an ESP32-S2 development board, with a USB cable connected to GPIO19 and GPIO20. + +### Build and Flash + +Build the project, by running: + +``` +idf.py build +``` + +First time flashing can be done over USB or over UART. + +#### Flashing the project for the first time using UART + +This is the same procedure described in the Getting Started Guide. Flashing is done using a USB-Serial adapter included on the development board. Determine the device name of the serial port (`PORT`) and run: + +``` +idf.py -p PORT flash +``` + +#### Flashing the project for the first time using USB + +We can also use the ESP32-S2 built-in USB bootloader to flash the program for the first time. + +1. Connect the development board using a USB breakout cable to the computer. +2. Put the chip into bootloader (download) mode, by holding "Boot" button (connected to GPIO0) and pressing "Reset" button. +3. A USB serial port device will appear in the system: + - On Windows, it will be one of COM ports + - On Linux, it will by /dev/ttyACMn (n is some number) + - On macOS, it will be /dev/tty.usbmodemN (N is some number) + + If the port doesn't appear, check that the board has entered the bootloader mode, and that the USB cable is connected correctly. + +4. Flash the board: + +``` +idf.py -p PORT flash +``` + +### View the console output over USB + +Once the board is flashed for the first time, a USB serial port will appear in the system. + +**Note: if you have used the step above to flash the board over USB, note that the port name may change after flashing!** + +To start the monitor, run: + +``` +idf.py -p PORT monitor +``` + +To exit the serial monitor, type ``Ctrl-]``. + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## 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. + +``` +This is an example of ESP-IDF console component. +Type 'help' to get the list of commands. +Use UP/DOWN arrows to navigate through command history. +Press TAB when typing command name to auto-complete. +esp32s2> help +help + Print the list of registered commands + +free + Get the current size of free heap memory + +heap + Get minimum size of free heap memory that was available during program execution + +version + Get version of chip and SDK + +restart + Software reset of the chip + +tasks + Get information about running tasks + +(remaining output of the help command skipped here) + +esp32s2> free +237824 +I (39864) cmd_system: Restarting +I (185) spi_flash: detected chip: generic +I (186) spi_flash: flash io: dio +I (186) cpu_start: Starting scheduler on PRO CPU. + +This is an example of ESP-IDF console component. +Type 'help' to get the list of commands. +Use UP/DOWN arrows to navigate through command history. +Press TAB when typing command name to auto-complete. +esp32s2> +``` + +## Troubleshooting + +### Line Endings + +The line endings in the Console Example are configured to match particular serial monitors. Therefore, if the following log output appears, consider using a different serial monitor (e.g. Putty for Windows). + +``` +This is an example of ESP-IDF console component. +Type 'help' to get the list of commands. +Use UP/DOWN arrows to navigate through command history. +Press TAB when typing command name to auto-complete. +Your terminal application does not support escape sequences. +Line editing and history features are disabled. +On Windows, try using Putty instead. +esp32s2> +``` + +### No USB port appears + +On Windows 10, macOS, Linux, USB CDC devices do not require additional drivers to be installed. + +If the USB serial port doesn't appear in the system after flashing the example, check the following: + +* Check that the USB device is detected by the OS. + VID/PID pair for ESP32-S2 is 303a:0002. + + - On Windows, check the Device Manager + - On macOS, check USB section in the System Information utility + - On Linux, check `lsusb` output + +* If the device is not detected, check the USB cable connection (D+, D-, and ground should be connected) diff --git a/examples/system/console_usb/main/CMakeLists.txt b/examples/system/console_usb/main/CMakeLists.txt new file mode 100644 index 0000000000..bf1d5041d2 --- /dev/null +++ b/examples/system/console_usb/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "console_usb_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/system/console_usb/main/console_usb_example_main.c b/examples/system/console_usb/main/console_usb_example_main.c new file mode 100644 index 0000000000..fab9d9e55e --- /dev/null +++ b/examples/system/console_usb/main/console_usb_example_main.c @@ -0,0 +1,137 @@ +/* USB console example + + 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 +#include +#include +#include "esp_system.h" +#include "esp_log.h" +#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" + +static void initialize_nvs(void) +{ + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK( nvs_flash_erase() ); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); +} + +static void initialize_console(void) +{ + /* 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 the console */ + esp_console_config_t console_config = { + .max_cmdline_args = 8, + .max_cmdline_length = 256, +#if CONFIG_LOG_COLORS + .hint_color = atoi(LOG_COLOR_CYAN) +#endif + }; + ESP_ERROR_CHECK( esp_console_init(&console_config) ); + + /* 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); + + /* Set command history size */ + linenoiseHistorySetMaxLen(10); +} + +void app_main(void) +{ + initialize_nvs(); + + initialize_console(); + + /* Register commands */ + esp_console_register_help_command(); + register_system_common(); + register_nvs(); + + /* Prompt to be printed before each line. + * This can be customized, made dynamic, etc. + */ + const char* prompt = LOG_COLOR_I CONFIG_IDF_TARGET "> " LOG_RESET_COLOR; + + printf("\n" + "This is an example of ESP-IDF console component.\n" + "Type 'help' to get the list of commands.\n" + "Use UP/DOWN arrows to navigate through command history.\n" + "Press TAB when typing command name to auto-complete.\n"); + + /* Figure out if the terminal supports escape sequences */ + int probe_status = linenoiseProbe(); + if (probe_status) { /* zero indicates success */ + printf("\n" + "Your terminal application does not support escape sequences.\n" + "Line editing and history features are disabled.\n" + "On Windows, try using Putty instead.\n"); + linenoiseSetDumbMode(1); +#if CONFIG_LOG_COLORS + /* Since the terminal doesn't support escape sequences, + * don't use color codes in the prompt. + */ + prompt = CONFIG_IDF_TARGET "> "; +#endif //CONFIG_LOG_COLORS + } + + /* Main loop */ + while(true) { + /* Get a line using linenoise. + * The line is returned when ENTER is pressed. + */ + char* line = linenoise(prompt); + if (line == NULL) { /* Ignore empty lines */ + continue; + } + /* Add the command to the history */ + linenoiseHistoryAdd(line); + + /* Try to run the command */ + int ret; + esp_err_t err = esp_console_run(line, &ret); + if (err == ESP_ERR_NOT_FOUND) { + printf("Unrecognized command\n"); + } else if (err == ESP_ERR_INVALID_ARG) { + // command was empty + } else if (err == ESP_OK && ret != ESP_OK) { + printf("Command returned non-zero error code: 0x%x (%s)\n", ret, esp_err_to_name(ret)); + } else if (err != ESP_OK) { + printf("Internal error: %s\n", esp_err_to_name(err)); + } + /* linenoise allocates line buffer on the heap, so need to free it */ + linenoiseFree(line); + } +} diff --git a/examples/system/console_usb/sdkconfig.defaults b/examples/system/console_usb/sdkconfig.defaults new file mode 100644 index 0000000000..d87eb3e60b --- /dev/null +++ b/examples/system/console_usb/sdkconfig.defaults @@ -0,0 +1,13 @@ +# Build for ESP32-S2 by default +CONFIG_IDF_TARGET="esp32s2" + +# Enable USB console +CONFIG_ESP_CONSOLE_USB_CDC=y + +# Reduce bootloader log verbosity +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_BOOTLOADER_LOG_LEVEL=2 + +# Enable FreeRTOS stats formatting functions, needed for 'tasks' command +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y