erd@lear.cs.duke.edu (Ed Darken) (01/15/90)
Hi. I'm having a hairy problem with a PC interrupt handler, and I'm posting this article in the desperate hope that somebody out there can suggest a solution. Here's the short version of the problem: I've written an interrupt handler to capture counter/timer board interrupts on IRQ3 every 20 milliseconds, but the handler fails after 1000-35,000 interrupts. The longer version: We have a counter/timer board in an AT-compatible 16-Mhz 80386SX PC (in case you're interested, the timer board is made by Data Translation, Inc., and the AT-compatible motherboard is from WaveMate). The timer board is configured to interrupt on IRQ3. There aren't any COM boards in this PC, and I'm sure the timer board is the only thing using IRQ3. I've written my own interrupt handler to capture the IRQ3 interrupt and reload the clock with another count. I initially wrote the handler in Microsoft C 5.1 but rewrote it (and this is a measure of my desperation) in Microsoft Assembler 4.0. I also wrote routines that initialize (i.e., enable IRQ3 interrupts, load an initial count, etc.) and shut down the timer. My test program calls the init routine and then waits for the user to type 'q' on the keyboard, upon which it exits with a report on the number of timer interrupts and the like, read from global variables set by the interrupt handler. In addition to keeping a count of the number of interrupts, the handler raises and lowers a bit on a parallel port. I monitor that line on an oscilloscope (you know you're in trouble when you're debugging your programs with an oscilloscope). When I start the program, everything looks hunky-dory on the scope; I see spikes every 20 milliseconds. However, after 1,000 to 35,000 interrupts (20 to 700 seconds), I stop seeing the spikes. All looks well with the program: I type 'q', and everything ends nicely (most specifically, there doesn't appear to be any corruption of the stack); BUT, the interrupt handler (or the timer) has stopped doing its job. My handler does the following (there's at most a 50-microsecond lapse from the time it sets the parallet bit high to the time it sets the bit low): =====> INTERRUPT! Push regs Set up local data and stack segments Re-enable interrupts (STI) Set parallel port bit high (using OUT instructions) Reload and start clock (using OUT instructions) Set parallel port bit low (using OUT instructions) Send non-specific EOI (using OUT instruction) Restore data and stack segments Restore regs Return from interrupt (IRET) The initialization routine uses INT21 to save the old interrupt vector (35H) and to set the new vector (25H). The shutdown routine uses INT21 (function 25H) to restore the original vector. These are the only times that INT21 is used; the handler itself does NOT use INT21. I've tried fiddling with stacks and stack sizes, with no effect whatsoever. I've also tried turning off all interrupts except keyboard and IRQ3 (using the interrupt mask). The problem persists (and I don't even type anything at the keyboard until the spikes disappear). It looks to me like my interrupt gets dropped or trampled in a probabilistic manner. I suspected the system clock interrupts (IRQ0), but turning them off doesn't seem to help. HELP! I'll listen to anything you have to say. Thanks, Ed Darken erd@cs.duke.edu P.S. By the way, I wrote a program that does the same thing by polling the timer rather than responding to interrupts. THAT runs ad infinitum.
davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (01/16/90)
In article <16815@duke.cs.duke.edu> erd@lear.cs.duke.edu (Ed Darken) writes: | Reload and start clock (using OUT instructions) | Set parallel port bit low (using OUT instructions) ==> Disable interrupts | Send non-specific EOI (using OUT instruction) | Restore data and stack segments | Restore regs | Return from interrupt (IRET) -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) "Stupidity, like virtue, is its own reward" -me