2011-01-12 44 views
7

我遇到长延迟 - 在对某PXA270 RISC PC/104一个RS232通信(为1.5ms率为9.5ms)。我想尽量减少长时间的延迟,但我是一个嵌入式设备和C++的初学者,所以我想我错过了一些东西。高延迟RS232通讯上的PXA270

所提到的延迟是在当PXA板接收经由RS232从外部设备的数据包(115200波特),直到它发送一个ACK自定义数据包返回到外部设备的时间。 我用示波器测量了PXA板上的延迟,其中一个通道在Rx上,另一个在Tx上。

的PXA板运行的是Arcom Embedded Linux(AEL)。我知道,这不是一个实时操作系统,但我仍然认为,平均延迟4.5ms的方式是太高用于提取接收到的数据包,验证它是CRC16,构造一个ACK数据包(带有CRC)并发送它回到串口线。 我也故意让CPU承受沉重的负载(一些并行gzip操作),但延迟时间根本没有增加。 接收到的数据包的最大大小为30个字节。

C++应用程序(另一位前同事写的)正在处理数据包及其确认的接收。 一个线程正在发送,另一个正在接收数据包。

我认为在PXA板上的RTC有一个非常糟糕的分辨率和AEL不能对齐到内部RTC分辨率的时机。但RTC的频率为32.768 kHz。这个决议是足够的,仍然不能解释高延迟。顺便说一句,我认为操作系统使用内部PXA时钟(它也有足够的分辨率),而不是RTC的时间。

因此该问题必须在C++应用或RS232接口的驱动器/ OS的设置。

以下控制标志根据Serial Programming Guide for POSIX Operating Systems用于在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驱动程序处理具有更高优先级的请求,以最小化延迟。

有没有人有任何想法?非常感谢您的帮助。

+0

你有这些延迟为每个字符,还是你的输入来时,有一个\输入中的n还是缓冲区已满?串行驱动程序上有一些与终端相关的东西,可以根据您的时间进行推断。 – Rudi 2011-01-12 09:42:26

+0

延迟不会发生在每个字符上。发生时,当收到整个数据包(〜30字节)时,直到ACK数据包被发回。 – saxos 2011-01-12 10:16:31

回答

8

非常感谢您的意见。

我能够将延迟减少到〜0.4ms。 AEL手册中引用了命令setserial(8)。和宾果游戏,我发现low_latency标志出现在下面的描述:

最小化以更大的 CPU利用率的成本收到 串行设备的延迟。 (正常情况下有一个 平均5-10ms延迟 字符传递给行 discpline前,以尽量减少开销。)这 默认是关闭的,但一定 实时应用程序可能会发现这 有用。

然后我执行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);