3
votes

Is there a way to improve latency on serial port data processing in Linux (4.8)? In particular, the time between actual data on the line and when select() and read read() functions on this port return.Scope trace of data on line and read complete (blue)

Right now, my measurement shows 350 microseconds. The process is run with SCHED_RR priority 90. Is there a way to shorten this time or I have to change the driver? I'm using a 16C550 compatible chip from PERICOM (PI7C9X7954).

1
Some system calls lead to context switch (from user mode to kernel mode and vice versa), which can take some amount of time. I heard that epoll() outperforms select(), you can try it. Anyway, it's hard to tell anything particular without knowing the whole picture. It would be great if you can profile further all related time points: interrupt in driver (data received), point where select() releases in kernel, and point where select() releases in user-space. Btw, check if your device issues an interrupt, otherwise it's polling in kernel, which can cause delays.Sam Protsenko
@SamProtsenko I've tried complete non-blocking read instead of select() - didn't make much difference in latency.ilya1725
Still you can't rule out the possibility of long context switch (even on async read() syscall). It's hard to predict its time without actual measurement. So you need to profile your TTY driver along with user space code, and see where is actual bottleneck happens. Only then you can decide how to solve that problem. Maybe driver needs to be fixed, or maybe your hardware is polling by driver (instead of interrupt), or maybe you need to write your time-critical code in kernel space instead.Sam Protsenko
In absolute terms you're already doing better than this solution: stackoverflow.com/questions/4667141/… I would not expect non-blocking read to make a difference, but there are other userspace configurations that could, e.g. canonical versus raw. There is a lot of buffer copying for serial terminal I/O, the first is from the UART RxD register to a (DMA?) buffer. Crucial issue is when does this data then get copied to the tty flip buffers, i.e. how does the DMA operation terminate?sawdust
"How to find out if it is setup for preemption?" -- The "Linux version..." line in the kernel boot log (dmesg or uname -a) will have the word "PREEMPT" in capital letters. "how to know if DMA is setup?" -- Usually the driver will output a line in the boot log. Otherwise it's architecture (e.g. Device Tree) or device driver specific. "You can point me to the location in the kernel source" -- "Stock" does not mean what you think it does. The mainline kernel is downloadable from kernel.org and viewable at lxr.free-electrons.com/source/?v=4.8.sawdust

1 Answers

1
votes

So in order to resolve this I had to write my own driver in the user space. It wasn't very difficult, just had figure out how to configure the chip properly. The chip is accessed using memory mapped IO. The memory offset could be read from /sys/dev/char/<major>:<minor>/iomem_base file.

enter image description here

Just need to make sure that the port is never opened. Otherwise the OS will try to read the same data.