PCjr NMI and 8253 Timer interactions

Michael B. Brutman mbbrutman-cctalk at brutman.com
Tue Sep 29 11:30:37 CDT 2009


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



More information about the cctalk mailing list