refactor(serial): add host serial framework
Signed-off-by: sakumisu <1203593632@qq.com>
This commit is contained in:
@@ -154,14 +154,115 @@ lsusb
|
||||
|
||||
int lsusb(int argc, char **argv);
|
||||
|
||||
CDC ACM
|
||||
SERIAL
|
||||
-----------------
|
||||
|
||||
usbh_serial_open
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_serial_open`` 根据路径打开一个串口设备。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct usbh_serial *usbh_serial_open(const char *devname, uint32_t open_flags);
|
||||
|
||||
- **devname** 串口路径
|
||||
- **open_flags** 打开标志,参考 `USBH_SERIAL_OFLAG_*` 定义
|
||||
- **return** serial 结构体句柄
|
||||
|
||||
usbh_serial_close
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_serial_close`` 关闭串口设备。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbh_serial_close(struct usbh_serial *serial);
|
||||
|
||||
- **serial** serial 结构体句柄
|
||||
|
||||
usbh_serial_control
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_serial_control`` 对串口进行配置。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_serial_control(struct usbh_serial *serial, int cmd, void *arg);
|
||||
|
||||
- **serial** serial 结构体句柄
|
||||
- **cmd** 控制命令,参考 `USBH_SERIAL_CMD_*` 定义
|
||||
- **arg** 控制参数指针
|
||||
- **return** 0 表示正常其他表示错误
|
||||
|
||||
usbh_serial_write
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_serial_write`` 向串口写数据。 **串口设备如果是 USB2TTL 类型,必须按照波特率发送,否则会丢包**
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_serial_write(struct usbh_serial *serial, const void *buffer, uint32_t buflen);
|
||||
|
||||
- **serial** serial 结构体句柄
|
||||
- **buffer** 数据缓冲区指针
|
||||
- **buflen** 要写入的数据长度,如果是 USB2TTL 设备,一次最高 wMaxPacketSize
|
||||
- **return** 实际写入的数据长度或者错误码
|
||||
|
||||
.. note:: 有无设置波特率都可以使用该 API,当未设置波特率时,长度无限制,如果设置了波特率则为 wMaxPacketSize。
|
||||
|
||||
usbh_serial_read
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_serial_read`` 从串口读数据。 **如果没有设置波特率,不允许使用该 API**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_serial_read(struct usbh_serial *serial, void *buffer, uint32_t buflen);
|
||||
|
||||
- **serial** serial 结构体句柄
|
||||
- **buffer** 数据缓冲区指针
|
||||
- **buflen** 要读取的最大数据长度
|
||||
- **return** 实际读取的数据长度或者错误码
|
||||
|
||||
usbh_serial_cdc_write_async
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_serial_cdc_write_async`` 异步从串口读数据。 **如果设置了波特率,不允许使用该 API**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_serial_cdc_write_async(struct usbh_serial *serial, uint8_t *buffer, uint32_t buflen, usbh_complete_callback_t complete, void *arg);
|
||||
|
||||
- **serial** serial 结构体句柄
|
||||
- **buffer** 数据缓冲区指针
|
||||
- **buflen** 要发送的数据长度
|
||||
- **complete** 读数据完成回调函数
|
||||
- **arg** 回调函数参数
|
||||
- **return** 0 表示正常其他表示错误
|
||||
|
||||
usbh_serial_cdc_read_async
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_serial_cdc_read_async`` 异步从串口读数据。 **如果设置了波特率,不允许使用该 API**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_serial_cdc_read_async(struct usbh_serial *serial, uint8_t *buffer, uint32_t buflen, usbh_complete_callback_t complete, void *arg);
|
||||
|
||||
- **serial** serial 结构体句柄
|
||||
- **buffer** 数据缓冲区指针
|
||||
- **buflen** 要读取的最大数据长度,一次最高 16K。并且需要是 wMaxPacketSize 的整数倍
|
||||
- **complete** 读数据完成回调函数
|
||||
- **arg** 回调函数参数
|
||||
- **return** 0 表示正常其他表示错误
|
||||
|
||||
|
||||
HID
|
||||
-----------------
|
||||
|
||||
MSC
|
||||
-----------------
|
||||
|
||||
RNDIS
|
||||
NETWORK
|
||||
-----------------
|
||||
@@ -1,4 +1,96 @@
|
||||
usbh_serial
|
||||
===============
|
||||
|
||||
当前仅支持 rt-thread device 框架,包括 cdc acm, ftdi, cp210x, ch34x, pl2303, 具体使用方式参考 rt-thread device api 即可。
|
||||
Serial 框架当前支持 cdc acm, ftdi, cp210x, ch34x, pl2303,gsm 驱动。当前支持两种使用方式,
|
||||
一种是使用源生 CherryUSB usbhost serial API 进行操作,另一种是基于平台封装的 API 操作,比如 rt-thread device API。,nuttx posix API。
|
||||
|
||||
下面演示的是使用 CherryUSB usbhost serial API 进行串口回环测试,并且使用阻塞发送,异步读取的方式:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
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) {
|
||||
/* for common, we use timeout with 0xffffffff, this is just a test */
|
||||
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;
|
||||
usb_osal_msleep(10); // 11.52 Byte/ms at 115200bps --> 64Byte/5.5ms
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
USB_LOG_RAW("serial loopback test success\r\n");
|
||||
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);
|
||||
|
||||
|
||||
用户需要考虑以下三种场景:
|
||||
|
||||
- USB2TTL 设备 + 启用了波特率,这种情况下需要使用 `usbh_serial_write` 和 `usbh_serial_read` 进行收发数据, **并且需要根据波特率控制发送频率,防止对端丢包**;
|
||||
|
||||
- 纯 USB 设备 + 未启动波特率,这种情况下可以使用 `usbh_serial_cdc_write_async` 和 `usbh_serial_cdc_read_async` 进行异步收发数据,阻塞则用 `usbh_serial_write` 并且不需要控制发送频率。不可以使用 `usbh_serial_read`。
|
||||
|
||||
- 纯 USB 设备 + 启动波特率,同 1,但是速率打折扣。不可以使用 `usbh_serial_cdc_write_async` 和 `usbh_serial_cdc_read_async`。如果是 GSM 设备需要使用第一种。
|
||||
Reference in New Issue
Block a user