usbh_serial

Serial 框架当前支持 cdc acm, ftdi, cp210x, ch34x, pl2303,gsm 驱动。

../_images/usbh_serial.png

当前支持两种使用方式,一种是使用源生 CherryUSB usbhost serial API 进行操作,另一种是基于平台封装的 API 操作,比如 rt-thread device API,nuttx posix API。

下面演示的是使用 CherryUSB usbhost serial API 进行串口回环测试,并且使用阻塞发送,异步读取的方式:

struct usbh_serial *serial;

serial = usbh_serial_open("/dev/ttyACM0", USBH_SERIAL_O_RDWR | USBH_SERIAL_O_NONBLOCK);
if (serial == NULL) {
    serial = usbh_serial_open("/dev/ttyUSB0", USBH_SERIAL_O_RDWR | USBH_SERIAL_O_NONBLOCK);
    if (serial == NULL) {
        USB_LOG_RAW("no serial device found\r\n");
        goto delete;
    }
}

struct usbh_serial_termios termios;

memset(&termios, 0, sizeof(termios));
termios.baudrate = 115200;
termios.stopbits = 0;
termios.parity = 0;
termios.databits = 8;
termios.rtscts = false;
termios.rx_timeout = 0;
ret = usbh_serial_control(serial, USBH_SERIAL_CMD_SET_ATTR, &termios);
if (ret < 0) {
    USB_LOG_RAW("set serial attr error, ret:%d\r\n", ret);
    goto delete_with_close;
}

serial_tx_bytes = 0;
while (1) {
    ret = usbh_serial_write(serial, serial_tx_buffer, sizeof(serial_tx_buffer));
    if (ret < 0) {
        USB_LOG_RAW("serial write error, ret:%d\r\n", ret);
        goto delete_with_close;
    } else {
        serial_tx_bytes += ret;

        if (serial_tx_bytes == SERIAL_TEST_LEN) {
            USB_LOG_RAW("send over\r\n");
            break;
        }
    }
}

volatile uint32_t wait_timeout = 0;
serial_rx_bytes = 0;
while (1) {
    ret = usbh_serial_read(serial, &serial_rx_data[serial_rx_bytes], SERIAL_TEST_LEN - serial_rx_bytes);
    if (ret < 0) {
        USB_LOG_RAW("serial read error, ret:%d\r\n", ret);
        goto delete_with_close;
    } else {
        serial_rx_bytes += ret;

        if (serial_rx_bytes == SERIAL_TEST_LEN) {
            USB_LOG_RAW("receive over\r\n");
            for (uint32_t i = 0; i < SERIAL_TEST_LEN; i++) {
                if (serial_rx_data[i] != 0xa5) {
                    USB_LOG_RAW("serial loopback data error at index %d, data: 0x%02x\r\n", (unsigned int)i, serial_rx_data[i]);
                    goto delete_with_close;
                }
            }
            serial_test_success = true;
            break;
        }
    }
    wait_timeout++;

    if (wait_timeout > 500) { // 5s
        USB_LOG_RAW("serial read timeout\r\n");
        goto delete_with_close;
    }

    usb_osal_msleep(10);
}

usbh_serial_close(serial);

Note

需要注意,例程中使用的是比较简单的先发送后读取的方式,因此发送的总长度不可以超过 CONFIG_USBHOST_SERIAL_RX_SIZE,正常使用 TX/RX 请分开进行。

用户需要考虑以下三种场景:

  • USB2TTL 设备 + 启用了波特率,这种情况下需要使用 usbh_serial_writeusbh_serial_read 进行收发数据, 并且 read 操作需要及时,防止 ringbuf 数据溢出而丢包

  • 纯 USB 设备 + 未启动波特率,这种情况下可以使用 usbh_serial_cdc_write_asyncusbh_serial_cdc_read_async 进行异步收发数据。阻塞则可以用 usbh_serial_write ,不可以使用 usbh_serial_read

  • 纯 USB 设备 + 启动波特率,同 1,但是速率打折扣(因为多了一层 ringbuf)。此时也不可以使用 usbh_serial_cdc_write_asyncusbh_serial_cdc_read_async如果是 GSM 设备请使用第一种场景

