3

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).

ilya1725
  • 4,496
  • 7
  • 43
  • 68
  • 2
    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 Mar 03 '17 at 23:33
  • 1
    @SamProtsenko I've tried complete non-blocking read instead of `select()` - didn't make much difference in latency. – ilya1725 Mar 04 '17 at 02:04
  • 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 Mar 04 '17 at 12:13
  • In absolute terms you're already doing better than this solution: http://stackoverflow.com/questions/4667141/high-delay-in-rs232-communication-on-a-pxa270 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 Mar 04 '17 at 21:34
  • 350 µs is too short for the [VTIME timeout](https://linux.die.net/man/3/termios). Anyway, what baud rate are you using? Does changing it affect the latency? – CL. Mar 05 '17 at 13:11
  • @CL My baud rate is 1152000. I've tried setting VTIME to 0, but it didn't make any difference. Since I'm using `select()` to see if data is available, it is irrelevant. – ilya1725 Mar 06 '17 at 06:55
  • 1152000 or 115200? At 115200 baud, 350 µs corresponds to 4 bytes. Does changing the baud rate afffect the latency? And how exactly are you measuring the latency? – CL. Mar 06 '17 at 10:21
  • @CL sorry, the baud rate is 921600. The oscilloscope plot shows how I measure the latency. I have a DIO driver with a pin set to high once `read()` call returns. – ilya1725 Mar 06 '17 at 18:38
  • @sawdust We operate in raw mode. This serial port is used to transfer data between machines. – ilya1725 Mar 08 '17 at 00:38
  • *"This serial port is used to transfer data between machines"* -- That was not even asked, nor is it salient information. What about DMA? Apparently you're oblivious to the ramifications of using DMA with a UART. DMA is straightforward with a block device, but with a char device such as a UART, a timer and/or polling is often required to control DMA in order to manage latency for reads by userspace. FYI this is totally separate from the VTIME timer of *termios*. BTW is your kernel even configured for preemption? – sawdust Mar 08 '17 at 04:45
  • @sawdust It is a stock 4.8 kernel with standard driver. How to find out if it is setup for preemption? And how to know if DMA is setup? – ilya1725 Mar 08 '17 at 06:51
  • @sawdust You can point me to the location in the kernel source as the starting location. – ilya1725 Mar 08 '17 at 06:58
  • 1
    *"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 https://www.kernel.org/ and viewable at http://lxr.free-electrons.com/source/?v=4.8. – sawdust Mar 08 '17 at 20:25

1 Answers1

1

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.

ilya1725
  • 4,496
  • 7
  • 43
  • 68