----- Original Message -----
From: "Michael B. Brutman" <mbbrutman-cctalk at brutman.com>
To: "CCTalk_list" <cctalk at classiccmp.org>
Sent: Tuesday, September 29, 2009 11:30 AM
Subject: PCjr NMI and 8253 Timer interactions
I recently wrote a ping utility for my DOS TCP/IP stack, and I wasn't
satisfied with the 55ms resolution of the BIOS timer tick. I used the
'delay' function in the Turbo C runtime which gives me a processor loop
that delays with 1ms granularity. I figured that I could call that and
poll for the ping reply, and the number of calls would be the ping latency
in ms.
Testing of delay in a controlled environment shows that at least on my
PCjr, it is off by 15%. My V20 processor might be part of the problem,
although I'm not going to fix it.
So I decided to dabble with the 8253 a bit. What a nightmare ..
First, some observations on the 8253:
- Mode 3 on the 8253 is not suitable for reading because of the way it
counts down twice before triggering an interrupt. If you just latch and
read the count you can't tell if you are on the first pass or the second
pass before the interrupt. That's not good for timing.
- Mode 2 counts down and generates an interrupt in a sane way, but
generates a different pulse to the 8259 interrupt controller so I'd rather
not use it. The BIOS initializes with Mode 3, and that is what I am
sticking with.
I decided to make timer 0 tick at a faster rate (64x faster), and in my
interrupt handler I call the original interrupt handler at the appropriate
rate to avoid speeding up the system clock. This works fine, even on the
PCjr. Except for one case ...
On the PCjr, if I touch the keyboard the machine screeches. And not its
normal polite 'Go away I'm busy beep' either. The keyboard on this
machine is wired to NMI instead of IRQ1, so it has higher priority than
timer 0. The NMI interrupt is used to read the keyboard serial data
stream and it uses timer 1 of the 8253 to record when the first bit is
received. Timer 1 isn't used elsewhere, so that is fine. If there is an
error in the serial data it sounds the system beeper, so timer 2 can get
altered at any time making timer 2 unusable.
Any keypress causes the screeching. First, I can't figure out why the NMI
handler is having a problem deserializing the keyboard even if timer 0 is
running fast. All interrupts are disabled, so this should be business as
usual. Yet any keypress causes it to go nuts. Any ideas? (As a side
effect the timings reported by ping start to look bad - the NMI is
definitely taking up precious time.)
Second, the machine becomes unstable. I don't care about getting bad
timings because of keypresses, but this is far worse ..
If I disable the NMI interrupt everything is perfect - but then you can't
hit Ctrl-Break to stop pinging. (Yes, I have Ctrl-Break captured, and it
works if I don't mess with timer 0 at all.) I don't want to have to shut
off the keyboard entirely if there is a possibility of figuring out why
the NMI is causing problems with a fast timer 0.
Ideas?
Thanks in advance,
Mike
Many years ago I tried a similar trick. I think I wanted a 10 millisecond
interrupt rate instead of 55ms for an embedded DOS application, and I got it
to work - sort of. However, I soon discovered that many other things
including the Borland delay() function depend on the 55ms interval, so I
rather quickly abandoned that line of thinking. I rather suspect your PCjr
keyboard driver is making similar assumptions regarding the tick rate.
I still use the 8253 for timing with better resolution by simply latching
and reading it periodically. Of course one must check and compensate for
the case where the timer rolls over from 0x0000 to 0xFFFF between two
successive reads. It is necessary to hold interrupts around the latch and
read command sequence to avoid incorrect register read values. I seem to
recall the 8253 counts down at a 0.8 microsecond rate so this only works if
one can arrange to check the timer at least once every 52ms.
I should add that my experience doing this is all under DOS on a PC, not a
PCjr. It does seem to work fine in a DOS window under both W98 and XP as
well, though I try to always use a full screen DOS window since I understand
that fewer things are "virtualized" in that case. I have no details as to
what those things are, but everything just seems to work better that way.
Later,
Charlie Carothers
--
My email address is csquared3 at tx dot rr dot com