[comp.sys.nsc.32k] DUARTS etc

daver@wombat.bungi.COM (Dave Rand) (08/31/90)

[In the message entitled "Interrupt 15, RxRDY interrupts, and DUART device drivers.." on Aug 30, 20:01, John Connin writes:]
> 
> Is the ICU interrupt input /INT15 connected to anything other than the 
> pullup resistor pack RES13-1 ??

No, it isn't connected to anything else. IR15 should be used for software
interrupts, or for RTC interrupts.

> Also, could you generally comment on your design decision to provide
> RxRDY interrupts.  More specificly, is there any code available
> which illustrates the 'perfered / best' way of controlling the
> 2681 DUART's ??

Ok, here's the scoop on RXrdy... UNIX has the nasty habit of disabling
interrupts for extended periods of time, usually sitting at SPL5 or SPL6.
Most serial drivers just live with this (since they run at SPL6 or
below), and drop characters, unless you have nasty, expensive NS16550A's
with FIFO's in them. I'm here to tell you that you don't need to put
up with this anymore!

This problem exists only on receiving characters - you don't care (much)
if the output from a serial port stops for a few milliseconds. You care
a LOT when this happens on input, though! The Signetics 2681/2692 handles
this with two different mechanisms on the PC532.

The first technique is to offer a separate interrupt line for received
characters. In the PC532 design, there is one "interrupt" and one
"RXrdy/FFul" interrupt per DUART (two serial channels). In a properly
designed operating system (non-UNIX), the serial channel interrupts would
never be disable (except for short periods during queue updates). With
two different interrupts from each DUART, we have the ability to externally
prioritize the two interrupts. The transmit/modem interrupt should be set
at a low priority, and the RXrdy interrupt at the highest priority (above
the highest kernel interrupt priority). When a RXrdy interrupt occurs,
the data is saved into a ring buffer (sized appropriately, not less than
7 * 70 bytes per port: 512 bytes is a good number). At the end of the
interrupt service routine, a TIMEOUT count is posted to an internal
variable. This variable is maintained on a per-port basis, and is
decremented by a timer interrupt from the counter/timer in each
DUART (handy, huh?). The timer interrupts should occur at the low-priority
interrupt level, and at a fairly high rate (1-5 milliseconds).

When the TIMEOUT variable reaches zero, indicating that data has not
appeared for quite a few character times, the data in the ring buffer
is transferred to the high level character queues through the line
discipline (CLISTs). You can also pass data up if the ring buffer
gets above a high water mark by setting the TIMEOUT to zero in the
RX interrupt routine, although in practice this doesn't help much.

(What's that? Too many interrupts? Can't work? I hate questions from the
assembled masses... let me continue!)

You may feel that taking interrupts from 8 sources (8 serial channels) at
38.4 KBps is quite a processor burden, what with context switches and
all... it ain't so! First of all, we WIRE-OR the open collector RXrdy
interrupts from each pair of serial channels (DUART) - this normally
cuts the number of interrupts in half, with an expense of 'polling'
each channel when you get an interrupt (a good idea anyway). Second,
the 2681/2692 has a FIFO of its own. If you feel the processor is getting
too busy, you can switch modes on the DUART, and get an interrupt every
3 characters instead of every character. You can tell when the processor
is too loaded, since you will have more than one character available on
each interrupt - by detecting this and switching modes, the interrupt
burden will go down correspondingly. Third, this is a _very_ light-weight
process. The interrupt handler will save the registers, read each of the
DUART channels to see which port has data (or both, for that matter), read
the status (check for parity), and read the data. The data will be saved in
a ring buffer, the TIMEOUT value posted, restore registers and return.
We're talking a hundred instructions, tops.

The second way that the 2681/2692 DUART fixes overrun problems is with
HARDWARE FLOW CONTROL (what a concept). When the DUART FIFO is about
to overflow, it automatically deasserts the RTS line. Before transmitting
a character, it looks at the status of the CTS line to ensure it is
asserted. Even if the processor is so busy it just _can't_ get to the
DUART in time, the hardware will still activate the flow control
signals!

This is the right DUART to use in all projects. Don't use NS16550A's.
You can do it in software, with the right hardware help...

I do have a nasty, grotty, unrolled, horrible driver that does all
of these things. You need that when you are running 4 Trailblazers on
a 0.75 MIPS machine... I'll hack it into the MINIX drivers (George is
boggled at MINIX right now - he can't believe that he hardware is
working!) and post it.


-- 
Dave Rand
dlr@bungi.com			{sun|vsi1|pyramid|uunet}!daver!dlr

news@daver.bungi.com (08/31/90)

>[In the message entitled "Interrupt 15, RxRDY interrupts, and DUART device dri
vers.." on Aug 30, 20:01, John Connin writes:]
...
>> Also, could you generally comment on your design decision to provide
>> RxRDY interrupts.

>Ok, here's the scoop on RXrdy... UNIX has the nasty habit of disabling
>interrupts for extended periods of time, usually sitting at SPL5 or SPL6.
>Most serial drivers just live with this (since they run at SPL6 or
>below), and drop characters, unless you have nasty, expensive NS16550A's
>with FIFO's in them. I'm here to tell you that you don't need to put
>up with this anymore!
...					When a RXrdy interrupt occurs,
>the data is saved into a ring buffer (sized appropriately, not less than
>7 * 70 bytes per port: 512 bytes is a good number). At the end of the
>interrupt service routine, a TIMEOUT count is posted to an internal
>variable.

Looks like a pretty good scheme; but what's magic about 70 * 7 ( = 490 )
bytes for the buffer size?

PS.  I'm still looking for a Public Domain scanf().  Any hints on where
to find one?

Many Thanks:	

Jonathan Ryshpan		<...!uunet!hitachi!jon>

M/S 420				(415) 244-7369  	
Hitachi America Ltd.
2000 Sierra Pt. Pkwy.
Brisbane CA 94005-1819

dlr@daver.bungi.com (Dave Rand) (09/01/90)

[In the message entitled "Re: DUARTS etc" on Aug 31,  9:31, Jonathan Ryshpan writes:]
> Looks like a pretty good scheme; but what's magic about 70 * 7 ( = 490 )
> bytes for the buffer size?
> 

That's uucp g protocol, with a window of 7... Can you tell I have a
fixation on uucp? :-)


-- 
Dave Rand
{pyramid|mips|bct|vsi1}!daver!dlr	Internet: dlr@daver.bungi.com

greg@cheers.Bungi.COM (Greg Onufer) (09/03/90)

>> Looks like a pretty good scheme; but what's magic about 70 * 7 ( = 490 )
>> bytes for the buffer size?
>That's uucp g protocol, with a window of 7... Can you tell I have a
>fixation on uucp? :-)

For the worst-case scenario, might as well make that 72*7 since the
4.3BSD UUCP has a feature/bug of sending two nulls after every packet.

What if you're talking g-protocol with a 4k packet size? :-)

Cheers!greg