2011-01-12 89 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);