Kodak DC-265 overrunning linux serial driver?

brian@worldcontrol.com
Fri, 19 Nov 1999 11:00:26 -0800


brian & jim

are talking about FIFO overruns while downloading from the Kodak DC-265
Camera over a standard PC 16550A based serial port under Linux 2.2.13.

A discussion of which may be of interest to whomever is maintaining
the linux 2.2.13/4.2.7 serial driver.

> "brian" == brian <brian@worldcontrol.com> writes:

> brian> FIFO overruns. 8-(

On Fri, Nov 19, 1999 at 06:00:09AM +0000, Jim Thompson wrote:

> Suggestions?
>
> Jim

I've been looking at the linux 2.2.13 serial driver version 4.2.7.

I believe I'm running into the same problem with another device.
A Cardinal 56K modem, which has had similar problems for about
a year. It works up to 38400 but becomes unreliable at higher
speeds. What has worried me about that problem is that it works
fine at 115200 under FreeBSD. However, I've just lived with
the 38400.

The linux serial driver, so far as my perusual has found, works
like this:

rs_interrupt (fast interrupt)
rs_receive_chars
while data in FIFO {
stick chars in small local structure called a flip buf
}
schedule upper layer
} (exit fast interrupt)

at some point the upper layer tty handling code runs, and based
on some watermark (buffer full (not related to FIFO) condition) it
calls back to the serial driver function rs_throttle which will
clear RTS (the signal to the camera or modem to stop transmitting).

This call to rs_throttle from the tty handling is not actually of
all that much interest.

The bottem line when using a 16550A UART in a UNIX-like OS is that the
system must service the FIFO in the time it takes for 14 or so characters
to come in. Apparently, this is not happening.

[we've been programming the 16550A to interrupt on 1st character]

Basically from the time the irq happens on the reception of the 1st
character your linux system has 14 character times to unload the FIFO.

The system is either capable of doing this or it is not. If it is
not then overruns are what you get.

RTS is really not related to this condition. And in fact, so long as
your have enough memory and you can respond to the FIFOs needs you
don't even need RTS.

In other words, RTS isn't meant to help you respond to the FIFO unloading
in a timely manner, its meant to make sure you don't run out of memory.

On the other hand, even at 38400 I get lots of errors. Can the latency
in linux be that bad?

Some people may tell you 'I talk to my xxyyzz product at 115200 all the
time with no problems'. Well, an RS232D protocol analyzer may well show
that the characters are indeed coming out of their xxyyzz at 115200
baud, but that there are substantial gaps of time, or quiet on the
serial line, between characters. This intercharacter gap counts as more
time for the OS to unload the FIFO, since it really isn't filling as
fast as it would with characters coming in back to back.

If my analysis is right I can think of two fixes for this problem,
of which I consider only one of value.

The of value fix works like this:

The serial driver itself keeps a local circular buffer of say 4096
characters.

the rs_interrupt/rs_recieve_chars routing would then work like:

fast interrupt (the lower layer serial interrupt)
transfer characters in FIFO to local circular buffer
if (circular buffer > 80% full) {
clear RTS (stops camera from transmitting)
}
schedule upper layer
exit fast interrupt

upper layer transfers data in circular buffer to flip bufs
when (circular buffer < 20% full) {
set RTS (starts camera transmitting)
}
schedule upper layer tty handling code

I might try to code this change myself, but perhaps it would be
wise for the serial guru to take a look at my idea first.

On the other hand, the change might not help at all. I'm not familiar
with all the upper layer stuff, and if the interrupt service routine
simply isn't being called in a timely enough manner there isn't much
that can be done, except get the routine called in a timely manner.

Or perhaps some improvements have been made in the 2.3.x driver.

One thing I've never understood is that many of these problems come
about due the the old unix tty line discipline. Why not make a raw mode
serial driver that bypasses all this?

Another fix is implemented in some UARTS (16550A like chips).

You simply, in hardware, tie the UART hardware level FIFO full
indication to the RTS line. I.E. the UART itself when it
generates the IRQ due to 14 chars in FIFO drives the RTS line
low until someone reads the data out of the FIFO.

This would be a one wire change in the 16550A. On the other hand,
some one would undoubtably claim we need extra registers to maintain
compatible with the old RS-232C definition of RTS, which no one uses,
and for the most part never used.

-- 
Brian Litzinger <brian@litzinger.com>

Copyright (c) 1999 By Brian Litzinger, All Rights Reserved

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/