scole@janus.Berkeley.EDU (Steven Cole) (10/13/90)
I'm wondering if anyone out there can help me... I'm looking for a code fragment that sets up timer interrupts approximately every 125 usec on a vanilla PC. From what I understand, this is possible by resetting the timer chip that causes INT 08, but unfortunately I don't know just how to do this. (I.e., is this register memory mapped or does it take some obscure I/O operation?) Thanks for any pointers, Steve Cole, scole@janus.berkeley.edu
np4@prism.gatech.EDU (POMPONIO,NICHOLAS A) (10/13/90)
In article <39119@ucbvax.BERKELEY.EDU> scole@janus.Berkeley.EDU (Steven Cole) writes: >I'm wondering if anyone out there can help me... > >I'm looking for a code fragment that sets up timer interrupts >approximately every 125 usec on a vanilla PC. From what I understand, >this is possible by resetting the timer chip that causes INT 08, but >unfortunately I don't know just how to do this. (I.e., is this >register memory mapped or does it take some obscure I/O operation?) > >Thanks for any pointers, > I used the following snippit of code to speed the clock interrupts. (I hope that you are using a very fast PC, because an XT that I used previously could take up to 125 usec just to respond to the interrupt!) The code is in Microsoft C 5.1. I gathered bits and pieces from some working code, and hopefully the details you need are here. If not, let me know by e-mail. -------------------------------------------------------------------------- static void (interrupt * old_intr8)(); static void interrupt system_timer (); /* Timer (8253) values */ #define TIMER_CONTROL_PORT 0x43 #define TIMER_0_PORT 0x40 #define TIMER_LOAD0_CMD 0x36 #define DIVIDE_BY 2 /* Speed up clock int's by this factor */ #define TIMER_0_COUNT 0x10000 / DIVIDE_BY #define TIMER_0_DEFAULT 0u static void install_interrupts () { /* This routine installs the interrupt handler routine below and reprograms the timer channel 0 */ auto union { unsigned int word; unsigned char bytes [2]; } split; old_intr8 = _dos_getvect (0x08); split.word = TIMER_0_COUNT; _disable (); outp (TIMER_CONTROL_PORT, TIMER_LOAD0_CMD); outp (TIMER_0_PORT, split.bytes [0]); outp (TIMER_0_PORT, split.bytes [1]); _dos_setvect (0x08, system_timer); _enable (); } #pragma check_stack(off) void interrupt system_timer () { /* This routine is the interrupt handler. The check_stack pragmas are needed only if you plan to call another function from this handler. */ static int divide_by = DIVIDE_BY; if (--divide_by == 0) { divide_by = DIVIDE_BY; (* old_intr8)(); } else { outp (0x20, 0x20); /* non-specific end-of-interrupt reset */ _enable (); } /* Do something here */ } #pragma check_stack(on) -- POMPONIO,NICHOLAS A Georgia Institute of Technology, Atlanta Georgia, 30332 uucp: ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!np4 Internet: np4@prism.gatech.edu
dixon@sagittarius.crd.ge.com (walt dixon) (10/13/90)
In <39119@ucbvax.BERKELEY.EDU> Steven Cole writes: >I'm looking for a code fragment that sets up timer interrupts >approximately every 125 usec on a vanilla PC. From what I understand, >this is possible by resetting the timer chip that causes INT 08, but >unfortunately I don't know just how to do this. (I.e., is this >register memory mapped or does it take some obscure I/O operation?) It is definitely possible to change the rate of the system clock. There are side effects of just increasing the clock frequency such as the tod clock gains time and some bios operations time out prematurely. The "proper" approach is to install a new int 8 ISR which calls the previous ISR at the appropriate time. The clock chip on the PC (8253) is pretty easy to use, and there are a number of books which describe its operation. Before I would attempt such a speed up, I would do some kind of timing analysis to make sure there were enough CPU cycles available. Check out Chapter 11 of "The MS-DOS Papers" (Howard Sams, 1988). In that chapter I present a device driver which speeds up the clock by a factor of 16 and go through the timing analysis. The book contains complete source code for the driver. BTW I get no revenues from book sales; I'm just citing a good reference. Walt Dixon {internet: dixon@crd.ge.com } {us mail: ge-crd } { po box 8 } { schenectady, ny 12301 } {phone: 518-387-5798 (W) } { 518-875-6203 (H) } Walt Dixon dixon@crd.ge.com
KRW1@Lehigh (10/15/90)
It's fairly easy to speed up the timer. Dealing with the consequences is another matter. You work with the system timer by issuing the proper command to the control register at i/o address 43h, and reading/writing data at 40h. The basic timer tick is .838095 usec. The largest number of ticks in the countdown cycle is ffffh, which is about 55 msec - the basic timer interrupt interval. To change to something else, first write 34h to port 43h to indicate that you will be sending first the low and then high order bytes of the countdown cycle. Write those to port 40h in succession. That's it. Then you can try it again after the system hangs. It's generally not considered a safe practice to change the timer rate - there are many potential eyes watching and depending on it. If you've taken care of those possibilities, however, the other thing to consider is that a vanilla PC probably can't interrupt every 125 usec. 500 usec would be a better figure to shoot for if the interrupt routine is expected to have time to do anything. Fast 286's and 386's can handle it without any problem, but not 808x and slow 286's. If you just need high timing resolution, consider an alternate approach which involves a non-interrupt driven process that reads the timer directly. There are various hi-res timer routines floating around on the net. -- Kevin ------------------------------------------------------------------ Kevin Weiner Lehigh University Computing Center (215) 758-3991