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.
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.
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.
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.
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.
Therefore the problem must be in the C++ app or in a driver/OS setting of the RS232 interface.
The following control flags are used for the RS232 communication in the C++ application according to the Serial Programming Guide for POSIX Operating Systems:
// 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.
Does anyone have any ideas? Thank you very much in advance for your help.
uptime
(maybe your system is overloaded?) 3.Does your Linux have Fast Context Switch Extension (lwn.net/images/conf/rtlws11/papers/proc/p01.pdf)? PXA270 can have context switch delay of ~0.5ms without it. – atzzread()
from the serial port unblocks, and use oscilloscope to measure delay between the first bit of the incoming packet and the GPIO pin transition. – atzz