Main Page | Report Page

 

  Linux Forum Index » Linux Development - Applications » low latency serial i/o

Author Message
Peter Münster
Posted: Fri Oct 28, 2005 2:35 pm
 
Hello,

I need to send a character (acknowledgement) after reception of a telegram
within no more than 2ms. Before beginning the real application, I wrote a
small test program, to measure the latency. Very strange: sometimes the
latency is about 3ms, sometimes about some µs only, but never other values,
than these 2.
For testing, I send about 3 times per second the telegram "abcdefghij" from
another system to my serial interface.

Perhaps, I need some more information about the fifos: are there tx and rx
fifos, where and how should I configure them?

Here is my test-program with some more detailed questions:

/* I tried 0, 1, 10 and 16, but it does not seem to change anything... */
#define FIFO_SIZE 1

/* This is needed, if not, we can get up to 10ms latency. */
#define TEST_LOW_LATENCY 1

/* If 1, than it seems, some transmissions get lost... */
#define TEST_OUTPUT_FLUSH 0

/* Perhaps only useful with heavy load... */
#define TEST_SCHED 1

#include <sched.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>

#define _POSIX_SOURCE 1
#define DEVICE "/dev/ttyS0"
#define FRAME_SIZE 10 // "abcdefghij"

int fd;

void serial_init()
{
struct termios options;
struct serial_struct serial;
if((fd = open(DEVICE, O_RDWR | O_NOCTTY)) < 0){
perror(DEVICE);
exit(-1);
}
ioctl(fd, TIOCGSERIAL, &serial);
#if TEST_LOW_LATENCY
serial.flags |= ASYNC_LOW_LATENCY;
#else
serial.flags &= ~ASYNC_LOW_LATENCY;
#endif
serial.xmit_fifo_size = FIFO_SIZE; // what is "xmit" ??
ioctl(fd, TIOCSSERIAL, &serial);

tcgetattr(fd, &options);
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
options.c_cflag &= ~(CSIZE | PARODD | CSTOPB | CRTSCTS);
options.c_cflag |= CLOCAL | CREAD | CS8 | PARENB;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_iflag |= INPCK | ISTRIP;
options.c_oflag &= ~OPOST;
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = FRAME_SIZE;
tcsetattr(fd, TCSANOW, &options);
}

int check_frame()
{
char buf[FRAME_SIZE + 1];
while(!read(fd, buf, FRAME_SIZE));
buf[FRAME_SIZE] = '\0';
puts(buf);
return buf[FRAME_SIZE - 1] == 'j';
}

void serial_ack()
{
write(fd, "a", 1);
#if TEST_OUTPUT_FLUSH
tcflush(fd, TCOFLUSH);
#endif
}

int main()
{
#if TEST_SCHED
struct sched_param sched;
sched_getparam(0, &sched);
sched.sched_priority = 50;
sched_setscheduler(0, SCHED_RR, &sched);
#endif
serial_init();
while(1)
if(check_frame())
serial_ack();
else
puts("Error");
return 0;
}

I would be glad about any hint!
Greetings, Peter

--
email: pmrb at free.fr
http://pmrb.free.fr/contact/
 
Jan Panteltje
Posted: Fri Oct 28, 2005 3:45 pm
 
On a sunny day (Fri, 28 Oct 2005 22:35:17 +0200) it happened
=?ISO-8859-15?Q?Peter_M=FCnster?= <look@signature.invalid> wrote in
<Pine.LNX.4.58.0510282155270.29642@gaston.free.fr>:

Quote:
Hello,

I need to send a character (acknowledgement) after reception of a telegram
within no more than 2ms. Before beginning the real application, I wrote a
small test program, to measure the latency. Very strange: sometimes the
latency is about 3ms, sometimes about some µs only, but never other values,
than these 2.
If a task switch happens it is 3ms else immediate.

Use external hardware (PIC microcontroller).
Or perhaps some real time Linux (have not tried that).
_________________________________________
Usenet Zone Free Binaries Usenet Server
More than 140,000 groups
Unlimited download
http://www.usenetzone.com to open account
 
Peter Münster
Posted: Sat Oct 29, 2005 3:34 am
 
On Fri, 28 Oct 2005, Floyd L. Davidson wrote:

Quote:
Your method of setting up "framing" of the data is guaranteed to
cause problems, soon or later. Instead of setting the number of
bytes that the serial port can provide to the frame size, build
your frame in a circular buffer, and fetch bytes from the serial
port in increments as small as 1 byte. You can still call
read(2) with a byte count that is higher, but if it gets out of
sync it won't hang waiting for bytes that will never be there.

Thanks for all your hints! I know, the program is full of mistakes, but it
has nothing to do with a real application, it's just for measuring the
delay on the scope.
I think, my main question is, how to configure the fifo in user mode,
without modifying the kernel. I only know the "Serial Programming Guide for
POSIX" but perhaps I need something more specific to Linux...

Greetings, Peter

--
email: pmrb at free.fr
http://pmrb.free.fr/contact/
 
 
Page 1 of 1    
All times are GMT - 5 Hours
The time now is Fri Apr 18, 2014 10:51 am