From: Jim Graham (jim@n5ial.mythical.com)
Date: 06/30/93


From: jim@n5ial.mythical.com (Jim Graham)
Subject: Re: 16550A FIFO IRQ setting question and ideas
Date: Thu, 1 Jul 1993 02:59:19 GMT

Oh, good....a fun one! I love datacomm issues (I suppose that's why I made
a career of it...that, or it's just one of those strange, unexplainable
things <grin>).

In article <1993Jun30.062729.5571@unlv.edu> ftlofaro@unlv.edu (Frank Lofaro)
writes:

>When doing a trace on a kermit process under Linux, data often came
>in in 8 byte chunks. I figured this might be related to the set-up of
>the FIFO's on the UART, i.e. how many bytes must be received before an
>IRQ is triggered. I looked through serial.c and serial.h and noticed
>that there is a FIFO control register which can set the FIFO trigger
>to either 1, 4, 8, or 14 bytes.

This has to do with the way the 16550 operates. Basically, it can be set
to wait until either a certain number of characters are in the FIFO, or a
certain amount of time has elapsed before issuing an interrupt. The idea
here is that the software will then receive *ALL* of the characters that
are waiting in one interrupt cycle, thus reducing the amount of overhead
used in context switching.

The adjustment is used for fine-tuning, but setting the trigger at 14 bytes
is potentially dangerous. If you're doing high-speed I/O, and your system
is also very busy, the CPU might not get around to processing the serial
port interrupt for a while. During this time, the FIFO could overflow if
you haven't left it any breathing room. I'd suggest setting it back to
8 bytes.

Here's a better description of what's going on, from National Semiconductor
(hang on a second while I pull up one of my prepared response files....I'm
editing this rather substantially to include only those bits that are more
or less related to the topic at hand---if you want the rest of the details,
I strongly recommend that you get a copy of AN-491 from NS---it's very good
reading, and is written such that it is very, very easy to understand, even
for the novice):

The following is from National Semiconductor's Application Note 491
(AN-491, ``The 16550A: UART Design and Application Considerations'').

============================ CUT HERE ============================
1.0 Design Considerations and Operation of the New UART Features

In order to optimize CPU/UART data transactions, the UART design takes
into consideration the following constraints:

1. The CPU is usually much faster than the UART at transferring data.
   [....]

2. There is a finite amount of wasted CPU time due to software overhead
   when stopping its current task to service the UART (context switching
   overhead).

3. The CPU may be required to complete a certain portion of its current
   task in a multitasking environment before servicing the UART. This
   delay is the CPU latency time associated with servicing the interrupt.
   The amount of time that the receiver can accept continuous data after
   it requests service from the CPU constrains CPU latency time.

[....]

The NS16550A receiver optimizes the CPU/UART data transaction via the
following features:

1. The depth of the Receiver (Rx) FIFO ensures that as many as 16
   characters will be ready to transfer when the CPU services the Rx
   interrupt. Therefore, the CPU transfer rate is effectively buffered
   from the serial data rate.

2. The program can select the number of bytes required in the Rx FIFO
   (1, 4, 8, or 14) before the UART issues an interrupt. This allows
   the software to modify the interrupt trigger levels depending on its
   current task or loading. It also ensures that the CPU doesn't
   continually waste time switching context for only a few characters.

3. The Rx FIFO will hold 16 bytes regardless of which trigger level the
   CPU selects. This makes allowances for a variety of CPU latency
   times, as the FIFO continues to fill after the interrupt is issued.

[....]

SYSTEM OPERATION: THE NS16550A VS THE NS16450

[....]

The greatest advantages of the NS16550A over the NS16450 are seen when
considering the CPU/UART interface.

[....]

The actual software required to transfer the data between the CPU and
the UART is a small percentage of that required to support this
transfer. However, each time a transfer occurs in the NS16450, this
support software (overhead) must also be executed. With the NS16550A
each time the UART needs service the CPU can theoretically transfer 16
bytes while only running through its overhead once. Tests have shown
that this will increase the performance by a factor of 5 at the system
level over the NS16450.

Another time savings for the CPU is a new feature of the UART interrupt
structure. Unlike most other UARTs with Rx FIFOs, the NS16550A will
issue an interrupt when there are characters below the interrupt trigger
level after a preset time delay. This saves the extra time spent by the
CPU to check for bytes that are at the end of a block, but won't reach
the interrupt level.

============================ CUT HERE ============================

>It was set to 8, I changed the
>definition of the setup command to use a 14 byte trigger instead of
>an 8 byte trigger. [....] Was this a good thing to do?

It could turn out to be a bad thing, depending on your system's performance.
Basically, by waiting until 14 characters are in the FIFO, you leave your
system *VERY* little time to process the interrupt.

>What are the advantages/disadvantages of a high or low trigger rate? I
>believe high would favor higher throughput, and low would favor low
>delay.

See text quoted from AN-491. The intent here is to reduce the context
switching overhead required when the CPU has to stop what it's doing and
service the interrupt. This is handled by transferring more than one
character at a time. So, one could say that setting the trigger level to
14 would tend to result in higher throughput. But...as I've already
mentioned, it could also result in not giving your system enough time to
process the interrupt before the FIFO is overrun. On the other hand,
setting the trigger level too low results in additional context switching
overhead, as more interrupts are generated. You have to find a happy
compromise, and without doing extensive testing, I tend to believe that
8 characters is a good compromise (I don't seem to be alone, as this seems
to be a pretty common default).

>If less bytes than the trigger come in, when is the FIFO
>drained? Thanks for any info you can give.

From the NS16550AF specs sheet, section 8.11:

 --------------------------- CUT HERE ---------------------------

   When RCVR FIFO and receiver interrupts are enabled, RCVR FIFO timeout
   interrupts will occur as follows:

   A. A FIFO timeout interrupt will occur, if the following conditions
      exist:

         --- at least one character is in the FIFO
         --- the most recent serial character received was longer
             than 4 continuous character times ago (if 2 stop bits
             are programmed the second one is included in this time
             delay).
         --- the most recent CPU read of the FIFO was longer than
             4 continuous character times ago.

      The maximum time between a received character and a timeout interrupt
      will be 160 ms at 300 baud with a 12-bit receive character (i.e.,
      1 Start, 8 Data, 1 Paraty and 2 Stop Bits).

 --------------------------- CUT HERE ---------------------------

So as you can see, at the higher port speeds, the time delay added by
waiting for a timeout interrupt is really not very substantial. How your
system handles this may or may not be substantial. Btw, so far, I have
yet to see any problems with Linux's handling of the serial port (and of
the 16550). Granted, I'm only setting the serial port to 38.4 kb (I have
the large-footprint USR DS, which only goes up to 38.4 kb on the serial
port), but I even doing heavy multitasking, Linux cruises right along,
where I've seen some dog (umm, err, dos) binaries crash and burn even
when they had the whole machine to themselves (i.e., not running under
windoze, Desqview, etc.).

Anyways, that's enough for this post. :-) If anyone has any questions,
feel free to e-mail me. If you're looking for the text of AN-491, you
need to contact National Semiconductor (1-800-272-9959 in US)...I don't
have much of it typed up, and NS will send it to you for free.

   --jim

PS: If you call NS for AN-491, also get AN-493 and the 16550AF specs.
     Trust me. :-)