Linux虚拟串口0x03,这字节为何如此特殊?

摘要:首先要啰嗦一段话,介绍一下项目背景,基于Linux异核架构平台实现高精度的电机控制。虚拟串口成为Linux和M4的一个很好的“沟通桥梁”,首先编写好驱动生成设备,然后就是像读写普通串口一样对M4发送指令、接收指令。我把电机实际脉冲数int类
首先要啰嗦一段话,介绍一下项目背景,基于Linux异核架构平台实现高精度的电机控制。虚拟串口成为Linux和M4的一个很好的“沟通桥梁”,首先编写好驱动生成设备,然后就是像读写普通串口一样对M4发送指令、接收指令。我把电机实际脉冲数int类型拆分成了4个char,类似于(以下为示例代码不可运行,大端模式) int value; uint8_t buf[4]; // 大端序拆分 buf[0] = (value >> 24) & 0xFF; buf[1] = (value >> 16) & 0xFF; buf[2] = (value >> 8) & 0xFF; buf[3] = value & 0xFF;   然后有趣的事情开始了,开始时简单测试收发一切正常,然后机器开始自主运行,每当机器运行超过20W个脉冲之后就会莫名奇妙的停止,通过打印日志发现M4会发送一些不符合通信协议的数据过来,导致Linux发现接收的数据不对一直在重复请求数据重发,可是M4那边发送的数据是写的固定长度。这就有点莫名奇妙。经过不断测试之后,发现每当Linux发送的指定脉冲数协议中出现“0003”这个特殊字符时候,机器必定故障。更加巧合的是20W的16进制是“30D40”,于是0x03这个罪魁祸首浮出水面。   在串口默认模式下,Linux 会启用的规范模式将 0x03 当作中断字符,一旦遇到这个字符便会舍弃0x03之前的内容,导致出现数据丢失。至于解决方案就非常简单了,在Linux打开串口之后把它设置成原始模式即可。(以下为示例代码不可运行) bool RPMsg::Create() { /*already opened*/ if(m_fd >= 0) return true; /*open virtual serial port*/ m_fd = open(VSP, O_RDWR | O_NOCTTY); if (m_fd < 0) { printf("open VSP failed!\n"); return false; } /*non-blocking*/ int flags = fcntl(m_fd, F_GETFL, 0); if (flags == -1 || fcntl(m_fd, F_SETFL, flags | O_NONBLOCK) == -1) { close(m_fd); m_fd = -1; return false; } //raw mode struct termios tty; if (tcgetattr(m_fd, &tty) != 0) { close(m_fd); return false; } cfmakeraw(&tty); tty.c_iflag &= ~(IXON | IXOFF | IXANY); cfsetispeed(&tty, B115200); cfsetospeed(&tty, B115200); if (tcsetattr(m_fd, TCSANOW, &tty) != 0) { close(m_fd); return false; } this->start(); return true; }