cu可读取串口但自研C程序读取阻塞的问题排查与解决
解决方案(感谢评论者)
部分终端默认设置与原始无过滤的串口传输不兼容,添加以下代码即可解决问题,其中有些设置可能是多余的:
struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); options.c_iflag &= ~(IXOFF | IXANY | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); options.c_cflag &= ~(CRTSCTS | CLOCAL | CSIZE | PARENB | CSTOPB); options.c_cflag |= CREAD | CS8; options.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE | ECHONL | IEXTEN); options.c_oflag &= ~(OPOST); options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 0; tcsetattr(fd, TCSANOW, &options);
原始问题
我使用运行Ubuntu 20.04的Nvidia Jetson Orin Nano设备,需要通过TTL电平串口连接某设备,已使用合适的USB转串口线,且用户已加入串口设备访问组。
目前使用cu命令可成功访问串口,命令如下:
cu -f -s 115200 -l /dev/ttyUSB0
于是我尝试编写自己的C程序来访问同一设备:
#include <iostream> #include <fcntl.h> #include <termios.h> #include <unistd.h> #include <stdio.h> int main() { int r; int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); if (fd == -1) { perror("tty "); return 1; } // Get current serial port options struct termios options; r = tcgetattr(fd, &options); if (r < 0) { perror("tcgetattr "); return 1; } // Set baud rate to 115200 cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); // Disable flow control (CTS and RTS) options.c_cflag &= ~CRTSCTS; // Set new serial port options r = tcsetattr(fd, TCSANOW, &options); if (r < 0) { perror("tcsetattr "); return 1; } char buf; while (1) { r = read(fd, &buf, 1); if (r < 0) { perror("read "); return 1; } printf("%02x\n", 255 & buf); } close(fd); return 0; }
遗憾的是,该程序无法正常工作:打开串口、执行tcgetattr和tcsetattr均成功,但read操作始终阻塞无响应。
我通过strace分析cu的执行流程(以下为部分跟踪内容),仅发现其检查了锁文件(该文件不存在),未找到其他关键差异,请问我哪里出错了?
谢谢!
[Mostly what precedes this is things like dynamically linking shared object libraries, setting signal handlers, closing already-closed fd's, and trying to access various files that don't exist.] getpid() = 17612 openat(AT_FDCWD, "/var/lock/TMP00000044cc", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3 write(3, " 17612\n", 11) = 11 close(3) = 0 linkat(AT_FDCWD, "/var/lock/TMP00000044cc", AT_FDCWD, "/var/lock/LCK..ttyUSB0", 0) = 0 unlinkat(AT_FDCWD, "/var/lock/TMP00000044cc", 0) = 0 geteuid() = 1000 getuid() = 1000 getegid() = 1000 getgid() = 1000 setregid(1000, 1000) = 0 setreuid(1000, 1000) = 0 openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NONBLOCK) = 3 geteuid() = 1000 getuid() = 1000 getegid() = 1000 getgid() = 1000 setregid(1000, 1000) = 0 setreuid(1000, 1000) = 0 fcntl(3, F_GETFD) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 faccessat(AT_FDCWD, "/dev/ttyUSB0", R_OK|W_OK) = 0 fcntl(3, F_GETFL) = 0x20802 (flags O_RDWR|O_NONBLOCK|O_LARGEFILE) fcntl(3, F_SETFL, O_RDWR|O_LARGEFILE) = 0 ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCFLSH, TCIFLUSH) = 0 ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, SNDCTL_TMR_START or TCSETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TIOCSCTTY, 0) = -1 EPERM (Operation not permitted) ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, SNDCTL_TMR_START or TCSETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, SNDCTL_TMR_STOP or TCSETSW, {B115200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0 faccessat(AT_FDCWD, "/dev/ttyUSB0", R_OK|W_OK) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}) = 0 write(1, "\7Connected.\n", 12) = 12 ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 -opost -isig -icanon -echo ...}) = 0 ioctl(0, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0 pipe2([4, 5], 0) = 0 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xffffa25c8d00) = 17613 close(5) = 0 read(0, 0xffffe67adad6, 1) = ? ERESTARTSYS (To be restarted if SA_RESTART is set) --- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=17614, si_uid=1000} --- rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call) --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=17613, si_uid=1000, si_status=0, si_utime=0, si_stime=0} --- ioctl(0, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0 ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0 write(2, "cu: Got termination signal\n", 27) = 27 ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 -opost -isig -icanon -echo ...}) = 0 ioctl(0, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0 close(4) = 0
内容的提问来源于stack exchange,提问作者Timothy Miller
相关产品推荐
相关产品推荐

