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