• Please review our updated Terms and Rules here

8250 serial port speeds on XT, AT

Twospruces

Veteran Member
Joined
Dec 9, 2009
Messages
779
Location
Canada
I have 2 machines displaying very different speed capabilities on RS-232.

1) Z-171, 80C88 4.7MHz, 8250 UART with 1.8432MHz crystal
--> works well at 9600baud, but receiver cannot keep up at 19200 baud
2) Sharp PC-6220, 80286 6/12MHz, unknown serial hardware
--> supports 115200 baud

obviously a part of this is processor and clock rate, but I am wondering, were all XT 8088 machines limited to 9600 baud? This seems really slow.

I feel like the Z-171 has some impairment relative to a normal XT. Since the Z-171 actually has a slower benchmark relative to XT, I guess there must be some interrupt consuming cycles (like the video subsystem) and that ultimately limits how fast the CPU can serve the 8250 UART.

Anyone have any thoughts on this? thanks.
 
The 8250 has no buffer, which limits performance on slow machines. You can achieve higher baud rates with the 16x50 which have FIFO buffers.
 
--> works well at 9600baud, but receiver cannot keep up at 19200 baud
That sounds like some form of 'flow control' (hardware or software) is not being used, e.g. when the receiving end needs to do something like write out an almost-full buffer to a file, it gets the transmitting end to pause transmission during that time.

obviously a part of this is processor and clock rate, but I am wondering, were all XT 8088 machines limited to 9600 baud?
No. Using my IBM 5150 (with old IBM serial card) to access serial drives, I can set operation to more than 9600 baud.
 
A tightly coded piece of software that does nothing but fetch/push bytes off the serial port hardware to and from memory should in theory be able to handle baud rates all the way up to 115200 without sweating too hard on an XT; that’s only around 12Kbytes a second and devices like XT-CF cards can do an order of magnitude faster than that on a 4.77mhz CPU. (It’s not quite an apples to apples comparison but it’s close enough; computers like Tandy 1000s that lack DMA likewise can keep up with their double-density disk controllers which run over twice as fast as serial ports.) Of course, in the real world if you’re having to format/scroll the display or access the disk things get dicier; even with hardware flow control XT class machines can have issues with interrupt latency during disk accesses bad enough to limit them to the 9600 baud-ish ballpark, so… what performance is reasonable to expect depends a lot on what you’re doing.

That said, I wouldn’t normally expect that much difference between an XT and a slow AT if they both have 8250 serial ports, are you positive that flow control is working on the Zenith? It’s also possible there’s some clock drift going on between the Zenith and whatever you’re interfacing with, some UARTs are less good than others about locking on to data streams if the clocks are off by more than a percent or two. (For instance, some early Apple IIcs had serial ports clocked about 3% off, which caused problems with faster modems.)
 
Last edited:
I've done 115200 on a 4.77MHz 8088 with an 8250. As @Eudimorphodon says, about all you have time to do is read a byte and stash it into memory. Also note that if you're displaying characters as you're reading them, the CRT handling, particularly for scrolling, will bollix things up. Note also, that the early 16550s had a bug that made it impossible to use the chip FIFO.
 
update:
I'm exploring why the Z171 can't transfer with Laplink any faster than 9600 baud.

I hooked up my Saleae Logic analyzer to the 8250 chip, and the reason is quite clear.

Laplink sends data with almost no delay between bytes, as it should.
The receiving computer must therefore react to the interrupt request within a byte-period of the receiver to avoid losing data.

The Z-171 has some IO Read/Write occuring during the serial processing, and that delays the reading of the buffer long enough to lose at least 1 byte. At 19200, one byte gets clobbered at a time. At 115600, I think 4 or 5 bytes get clobbered. This makes sense as the 'other process' takes a fixed amount of time.

In this experiment, Laplink is running using the C: drive which is an XTIDE compact flash card. Since this is an I/O device, I wonder if it this that is causing the problem?

So, lets run Laplink from the floppy. Nope same problem. So, it isn't file I/O that is causing the interference.

I'm thinking it must be video. I can't immediately think of a way to suppress video updates, to confirm that this is what is happening. I am seeing an interfering burst of I/O read write every 13.5 msec.

I don't think hardware flow control is in use.
 
Last edited:
update.
It is an NMI at the processor which is delaying the serial port interrupt from being served in time.
looks like the NMI is connected to the "keyboard processor" which is an 80C37.

when the system is idle, this NMI is not toggling at all. (Laplink is running, but no action being taken)
when I "copy" a file, the NMI starts firing.
If NMI occurs during a sequence of RX data, the buffer is not read in time.
 
… It’s my vague recollection that the Z-171 was one of those machines that was a spin-off of the Dataview Spark/Morrow Pivot? Wasn’t that machine not really quite according-to-Hoyle PC Compatible in a number of respects? Have you tried software *other* than Laplink? I wonder if laplink might be doing something that specifically triggers some keyboard related compatibility quirk, like trying to leverage some BIOS call to fake keypresses as part of the transfer routine, which on this oddball hardware triggers the phantom NMIs.
 
By this, may we assume that the Z-171 does not have an interrupt controller (e.g. 8259)? But it clearly does. So why would it be using NMI?
 
