最近项目测试发现串口收取时存在延迟、拥堵现象,多个 packet 接收的时间戳是一样的,但是发送的时候的确是每帧间隔固定时间。

测试了手头的 USB转串口模块,CH340的没有这个问题,但是 FT 系列都存在这个问题,包括 FT232/FT2232 等。现象是高频小包数据通信时,多个包拥堵到达,达到时间是一样的,但是发送时候是明显单包单包发送,就好像传输过来有缓冲区一样。

搜索了 “FTDI+Latency"后,发现如果使用的是 FTDI 厂商的 USB 转 UART 串口模块,默认是存在传输延迟的,参见 FTDI Linux USB latency,通过一下命令可以查看当前的默认延迟时间,默认一般为 16ms,这个对于高频率小包传输的影响是相当明显的:

1
cat /sys/bus/usb-serial/devices/ttyUSB0/latency_timer

对于目前的新版内科而言,命令 echo 1 > /sys/bus/usb-serial/devices/ttyUSB0/latency_timer 无法使用,提示 Input/Output Error,正确的方法是通过系统 API 来配置串口描述符 的 Low Latency 属性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <sys/ioctl.h>
#include <linux/serial.h>
...
// low latency
int serial = open(...);
...
struct serial_struct kernel_serial_settings;
ioctl(serial, TIOCGSERIAL, &kernel_serial_settings);
kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
ioctl(serial, TIOCSSERIAL, &kernel_serial_settings);

如此设置后,内核会通知 ftdi 驱动部分去降低 latency_timer 值,设置后可以通过 cat /sys/bus/usb-serial/devices/ttyUSB0/latency_timer 查看到该值已变更为 1.