ESP-IDF: как сделать интерактивную консоль |
![]() |
Добавил(а) microsin | ||||||||||||
Рабочие примеры организации интерактивной консоли можно найти в папке examples/system/console каталога установки ESP-IDF. Там есть два примера: advanced и basic, отличаются они функциональными возможностями. У примера advanced доступны сохранение истории команд в файловой системе и редактирование строки команды. Процесс добавления интерактивной консоли в проект ESP32-C3 на основе примера advanced, процесс по шагам: 1. idf.py menuconfig: поменяйте опцию Component config → ESP System Settings → Channel for console output на "(X) USB Serial/JTAG Controller" (это установит опцию CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y). Можно выбрать и другие варианты: Default: UART0, USB CDC, Custom UART, None. Замечание: набор доступных вариантов для опции Channel for console output может меняться в зависимости от используемого чипа. Например, для всех чипов доступен вариант UART0, для чипов ESP32S2 и ESP32S3 доступен вариант USB CDC. 2. Скопируйте папку components из примера advanced в корневой каталог своего проекта. Также скопируйте в свою папку main файлы console_settings.c и console_settings.h из папки advanced/main примера. 3. Откройте в текстовом редакторе файл main/CMakeLists.txt своего проекта. В секцию исходного кода SRCS добавьте console_settings.c, а в секцию PRIV_REQUIRES добавьте компоненты console, esp_driver_usb_serial_jtag, cmd_system. После этого файл main/CMakeLists.txt может выглядеть следующим образом (список файлов исходного кода и компонентов может отличаться, в зависимости от вашего проекта): idf_component_register(SRCS "main.c" "console_settings.c" PRIV_REQUIRES spi_flash esp_driver_gpio esp_driver_uart console esp_driver_usb_serial_jtag cmd_system INCLUDE_DIRS "") 4. Добавьте в модуль проекта, где будет использоваться консоль, подключение следующих заголовков: #include "console_settings.h" Замечание: если вы будете использовать сохранение в энергонезависимой памяти истории команд (определяется активацией опции CONFIG_CONSOLE_STORE_HISTORY), то может понадобиться также добавление в main/CMakeLists.txt компонентов fatfs, nvs_flash а также необходимо подключение заголовков: #include "esp_vfs_fat.h" 5. По аналогии с модулем main/console_example_main.c из примера advanced добавьте инициализацию консоли: static const char *prompt; 6. Добавьте в какой-нибудь поток обработку консоли, опять-таки на основе примера advanced (см. цикл while функции app_main в исходном коде main/console_example_main.c): // Получение введенной пользователем строки с помощью // библиотеки linenoise. Возврат из этого вызова // произойдет, когда пользователь нажал ENTER. char* line = linenoise(prompt); Обратите внимание, что вызов функции linenoise блокирующий (на ожидании окончания ввода пользователя по нажатию ENTER в консоли), поэтому для обеспечения работы другого функционала программы (в частности, для отображения отладочного вывода в той же консоли) для linenoise необходим отдельный поток. Скомпилируйте и запустите проект, как обычно. Вы увидите вот такую консоль (выход из монитора по умолчанию Ctrl+]): $ idf.py build flash monitor --port=/dev/ttyACM0 ... This is esp32c3 chip with 1 CPU core(s), WiFi/BLE, silicon revision v0.3, 2MB external flash Minimum free heap size: 308528 bytes [Добавление и изменение списка поддерживаемых команд консоли] В папке components, которая была скопирована на шаге 2, имеется модуль cmd_system/cmd_system_common.c. В нем регистрируются все команды, которые поддерживает консоль. По умолчанию уже зарегистрированы следующие команды:
Свои собственные команды можно создать по аналогии этих команд. Пример регистрации команды "test", которая будет принимать один числовой аргумент: 1. Создайте функцию регистрации команды register_test: static struct { struct arg_str *tag; struct arg_end *end; } test_args; 2. Создайте функцию обработчика команды func_test: static int func_test(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **) &test_args); if (nerrors != 0) { arg_print_errors(stderr, test_args.end, argv[0]); return 1; } assert(test_args.tag->count == 1); //printf("argv[0]: %s\n", argv[0]); printf("Запуск %i проверок\n", atoi(argv[1])); return 0; } Параметры, передаваемые в команде, доступны в виде текстовых строк в массиве argv. 3. Добавьте вызов register_test в функцию register_system_common: void register_system_common(void) { register_free(); register_heap(); register_version(); register_restart(); [Ссылки] |