Программирование ARM: работа с USB ESP-IDF: зависание, если нет соединения через USB Sun, July 12 2026  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


ESP-IDF: зависание, если нет соединения через USB Печать
Добавил(а) microsin   

Проблема с проектом ESP-IDF: если не подключен виртуальный последовательный порт к хосту USB (т. е. к хосту отладки), то программа перестает работать. Возможные причины такой ситуации описаны ниже.

[Перегруженный вывод]

Программа перестает работать, так как функции вывода (например, printf или ESP_LOGI) в ESP-IDF по умолчанию используют виртуальный USB-порт. Если порт не подключен, буфер передачи заполняется, и выполнение блокируется в ожидании хоста (USB).

Эту проблему можно решить программно или изменив настройки конфигурации.

1. Отключение блокирующего вывода

В коде программы (например, в задаче FreeRTOS) используйте функции, которые не будут бесконечно ждать отправки, если USB-хост отключен.

Если вы используете компонент esp_console или usb_serial_jtag, убедитесь, что операции вывода не блокируют планировщик наглухо.

2. Изменение настроек в menuconfig

Вы можете перенаправить вывод логов с виртуального USB на обычный физический UART или задать таймауты в ESP-IDF menuconfig:

● Перенаправление вывода на UART: перейдите в Component config -> ESP System Settings и в параметре Channel for console output (или UART for console output) выберите физический UART вместо USB CDC / USB Serial/JTAG Controller.
● Изменение поведения USB: в параметрах USB отключите опцию энергосбережения CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB.

[Блокирующий режим драйвера]

Для микроконтроллера ESP32-S3 в ESP-IDF зависание при отключенном USB CDC может происходить из-за того, что драйвер usb_serial_jtag по умолчанию работает в блокирующем режиме. Когда буфер передачи заполняется, функции логирования (ESP_LOGx, printf) бесконечно ждут подтверждения от USB-хоста.

Вот три способа решить эту проблему.

1. Изменение настроек в menuconfig (рекомендуемый способ)

Вы можете отключить блокировку при заполнении буфера прямо в конфигурации проекта. В этом случае, если USB не подключен, логи будут просто отбрасываться, а программа продолжит работать.

- Откройте терминал и запустите: idf.py menuconfig.
- Перейдите по пути: Component config → ESP System Settings.
- Найдите параметр: Channel for console output.
- Убедитесь, что выбран вариант USB Serial/JTAG Controller (если вы выводите логи через него).
- Ниже появится параметр: Drop console output if USB CDC is not connected (CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_BUFF_FAIL_DROP).
- Включите этот параметр (поставьте галочку [X]).
- Сохраните настройки (S) и выйдите (Q).

2. Изменение таймаута блокировки в коде

Если вы хотите управлять поведением USB-порта прямо из кода (например, динамически менять таймаут), вы можете установить нулевое время ожидания для драйвера usb_serial_jtag:

#include "driver/usb_serial_jtag.h"
#include "esp_vfs_usb_serial_jtag.h"

void app_main(void) {
// Инициализация VFS для USB Serial/JTAG (обычно вызывается автоматически)
esp_vfs_dev_usb_serial_jtag_register();

// Установка таймаута отправки в 0 (не ждать хост, если буфер полон)
usb_serial_jtag_ll_set_tx_timeout(0);

// Альтернативный вариант через драйвер (если используется usb_serial_jtag_driver_install):
// usb_serial_jtag_set_tx_timeout(0);

ESP_LOGI("MAIN", "Программа не будет зависать без USB!"); }

3. Проверка подключения перед отправкой (для Native USB CDC)

Если вы используете стек TinyUSB (tinyusb компонент), а не встроенный usb_serial_jtag, то перед отправкой данных всегда проверяйте, готов ли хост принимать данные:

#include "tusb.h"

void send_data_task(void *pvParameters) {
while (1) {
// Проверяем, подключен ли виртуальный COM-порт к компьютеру
if (tud_cdc_connected()) {
printf("Хост подключен, отправляем данные...\n");
} else {
// Хост отключен — логируем в пустоту или пропускаем шаг
}
vTaskDelay(pdMS_TO_TICKS(1000));
} }

[Проблема с питанием]

1. Иногда проблема связана с тем, что плата перезагружается при подключении к USB или испытывает скачок напряжения. Убедитесь, что вы используете качественный кабель, передающий данные (а не только питание), и при необходимости подайте внешнее питание 5 В на ножки платы.

2. Возможно медленное нарастание напряжения питания микроконтроллера, и по этой причине сброс программы происходит позже, чем начинает работу внешнее оборудование. Т. е. при подключенном кабеле USB, когда микроконтроллер постоянно получает питание, момент сброса программы после прошивки (idf.py flash) или при подключении монитора (idf.py monitor) происходит в других интервалах времени по отношению к включению питания других схем, и программа ведет себя по-другому.

Именно с таким случаем я как раз и столкнулся. Выглядело это как непредсказуемое поведение программы в разных вариантах компиляции. Заработает программа нормально или нет при включении питания зависело от разных факторов, которые никак не должны влиять на работоспособность. Т. е. если к примеру скомпилировать поддержку Ethernet, то программа запускается нормально, даже если кабель USB не подключен, а если код Ethernet выкинуть, то программа запускается только если подключен кабель USB. Если нажать кнопку сброса, то программа запускается всегда нормально.

Что можно сделать в этом случае:

1. Проверить скорость нарастания питания микроконтроллера, формирование сигнала сброса. Как вариант применить внешний аппаратный супервизор питания, генерирующий сброс микроконтроллера.

2. Опытным путем добавить и подобрать в программе задержки для запуска отдельных потоков в коде. Для моего случая помогло простое добавление vTaskDelay(pdMS_TO_TICKS(1000)) в самом начале тела функции app_main.

[Решение проблемы]

Ообычно основная причина зависания — бесконечное ожидание очистки TX-буфера. Активация опции CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_BUFF_FAIL_DROP в menuconfig или принудительная установка таймаута usb_serial_jtag_ll_set_tx_timeout(0) полностью устраняют блокировку программы при отключенном USB-кабеле. Но могут быть и другие причины, вызванные взамодействием потоков в программе и внешним оборудованием.

[Ссылки]

1. ESP-IDF FAQ.

 

Добавить комментарий


Защитный код
Обновить

Top of Page