Last edited:
It does have an 8259.
What's a bit strange is that, coming off the 80C37 keyboard controller, there is a feed to IRQ1 and also to NMI.

I can't really understand why the keyboard controller would need a non maskable Interrupt as well as IRQ2.

Keystrokes fire both interrupts, at the DOS prompt for example. (I'm pretty sure, will have to confirm)

I'll read that bit on PCjr. thanks.
Also good suggestion to try some other software. I did try Procomm and I did observe the same byte corruption, at 19200. So, I think it is independent of the application.
 
Keystrokes at DOS prompt:
This is D I R keys
For each key, IRQ1 fires, then NMI fires, thjen IRQ1 fires again.


z171 mni irq1.png
 
Here is something more interesting - NMI fires when the screen is being updated.
Here is a trace of
D I R <enter> - 4 keystrokes followed by a bunch of screen updates.

z171 mni irq1 _2.png

Interesting .. implies that NMI, from the "keyboard controller" has a screen update component to it.

In the case of keystrokes at the DOS prompt - that is both a keystroke detection + a display.
 
We assume that everyone who programmed for the first IBM PCs and clones were competent, but it's possible that some software was simply unoptimized. I grabbed Laplink 2.14 and inspected it; it is definitely written in assembly, but -- and I could totally be wrong about this -- it seems like it only grabs 8 bytes at a time before doing some ACK and housekeeping:

Code:
seg002:28F5 sub_1C825       proc near               ; CODE XREF: sub_1C812+8p
seg002:28F5                 mov     bx, dx
seg002:28F7                 mov     cx, 8
seg002:28FA                 cld
seg002:28FB
seg002:28FB recByte:                                ; CODE XREF: sub_1C825+9j
seg002:28FB                 in      al, dx          ; COM: receiver buffer register.
seg002:28FB                                         ; 8 bits of character received.
seg002:28FC                 stosb
seg002:28FD                 inc     dx
seg002:28FE                 loop    recByte
seg002:2900                 mov     dx, bx
seg002:2902                 add     dx, 3
seg002:2905                 mov     al, 10000000b
seg002:2907                 out     dx, al          ; COM: line control register bits:
seg002:2907                                         ; 0-1: word length: 00=5, 01=6, 10=7, 11=8
seg002:2907                                         ; 2:   stop bits: 0=1,1=2
seg002:2907                                         ; 3-4: parity: x0=None, 01=Odd, 11=Even
seg002:2907                                         ; 5:   stuck parity
seg002:2907                                         ; 6:   enable break control. 1=start sending 0s (spaces)
seg002:2907                                         ; 7:   DLAB (Divisor Latch Access Bit)
seg002:2908                 mov     dx, bx
seg002:290A                 in      al, dx          ; COM: receiver buffer register.
seg002:290A                                         ; 8 bits of character received.
seg002:290B                 stosb
seg002:290C                 inc     dx
seg002:290D                 in      al, dx          ; COM: divisor latch high byte(when DLAB=1)
seg002:290D                                         ; or interrupt enable register bits:
seg002:290D                                         ; 0:1=an interrupt when rec'd data is available
seg002:290D                                         ; 1:1=interrupt when transmit buffer is empty
seg002:290D                                         ; 2:1=int on rec'r line status (error or break)
seg002:290D                                         ; 3:1=int on modem status (CTS,DSR,RI,RLSD)
seg002:290E                 stosb
seg002:290F                 xor     al, al
seg002:2911                 add     dx, 2
seg002:2914                 out     dx, al          ; COM: line control register bits:
seg002:2914                                         ; 0-1: word length: 00=5, 01=6, 10=7, 11=8
seg002:2914                                         ; 2:   stop bits: 0=1,1=2
seg002:2914                                         ; 3-4: parity: x0=None, 01=Odd, 11=Even
seg002:2914                                         ; 5:   stuck parity
seg002:2914                                         ; 6:   enable break control. 1=start sending 0s (spaces)
seg002:2914                                         ; 7:   DLAB (Divisor Latch Access Bit)
seg002:2915                 in      al, 21h         ; Interrupt controller, 8259A.
seg002:2917                 stosb
seg002:2918                 retn
seg002:2918 sub_1C825       endp

I've never programmed the 8250 directly, so I don't want to throw too much shade here, but I would have expected a larger window than 8 bytes (if that's what's going on).
 
I think I might try running DOS over serial terminal (CTTY COM1) to suppress display updates on the local machine, to see if NMI continues to get fired.

I am imagining a buffer circuit to sit between the 8250 and the bus to manage this
 
Perhaps the NMI screen update is generated when the character is echoed.

Try "ctty com1:" to route things to an external serial terminal. Shouldn't echo on the main display.
 
"I've never programmed the 8250 directly, so I don't want to throw too much shade here, but I would have expected a larger window than 8 bytes (if that's what's going on)."
The 8250 is a pretty simple-minded UART. Think 8251 in async mode with no baud-rate-generator. Or a 2651 or a Z80 DART. Waste of a 40 pin package, if you ask me. The 2651 can do both sync and async with a BRG in 28 pins.
 
Back
Top