[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
[I/usbh_core] New device found,idVendor:10c4,idProduct:ea60,bcdDevice:0100
[I/usbh_core] The device has 1 bNumConfigurations
[I/usbh_core] The device has 1 interfaces
[I/usbh_core] Enumeration success, start loading class driver
[I/usbh_core] Loading cp210x class driver on interface 0
[I/usbh_cp210x] chip partnum: 0x02
[I/usbh_cp210x] ulAmountInInQueue: 0, ulAmountInOutQueue: 0
[I/usbh_serial] Ep=81 Attr=02 Mps=64 Interval=00 Mult=00
[I/usbh_serial] Ep=01 Attr=02 Mps=64 Interval=00 Mult=00
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (cp210x)
start serial loopback test, len: 1024
send over
receive over
serial loopback test success
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (cp210x)
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
[I/usbh_hub] New high-speed device on Bus 0, Hub 1, Port 1 connected
[I/usbh_core] New device found,idVendor:0403,idProduct:6010,bcdDevice:0700
[I/usbh_core] The device has 1 bNumConfigurations
[I/usbh_core] The device has 2 interfaces
[I/usbh_core] Enumeration success, start loading class driver
[I/usbh_core] Loading ftdi class driver on interface 0
[I/usbh_ftdi] chip name: FT2232H
[I/usbh_serial] Ep=81 Attr=02 Mps=512 Interval=00 Mult=00
[I/usbh_serial] Ep=02 Attr=02 Mps=512 Interval=00 Mult=00
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (ftdi)
[I/usbh_core] Loading ftdi class driver on interface 1
[I/usbh_ftdi] chip name: FT2232H
[I/usbh_serial] Ep=83 Attr=02 Mps=512 Interval=00 Mult=00
[I/usbh_serial] Ep=04 Attr=02 Mps=512 Interval=00 Mult=00
[I/usbh_serial] Register Serial Class: /dev/ttyUSB1 (ftdi)
start serial loopback test, len: 1024
send over
receive over
serial loopback test success
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (ftdi)
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB1 (ftdi)
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
[I/usbh_core] New device found,idVendor:067b,idProduct:2303,bcdDevice:0300
[I/usbh_core] The device has 1 bNumConfigurations
[I/usbh_core] The device has 1 interfaces
[I/usbh_core] Enumeration success, start loading class driver
[I/usbh_core] Loading pl2303 class driver on interface 0
[I/usbh_pl2303] Ep=81 Attr=03 Mps=10 Interval=01 Mult=00
[I/usbh_pl2303] chip type: PL2303HX
[I/usbh_serial] Ep=02 Attr=02 Mps=64 Interval=00 Mult=00
[I/usbh_serial] Ep=83 Attr=02 Mps=64 Interval=00 Mult=00
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (pl2303)
start serial loopback test, len: 1024
send over
receive over
serial loopback test success
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (pl2303)
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
[W/usbh_hub] Failed to enable port 1
[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
[I/usbh_core] New device found,idVendor:1a86,idProduct:7523,bcdDevice:0264
[I/usbh_core] The device has 1 bNumConfigurations
[I/usbh_core] The device has 1 interfaces
[I/usbh_core] Enumeration success, start loading class driver
[I/usbh_core] Loading ch34x class driver on interface 0
[I/usbh_ch43x] Ep=81 Attr=03 Mps=8 Interval=01 Mult=00
[I/usbh_ch43x] chip version: 0x31
[I/usbh_serial] Ep=82 Attr=02 Mps=32 Interval=00 Mult=00
[I/usbh_serial] Ep=02 Attr=02 Mps=32 Interval=00 Mult=00
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (ch34x)
start serial loopback test, len: 1024
send over
receive over
serial loopback test success
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (ch34x)
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
[I/usbh_core] New device found,idVendor:42bf,idProduct:b210,bcdDevice:0217
[I/usbh_core] The device has 1 bNumConfigurations
[I/usbh_core] The device has 3 interfaces
[I/usbh_core] Enumeration success, start loading class driver
[E/usbh_core] Do not support Class:0xff, Subclass:0x01, Protocl:0x00 on interface 0
[I/usbh_core] Loading cdc_acm class driver on interface 1
[I/usbh_cdc_acm] Ep=85 Attr=03 Mps=64 Interval=00 Mult=00
[I/usbh_serial] Ep=04 Attr=02 Mps=64 Interval=00 Mult=00
[I/usbh_serial] Ep=83 Attr=02 Mps=64 Interval=00 Mult=00
[I/usbh_serial] Register Serial Class: /dev/ttyACM0 (cdc_acm)
[I/usbh_core] Loading cdc_data class driver on interface 2
start serial loopback test, len: 1024
send over
receive over
serial loopback test success
[I/usbh_serial] Unregister Serial Class: /dev/ttyACM0 (cdc_acm)
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected