You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64架构(Radxa Rock)USB串口read调用阻塞问题求助

解决Linux ARM64串口read()阻塞问题的排查方案

核心排查方向

既然Linux终端能正常完成串口读写,说明硬件、串口本身无问题,问题出在你的程序对串口的配置细节或调用逻辑上,重点检查以下几点:

1. 串口阻塞模式与超时配置

默认情况下Linux串口为阻塞模式,read()会一直等待数据到来。终端程序通常默认带超时或非阻塞机制,而你的代码可能未配置。两种解决方式:

  • 设置非阻塞模式:
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  • 配置超时(通过termios的VTIME和VMIN):
struct termios tty;
tcgetattr(fd, &tty);
tty.c_cc[VMIN] = 0;    // 最小读取字节数设为0,不强制等待数据
tty.c_cc[VTIME] = 5;   // 超时时间0.5秒(单位0.1秒)
tcsetattr(fd, TCSANOW, &tty);

注意:VMIN>0时,VTIME是等待第一个字节后的超时;VMIN=0时,VTIME是整体读取超时。

2. 完整串口属性匹配验证

用stty -F /dev/ttyUSB0 -a在终端查看串口的完整配置,逐行对比代码中termios的设置,重点核对:

  • 奇偶校验、停止位、数据位是否完全一致
  • 是否关闭了ICANON规范模式(终端可能用规范模式,而你的程序如果用原始模式需手动关闭):
tty.c_lflag &= ~ICANON;
  • 是否禁用硬件流控制CRTSCTS(终端未启用的话,程序必须同步关闭):
tty.c_cflag &= ~CRTSCTS;

3. 串口文件描述符打开参数确认

确保打开串口时使用正确的标志位:

int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
    perror("Failed to open serial port");
    return -1;
}

O_NOCTTY避免串口成为进程控制终端,O_NDELAY让open不等待DCD信号,后续可通过fcntl调整阻塞模式。

4. 缓冲区清空操作

打开串口后,清空输入输出缓冲区,避免残留数据或未初始化的握手信号影响:

tcflush(fd, TCIOFLUSH);

5. 系统调用级别的调试跟踪

当程序卡在read()时,在Linux终端用以下命令跟踪进程行为:

  1. 用ps aux | grep your_program_name找到进程ID
  2. 执行strace -p <pid>查看系统调用细节,确认read()是真的在等待数据,还是存在隐藏配置错误

验证步骤

  1. 完全复制终端stty输出的参数到代码的termios配置中
  2. 启用超时或非阻塞模式,测试read()是否还会无限阻塞
  3. 用strace跟踪进程,确认read()的实际状态

内容的提问来源于stack exchange,提问作者Siguard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:28:23