latency_timer值对usb转串口设备的卡顿、延时性能的影响


  • administrators

    对于usb转串口设备,它硬件上一般有一个叫做latency_timer的定时器,当这个值设为lt时,表示数据会在设备上至少暂存lt 毫秒后再发送,只有在设备缓存写满的情况下才会忽略这个值而立即发送。latency_timer的取值范围一般为1到255之间,一般由设备驱动设置默认值。
    ftdi芯片的串口设备,一般默认值会是16毫秒,这在高实时性的场景是无法忍受的,具体详情请阅读这篇帖子:https://projectgus.com/2011/10/notes-on-ftdi-latency-with-arduino/

    解决办法是:

    1.手动设置latency_timer的值
    # 先查看当前值
    cat /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
    
    #设置为最小值 1 ms 
    sudo chmod 0666 /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
    echo 1 > /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
    
    #重启串口程序,应该就有效果了
    
    2.使用ioctl API代码的办法设置
    #如果使用了boost asio库
    #include <sys/ioctl.h> 
    #include <linux/serial.h>
    boost::asio::basic_serial_port<boost::asio::serial_port_service>::native_type native = serial_port_.native(); // serial_port_ is the boost's serial port class.
    struct serial_struct serial;
    ioctl(native, TIOCGSERIAL, &serial);
    serial.flags |= ASYNC_LOW_LATENCY; // (0x2000)
    ioctl(native, TIOCSSERIAL, &serial);
    
    #不使用boost库,直接操纵设备的方式
    #include <sys/ioctl.h> 
    #include <linux/serial.h>
    // Open RS232 on COM1
    mPhysicalComPort = open(aPort, O_RDWR | O_NOCTTY | O_NDELAY);
    struct serial_struct serial;
    ioctl(mPhysicalComPort, TIOCGSERIAL, &serial); 
    serial.flags |= ASYNC_LOW_LATENCY; // (0x2000)
    ioctl(mPhysicalComPort, TIOCSSERIAL, &serial);