PXA270上的RS232通信延迟很高

时间:2022-06-02 17:26:19

I'm experiencing a long delay (1.5ms - 9.5ms) in a RS232 communication on a PXA270 RISC PC/104. I want to minimize the long delay but I'm a beginner with embedded devices and C++ so I think I'm missing something.

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

The mentioned delay is at the time when the PXA board receives a packet from the external device via RS232 (115200 baud) until it sends an ACK custom packet back to the external device. I measured the delay on the PXA board with an oscilloscope, one channel at the Rx and the other on the Tx.

上述延迟是在PXA板通过RS232(115200波特)从外部设备接收数据包之前,直到它将ACK自定义数据包发送回外部设备。我用示波器测量了PXA板上的延迟,一个通道位于Rx,另一个通道位于Tx。

The PXA board is running an Arcom Embedded Linux (AEL). I know, it's not a real-time OS, but I still think, that an average delay of 4.5ms is way too high for extracting the received packet, verify it's CRC16, construct an ACK packet (with CRC) and send it back the serial line. I also deliberately put the CPU under heavy load (some parallel gzip operations) but the delay time didn't increase at all. The maximum size of a received packet is 30 bytes.

PXA板运行的是Arcom嵌入式Linux(AEL)。我知道,它不是一个实时操作系统,但我仍然认为,4.5ms的平均延迟对于提取接收的数据包来说太高了,验证它是CRC16,构造一个ACK数据包(带CRC)并将其发送回串行线。我还故意将CPU置于高负载(一些并行gzip操作)但延迟时间根本没有增加。接收数据包的最大大小为30个字节。

A C++ application (another former co-worker wrote it) is handling the reception of the packets and their acknowledgement. One thread is sending and the other is receiving the packets.

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

I thought that the RTC on the PXA board has a very bad resolution and the AEL can not align the timing to the internal RTC resolution. But the RTC has a frequency of 32.768 kHz. The resolution is sufficient, still don't explain the high delay. Btw, I think the OS is using the internal PXA clock (which has also a sufficient resolution) instead of the RTC for the timing.

我认为PXA板上的RTC分辨率非常差,AEL无法将时序与内部RTC分辨率对齐。但RTC的频率为32.768 kHz。分辨率足够,仍然不解释高延迟。顺便说一下,我认为操作系统正在使用内部PXA时钟(也具有足够的分辨率)而不是RTC用于时序。

Therefore the problem must be in the C++ app or in a driver/OS setting of the RS232 interface.

因此问题必须出在C ++应用程序或RS232接口的驱动程序/ OS设置中。

The following control flags are used for the RS232 communication in the C++ application according to the Serial Programming Guide for POSIX Operating Systems:

根据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);

I think I'm missing something very simple. I think, that if the process of the app is running under a higher priority, this will not solve the problem. There must be something, which instructs the RS232 driver to handle the requests with a higher priority to minimize the latency.

我想我错过了很简单的事情。我认为,如果应用程序的进程在更高的优先级下运行,这将无法解决问题。必须有一些东西,它指示RS232驱动程序以更高的优先级处理请求以最小化延迟。

Does anyone have any ideas? Thank you very much in advance for your help.

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

1 个解决方案

#1


8  

Thank you very much for your comments.

非常感谢您的评论。

I was able to reduce the delay to ~0.4ms. The command setserial(8) was referenced in the AEL manual. And bingo, I found the low_latency flag there with the following description:

我能够将延迟减少到~0.4ms。命令setserial(8)在AEL手册中引用。和宾果游戏,我在那里找到了low_latency标志,其中包含以下描述:

Minimize the receive latency of the serial device at the cost of greater CPU utilization. (Normally there is an average of 5-10ms latency before characters are handed off to the line discpline to minimize overhead.) This is off by default, but certain real-time applications may find this useful.

以更高的CPU利用率为代价,最大限度地减少串行设备的接收延迟。 (通常在将字符切换到行discpline之前平均有5-10ms的延迟以最小化开销。)默认情况下这是关闭的,但某些实时应用程序可能会发现这很有用。

I then executed setserial /dev/ttyS1 low_latency and the delay was reduced to ~0.4ms :-)

然后我执行setserial / dev / ttyS1 low_latency,延迟减少到~0.4ms :-)

But I wanted to implement this behaviour in the C++ app, without setting this flag globally with setserial (this command is by default not included in all distros).

但我想在C ++应用程序中实现此行为,而不使用setserial全局设置此标志(默认情况下,此命令不包含在所有发行版中)。

I've added the following code lines, which had the same effect as the low_latency flag from 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);

#1


8  

Thank you very much for your comments.

非常感谢您的评论。

I was able to reduce the delay to ~0.4ms. The command setserial(8) was referenced in the AEL manual. And bingo, I found the low_latency flag there with the following description:

我能够将延迟减少到~0.4ms。命令setserial(8)在AEL手册中引用。和宾果游戏,我在那里找到了low_latency标志,其中包含以下描述:

Minimize the receive latency of the serial device at the cost of greater CPU utilization. (Normally there is an average of 5-10ms latency before characters are handed off to the line discpline to minimize overhead.) This is off by default, but certain real-time applications may find this useful.

以更高的CPU利用率为代价,最大限度地减少串行设备的接收延迟。 (通常在将字符切换到行discpline之前平均有5-10ms的延迟以最小化开销。)默认情况下这是关闭的,但某些实时应用程序可能会发现这很有用。

I then executed setserial /dev/ttyS1 low_latency and the delay was reduced to ~0.4ms :-)

然后我执行setserial / dev / ttyS1 low_latency,延迟减少到~0.4ms :-)

But I wanted to implement this behaviour in the C++ app, without setting this flag globally with setserial (this command is by default not included in all distros).

但我想在C ++应用程序中实现此行为,而不使用setserial全局设置此标志(默认情况下,此命令不包含在所有发行版中)。

I've added the following code lines, which had the same effect as the low_latency flag from 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);