/dev/ttyUSB 延迟 15 毫秒
/dev/ttyUSB latency of 15ms
在 115200 波特率下,一个字节的异步串行传输耗时 < 0.1 毫秒。 (10 位周期:START + 8 + STOP。)
以下 C 程序:
#define _POSIX_C_SOURCE 199309L /* needed for CLOCK_MONOTONIC */
#include <termios.h> /* tcattr */
#include <unistd.h>
#include <string.h> /* strerror */
#include <errno.h> /* errno */
#include <fcntl.h> /* O_NDELAY, O_RDWR, O_EXCL */
#include <stdio.h> /* printf */
#include <stdint.h>
#include <stdlib.h> /* exit */
#include <inttypes.h> /* PRIu64 */
#include <time.h> /* struct timespec */
int open_ttyusb(uint8_t n)
{
char path[] = "/dev/ttyUSBnnn"; /* long enough for all values of uint8_t */
sprintf(path, "/dev/ttyUSB%i", n);
int fd = open(path, O_NDELAY|O_RDWR|O_EXCL);
if (fd < 0) {
exit(-1);
}
struct termios t;
tcgetattr(fd, &t); /* save old one */
t.c_iflag = t.c_oflag = 0;
t.c_cflag = B115200;
t.c_cflag |= (CLOCAL | CREAD); /* always 8-bit and local (no modem controls) */
t.c_cflag |= CS8; /* 8 bit character size mask */
t.c_iflag = IGNBRK;
t.c_lflag = 0;
t.c_cc[VMIN] = 1;
t.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &t); /* do it all and flush input */
tcflush(fd, TCIFLUSH);
uint8_t rubbish[4096];
while (read(fd, rubbish, 4096) > 0); /* make sure that there is nothing left */
return fd;
}
uint64_t now(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
return spec.tv_nsec + spec.tv_sec * 1000000000;
}
int main(void) {
int fd0 = open_ttyusb(0);
int fd1 = open_ttyusb(1);
for (int i = 0; i < 10; ++i) { /* repeat the test 10 times */
uint64_t start = now();
char tx = 'A' + i; /* send chars 'A' through 'J' */
write(fd0, &tx, 1);
uint8_t rx;
while (read(fd1, &rx, 1) < 1); /* loop until read succeeds */
if (rx != 'A' + i) { /* check that we've read the right char */
exit(-2);
}
uint64_t elapsed = now() - start;
printf("time_taken: %"PRIu64".%"PRIu64"ms\n", elapsed / 1000000, elapsed % 1000000);
}
}
输出:
time_taken: 1.292915ms
time_taken: 15.881472ms
time_taken: 15.859872ms
time_taken: 15.926402ms
time_taken: 15.975379ms
time_taken: 15.851588ms
time_taken: 15.882685ms
time_taken: 15.944355ms
time_taken: 15.915532ms
time_taken: 15.925496ms
(第一个 time_taken 从 0-16 毫秒变化,每个 运行。)
我有两个 USB FTDI 适配器,通过 RX 和 TX 交叉连接在一起。
- 为什么字节从一个 ttyUSB 传输到另一个需要 15 毫秒?
- 为什么第一次传输通常要快得多?
- 能否更改代码以减少延迟?
运行:
$ echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
$ echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB1/latency_timer
之前,将输出更改为:
time_taken: 0.702836ms
time_taken: 0.959548ms
time_taken: 1.2687ms
time_taken: 0.973790ms
time_taken: 0.994789ms
time_taken: 0.971454ms
time_taken: 1.12738ms
time_taken: 1.9920ms
time_taken: 0.986125ms
time_taken: 0.947801ms
哪个更容易接受。
虽然我没有证据,但我猜测这会增加通过 USB 轮询 FTDI 设备的速率。 (USB 设备无法启动通信,必须对其进行轮询。)
同样,我猜测(最初的)更快的第一响应是由于程序在轮询 ttyUSB1 之前启动的。
P.S。将零回显到 latency_timer
中可以进一步改善:
time_taken: 0.174095ms
time_taken: 0.350353ms
time_taken: 0.188431ms
time_taken: 0.175983ms
time_taken: 0.184215ms
time_taken: 0.197525ms
time_taken: 0.229502ms
time_taken: 0.201619ms
time_taken: 0.158024ms
time_taken: 0.150763ms
波形为:
在 115200 波特率下,一个字节的异步串行传输耗时 < 0.1 毫秒。 (10 位周期:START + 8 + STOP。)
以下 C 程序:
#define _POSIX_C_SOURCE 199309L /* needed for CLOCK_MONOTONIC */
#include <termios.h> /* tcattr */
#include <unistd.h>
#include <string.h> /* strerror */
#include <errno.h> /* errno */
#include <fcntl.h> /* O_NDELAY, O_RDWR, O_EXCL */
#include <stdio.h> /* printf */
#include <stdint.h>
#include <stdlib.h> /* exit */
#include <inttypes.h> /* PRIu64 */
#include <time.h> /* struct timespec */
int open_ttyusb(uint8_t n)
{
char path[] = "/dev/ttyUSBnnn"; /* long enough for all values of uint8_t */
sprintf(path, "/dev/ttyUSB%i", n);
int fd = open(path, O_NDELAY|O_RDWR|O_EXCL);
if (fd < 0) {
exit(-1);
}
struct termios t;
tcgetattr(fd, &t); /* save old one */
t.c_iflag = t.c_oflag = 0;
t.c_cflag = B115200;
t.c_cflag |= (CLOCAL | CREAD); /* always 8-bit and local (no modem controls) */
t.c_cflag |= CS8; /* 8 bit character size mask */
t.c_iflag = IGNBRK;
t.c_lflag = 0;
t.c_cc[VMIN] = 1;
t.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &t); /* do it all and flush input */
tcflush(fd, TCIFLUSH);
uint8_t rubbish[4096];
while (read(fd, rubbish, 4096) > 0); /* make sure that there is nothing left */
return fd;
}
uint64_t now(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
return spec.tv_nsec + spec.tv_sec * 1000000000;
}
int main(void) {
int fd0 = open_ttyusb(0);
int fd1 = open_ttyusb(1);
for (int i = 0; i < 10; ++i) { /* repeat the test 10 times */
uint64_t start = now();
char tx = 'A' + i; /* send chars 'A' through 'J' */
write(fd0, &tx, 1);
uint8_t rx;
while (read(fd1, &rx, 1) < 1); /* loop until read succeeds */
if (rx != 'A' + i) { /* check that we've read the right char */
exit(-2);
}
uint64_t elapsed = now() - start;
printf("time_taken: %"PRIu64".%"PRIu64"ms\n", elapsed / 1000000, elapsed % 1000000);
}
}
输出:
time_taken: 1.292915ms
time_taken: 15.881472ms
time_taken: 15.859872ms
time_taken: 15.926402ms
time_taken: 15.975379ms
time_taken: 15.851588ms
time_taken: 15.882685ms
time_taken: 15.944355ms
time_taken: 15.915532ms
time_taken: 15.925496ms
(第一个 time_taken 从 0-16 毫秒变化,每个 运行。)
我有两个 USB FTDI 适配器,通过 RX 和 TX 交叉连接在一起。
- 为什么字节从一个 ttyUSB 传输到另一个需要 15 毫秒?
- 为什么第一次传输通常要快得多?
- 能否更改代码以减少延迟?
运行:
$ echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
$ echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB1/latency_timer
之前,将输出更改为:
time_taken: 0.702836ms
time_taken: 0.959548ms
time_taken: 1.2687ms
time_taken: 0.973790ms
time_taken: 0.994789ms
time_taken: 0.971454ms
time_taken: 1.12738ms
time_taken: 1.9920ms
time_taken: 0.986125ms
time_taken: 0.947801ms
哪个更容易接受。
虽然我没有证据,但我猜测这会增加通过 USB 轮询 FTDI 设备的速率。 (USB 设备无法启动通信,必须对其进行轮询。)
同样,我猜测(最初的)更快的第一响应是由于程序在轮询 ttyUSB1 之前启动的。
P.S。将零回显到 latency_timer
中可以进一步改善:
time_taken: 0.174095ms
time_taken: 0.350353ms
time_taken: 0.188431ms
time_taken: 0.175983ms
time_taken: 0.184215ms
time_taken: 0.197525ms
time_taken: 0.229502ms
time_taken: 0.201619ms
time_taken: 0.158024ms
time_taken: 0.150763ms
波形为: