PXA270 上的 RS232 通信延迟较高
- 2024-11-11 08:27:00
- admin 原创
- 21
问题描述:
我在 PXA270 RISC PC/104 上的 RS232 通信中遇到了较长的延迟(1.5 毫秒 - 9.5 毫秒)。我想尽量减少较长的延迟,但我是嵌入式设备和 C++ 的初学者,所以我认为我遗漏了一些东西。
上述延迟是指 PXA 板通过 RS232(115200 波特)从外部设备接收数据包到将自定义 ACK 数据包发送回外部设备的时间。我用示波器测量了 PXA 板上的延迟,一个通道位于 Rx,另一个通道位于 Tx。
PXA 板运行的是Arcom 嵌入式 Linux (AEL)。我知道这不是实时操作系统,但我仍然认为,平均 4.5ms 的延迟对于提取接收的数据包、验证其 CRC16、构造 ACK 数据包(带 CRC)并将其发送回串行线来说太高了。我还故意让 CPU 处于高负载状态(一些并行 gzip 操作),但延迟时间根本没有增加。接收数据包的最大大小为 30 字节。
一个 C++ 应用程序(另一位前同事编写)负责处理数据包的接收和确认。一个线程负责发送数据包,另一个线程负责接收数据包。
我认为 PXA 板上的 RTC 分辨率很差,AEL 无法将时序与内部 RTC 分辨率对齐。但 RTC 的频率为 32.768 kHz。分辨率足够,但仍然无法解释高延迟。顺便说一句,我认为操作系统使用内部 PXA 时钟(也具有足够的分辨率)而不是 RTC 进行计时。
因此问题一定出在 C++ 应用程序或 RS232 接口的驱动程序/操作系统设置中。
根据POSIX 操作系统的串行编程指南,以下控制标志用于 C++ 应用程序中的 RS232 通信:
// Open RS232 on COM1
mPhysicalComPort = open(aPort, O_RDWR | O_NOCTTY | O_NDELAY);
// Force read call to block if no data available
int f = fcntl(mPhysicalComPort, F_GETFL, 0);
f &= ~O_NONBLOCK;
fcntl(mPhysicalComPort, F_SETFL, f);
// Get the current options for the port...
tcgetattr(mPhysicalComPort, &options);
// ... and set them to the desired values
cfsetispeed(&options, baudRate);
cfsetospeed(&options, baudRate);
// no parity (8N1)
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
// disable hardware flow control
options.c_cflag &= ~CRTSCTS;
// raw input
options.c_lflag = 0;
// disable software flow control
options.c_iflag = 0;
// raw output
options.c_oflag = 0;
// Set byte times
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
// Set the new options for the port
tcsetattr(mPhysicalComPort, TCSAFLUSH, &options);
// Flush to put settings to work
tcflush(mPhysicalComPort, TCIOFLUSH);
我觉得我遗漏了一些非常简单的东西。我认为,如果应用程序的进程在更高的优先级下运行,这将无法解决问题。一定有一些东西可以指示 RS232 驱动程序以更高的优先级处理请求,以最大限度地减少延迟。
有人有什么想法吗?非常感谢您的帮助。
解决方案 1:
非常感谢您的评论。
我能够将延迟减少到约 0.4 毫秒。AEL手册中引用了命令setserial(8)low_latency
。然后,我在那里找到了带有以下描述的标志:
以更高的 CPU 利用率为代价,将串行设备的接收延迟降到最低。(通常,在将字符移交给线路学科之前,平均有 5-10ms 的延迟,以尽量减少开销。)默认情况下,此功能处于关闭状态,但某些实时应用程序可能会发现此功能很有用。
然后我执行了它setserial /dev/ttyS1 low_latency
,延迟减少到了~0.4ms :-)
但是我想在 C++ 应用程序中实现这种行为,而不使用 setserial 全局设置此标志(此命令默认不包含在所有发行版中)。
我添加了以下代码行,其效果与 setserial 中的 low_latency 标志相同:
#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);
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件