mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'fix/usb_cdc_example' into 'master'
fix(usb/host): Update CDC example so it opens device with any VID/PID Closes IEC-404 See merge request espressif/esp-idf!44117
This commit is contained in:
@@ -5,22 +5,46 @@
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example shows how to use the CDC-ACM Host Driver to allow an ESP chip to communicate with a USB CDC-ACM device.
|
||||
## Overview
|
||||
|
||||
This example demonstrates how to use the [CDC-ACM Host Driver](https://components.espressif.com/components/espressif/usb_host_cdc_acm) to enable an ESP chip to communicate with a USB CDC-ACM (Communication Device Class - Abstract Control Model) device. CDC-ACM is a USB device class specification that allows USB devices to appear as serial ports, commonly used by USB-to-UART converters and virtual COM port devices.
|
||||
|
||||
The example performs the following operations:
|
||||
|
||||
1. Installs the USB Host Library and CDC-ACM driver
|
||||
2. Waits for a CDC-ACM device to be connected
|
||||
3. Opens the first available CDC-ACM device found
|
||||
4. Prints the device descriptor information
|
||||
5. Sends test data to the device
|
||||
6. Receives data from the device (handled via callback)
|
||||
7. Demonstrates line coding commands (get/set baud rate, data bits, stop bits, parity)
|
||||
8. Demonstrates control line state commands (DTR/RTS)
|
||||
9. Waits for device disconnection and repeats the process
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
Two development boards with USB-OTG support. One will act as USB host and the other as USB device.
|
||||
* Development board with USB-OTG support that will act as USB host
|
||||
* USB CDC-ACM device. This can be:
|
||||
- A USB-to-UART converter (e.g., CP210x, FTDI FT23x, CH34x)
|
||||
- Another ESP development board configured as a USB serial device (see [tusb_serial_device example](../../../device/tusb_serial_device))
|
||||
- Another ESP development board connected with USB-Serial-JTAG
|
||||
- Any other USB device that implements the CDC-ACM class
|
||||
|
||||
#### Pin Assignment
|
||||
|
||||
Follow instruction in [examples/usb/README.md](../../../README.md) for specific hardware setup.
|
||||
Follow instructions in [examples/usb/README.md](../../../README.md) for specific hardware setup.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
1. Build and flash [tusb_serial_device example](../../../device/tusb_serial_device) to USB device board.
|
||||
2. Build this project and flash it to the USB host board, then run monitor tool to view serial output:
|
||||
1. Prepare the USB CDC device:
|
||||
- If using a USB-to-UART converter, no preparation is needed
|
||||
- If using another ESP board as a USB device, build and flash the [tusb_serial_device example](../../../device/tusb_serial_device) to that board first
|
||||
|
||||
2. Connect the CDC device to the USB Host port
|
||||
|
||||
3. Build this project and flash it to the USB host board, then run monitor tool to view serial output:
|
||||
|
||||
```bash
|
||||
idf.py -p PORT flash monitor
|
||||
@@ -34,24 +58,50 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
||||
|
||||
## Example Output
|
||||
|
||||
After the flashing you should see the output at idf monitor:
|
||||
After flashing and connecting a CDC-ACM device, you should see output similar to the following in the idf monitor:
|
||||
|
||||
```
|
||||
...
|
||||
I (256) USB-CDC: USB Host installed
|
||||
I (256) USB-CDC: Opening CDC ACM device 0x303A:0x4001
|
||||
...
|
||||
Device descriptor is printed here
|
||||
...
|
||||
I (1666) USB-CDC: Data received
|
||||
I (1666) USB-CDC: 0x3ffc4c20 41 54 0d |AT.|
|
||||
I (2666) USB-CDC: Data received
|
||||
I (2666) USB-CDC: 0x3ffc4c20 41 54 2b 47 53 4e 0d |AT+GSN.|
|
||||
I (3666) USB-CDC: Setting up line coding
|
||||
I (3666) USB-CDC: Line Get: Rate: 115200, Stop bits: 0, Parity: 0, Databits: 8
|
||||
I (3666) USB-CDC: Line Set: Rate: 9600, Stop bits: 1, Parity: 1, Databits: 7
|
||||
I (3666) USB-CDC: Line Get: Rate: 9600, Stop bits: 1, Parity: 1, Databits: 7
|
||||
I (3676) Example finished successfully!
|
||||
...
|
||||
I (256) USB-CDC: Installing USB Host
|
||||
I (256) USB-CDC: Installing CDC-ACM driver
|
||||
I (256) USB-CDC: Opening CDC ACM device...
|
||||
|
||||
...
|
||||
I (1174) USB-CDC: Data received
|
||||
I (1174) USB-CDC: 0x4ffbf640 43 44 43 20 74 65 73 74 20 73 74 72 69 6e 67 21 |CDC test string!|
|
||||
I (1274) USB-CDC: Testing control line state command
|
||||
I (1294) USB-CDC: - Control line state set to DTR=false, RTS=true
|
||||
I (1314) USB-CDC: Testing line coding commands
|
||||
I (1314) USB-CDC: - Line Coding Get: Rate: 115200, Stop bits: 0, Parity: 0, Databits: 8
|
||||
I (1314) USB-CDC: - Line Set: Rate: 115200, Stop bits: 0, Parity: 0, Databits: 8
|
||||
I (1314) USB-CDC: Example finished successfully! You can reconnect the device to run again.
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Device Not Detected
|
||||
|
||||
If the CDC-ACM device is not detected, check:
|
||||
|
||||
1. **USB connection:** Ensure the device is properly connected to the USB host port
|
||||
2. **Device compatibility:** Verify that the device implements the CDC-ACM class. Some USB-to-UART converters may use proprietary drivers
|
||||
3. **Power supply:** Ensure the USB host port provides adequate power for the connected device
|
||||
4. **Cable quality:** Use a quality USB cable that supports data transfer (not charge-only cables)
|
||||
|
||||
### No Data Received
|
||||
|
||||
If data is sent but not received:
|
||||
|
||||
1. **Check device connection:** Ensure the device is still connected and enumerated
|
||||
2. **Verify device functionality:** Test the device with another host to confirm it's working
|
||||
3. **Check line coding:** Some devices may require specific line coding settings before they start transmitting data
|
||||
4. **Increase log level:** Set the log level to debug via `idf.py menuconfig` to get more detailed information
|
||||
|
||||
### Line Coding Commands Not Supported
|
||||
|
||||
If you see warnings like:
|
||||
```
|
||||
W (xxx) USB-CDC: Line coding get not supported
|
||||
W (xxx) USB-CDC: Control line state set not supported
|
||||
```
|
||||
|
||||
This is normal for some CDC-ACM devices that don't support these optional commands. The example will continue to work for basic data transfer operations.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
usb_host_cdc_acm: "2.*"
|
||||
idf: ">=4.4"
|
||||
usb_host_cdc_acm: "^2.1.1"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
@@ -19,9 +18,6 @@
|
||||
#include "usb/cdc_acm_host.h"
|
||||
|
||||
#define EXAMPLE_USB_HOST_PRIORITY (20)
|
||||
#define EXAMPLE_USB_DEVICE_VID (0x303A)
|
||||
#define EXAMPLE_USB_DEVICE_PID (0x4001) // 0x303A:0x4001 (TinyUSB CDC device)
|
||||
#define EXAMPLE_USB_DEVICE_DUAL_PID (0x4002) // 0x303A:0x4002 (TinyUSB Dual CDC device)
|
||||
#define EXAMPLE_TX_STRING ("CDC test string!")
|
||||
#define EXAMPLE_TX_TIMEOUT_MS (1000)
|
||||
|
||||
@@ -113,7 +109,7 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
|
||||
// Create a task that will handle USB library events
|
||||
BaseType_t task_created = xTaskCreate(usb_lib_task, "usb_lib", 4096, xTaskGetCurrentTaskHandle(), EXAMPLE_USB_HOST_PRIORITY, NULL);
|
||||
BaseType_t task_created = xTaskCreate(usb_lib_task, "usb_lib", 4096, NULL, EXAMPLE_USB_HOST_PRIORITY, NULL);
|
||||
assert(task_created == pdTRUE);
|
||||
|
||||
ESP_LOGI(TAG, "Installing CDC-ACM driver");
|
||||
@@ -131,16 +127,14 @@ void app_main(void)
|
||||
while (true) {
|
||||
cdc_acm_dev_hdl_t cdc_dev = NULL;
|
||||
|
||||
// Open USB device from tusb_serial_device example example. Either single or dual port configuration.
|
||||
ESP_LOGI(TAG, "Opening CDC ACM device 0x%04X:0x%04X...", EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_PID);
|
||||
esp_err_t err = cdc_acm_host_open(EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_PID, 0, &dev_config, &cdc_dev);
|
||||
// Open any CDC-ACM device
|
||||
// This call always opens the first CDC-ACM device and first interface it finds
|
||||
ESP_LOGI(TAG, "Opening CDC ACM device...");
|
||||
esp_err_t err = cdc_acm_host_open(CDC_HOST_ANY_VID, CDC_HOST_ANY_PID, 0, &dev_config, &cdc_dev);
|
||||
if (ESP_OK != err) {
|
||||
ESP_LOGI(TAG, "Opening CDC ACM device 0x%04X:0x%04X...", EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_DUAL_PID);
|
||||
err = cdc_acm_host_open(EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_DUAL_PID, 0, &dev_config, &cdc_dev);
|
||||
if (ESP_OK != err) {
|
||||
ESP_LOGI(TAG, "Failed to open device");
|
||||
continue;
|
||||
}
|
||||
ESP_LOGI(TAG, "Failed to open device");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // To prevent infinite loop of failed attempts to open the device
|
||||
continue;
|
||||
}
|
||||
cdc_acm_host_desc_print(cdc_dev);
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
@@ -149,27 +143,47 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(cdc_acm_host_data_tx_blocking(cdc_dev, (const uint8_t *)EXAMPLE_TX_STRING, strlen(EXAMPLE_TX_STRING), EXAMPLE_TX_TIMEOUT_MS));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
// Test Line Coding commands: Get current line coding, change it 9600 7N1 and read again
|
||||
ESP_LOGI(TAG, "Setting up line coding");
|
||||
ESP_LOGI(TAG, "Testing control line state command");
|
||||
err = cdc_acm_host_set_control_line_state(cdc_dev, false, false);
|
||||
if (ESP_ERR_NOT_SUPPORTED == err) {
|
||||
ESP_LOGW(TAG, "\t- Control line state set not supported");
|
||||
} else if (ESP_OK != err) {
|
||||
ESP_LOGE(TAG, "\t- Failed to set control line state");
|
||||
} else {
|
||||
// In case you connected ESP board with USB-Serial-JTAG, this procedure will reset the board
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
cdc_acm_host_set_control_line_state(cdc_dev, false, true);
|
||||
ESP_LOGI(TAG, "\t- Control line state set to DTR=false, RTS=true");
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
cdc_acm_host_set_control_line_state(cdc_dev, false, false);
|
||||
}
|
||||
|
||||
// Test Line Coding commands: Get current line coding and change it to 115200 8N1
|
||||
ESP_LOGI(TAG, "Testing line coding commands");
|
||||
|
||||
cdc_acm_line_coding_t line_coding;
|
||||
ESP_ERROR_CHECK(cdc_acm_host_line_coding_get(cdc_dev, &line_coding));
|
||||
ESP_LOGI(TAG, "Line Get: Rate: %"PRIu32", Stop bits: %"PRIu8", Parity: %"PRIu8", Databits: %"PRIu8"",
|
||||
line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType, line_coding.bDataBits);
|
||||
err = cdc_acm_host_line_coding_get(cdc_dev, &line_coding);
|
||||
if (ESP_ERR_NOT_SUPPORTED == err) {
|
||||
ESP_LOGW(TAG, "\t- Line coding get not supported");
|
||||
} else if (ESP_OK != err) {
|
||||
ESP_LOGE(TAG, "\t- Failed to get line coding");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "\t- Line Coding Get: Rate: %"PRIu32", Stop bits: %"PRIu8", Parity: %"PRIu8", Databits: %"PRIu8"",
|
||||
line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType, line_coding.bDataBits);
|
||||
|
||||
line_coding.dwDTERate = 9600;
|
||||
line_coding.bDataBits = 7;
|
||||
line_coding.bParityType = 1;
|
||||
line_coding.bCharFormat = 1;
|
||||
ESP_ERROR_CHECK(cdc_acm_host_line_coding_set(cdc_dev, &line_coding));
|
||||
ESP_LOGI(TAG, "Line Set: Rate: %"PRIu32", Stop bits: %"PRIu8", Parity: %"PRIu8", Databits: %"PRIu8"",
|
||||
line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType, line_coding.bDataBits);
|
||||
|
||||
ESP_ERROR_CHECK(cdc_acm_host_line_coding_get(cdc_dev, &line_coding));
|
||||
ESP_LOGI(TAG, "Line Get: Rate: %"PRIu32", Stop bits: %"PRIu8", Parity: %"PRIu8", Databits: %"PRIu8"",
|
||||
line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType, line_coding.bDataBits);
|
||||
|
||||
ESP_ERROR_CHECK(cdc_acm_host_set_control_line_state(cdc_dev, true, false));
|
||||
// Set new line coding
|
||||
line_coding.dwDTERate = 115200;
|
||||
line_coding.bDataBits = 8;
|
||||
line_coding.bParityType = 0;
|
||||
line_coding.bCharFormat = 0;
|
||||
err = cdc_acm_host_line_coding_set(cdc_dev, &line_coding);
|
||||
if (ESP_OK != err) {
|
||||
ESP_LOGE(TAG, "\t- Failed to set line coding");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "\t- Line Set: Rate: %"PRIu32", Stop bits: %"PRIu8", Parity: %"PRIu8", Databits: %"PRIu8"",
|
||||
line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType, line_coding.bDataBits);
|
||||
}
|
||||
}
|
||||
|
||||
// We are done. Wait for device disconnection and start over
|
||||
ESP_LOGI(TAG, "Example finished successfully! You can reconnect the device to run again.");
|
||||
|
||||
Reference in New Issue
Block a user