Probably the most basic of the timed events in a PC is the step-by-step operation of the computer's CPU, whose
speed is determined by the frequency of a special oscillator circuit that generates high-frequency pulses at regular
intervals. This frequency is the CPU's clock speed, and it determines how quickly the CPU can carry out its functions.
At each tick of the CPU clock (that is, at each pulse in the CPU oscillator's signal), the CPU carries out part of one machine instruction. All CPU instructions require one or more clock cycles to execute. For example, the register INC instruction requires two clock cycles to execute, except on the 80486, where it requires only one; more complicated instructions such as CALL and MUL take a longer amount of time.
In the original IBM PC and PC/XT, the CPU's clock speed is 4,772,727 cycles per second, or about 4.77 megahertz. One CPU clock cycle thus lasts about 1/4,772,727 of a second, or about 210 nanoseconds. The odd clock speed of 4.77 MHz was actually a convenient frequency for the designers of the original PC to use. In fact, the CPU clock speed is derived from a basic oscillator frequency of 14.31818 MHz, which is commonly used in television circuitry. Dividing the basic frequency by 3 gives the 4.77 MHz CPU clock speed. Dividing by 4 gives a clock speed of 3.57955 MHz, which is the frequency of the color burst signal used in color televisions and in the PC's Color Graphics Adapter. Dividing the basic frequency by 12 gives 1.19318 MHz, which is the clock frequency used by the PC's system timers.
System Timers
Not only the CPU but many other basic hardware and software functions occur at regular intervals based on a preset clock frequency. For example, the dynamic RAM chips that constitute the computer's main memory must be accessed at regular intervals in order to refresh the information represented in them. Also, ROM BIOS and operating system functions such as keeping track of the time of day require the computer to generate a clock-tick signal at a predetermined rate. All PCs have circuitry that generates the necessary timing signals.
In the PC and PC/XT, an Intel 82535 programmable timer/counter chip produces the RAM refresh and clock-tick signals. In the PC/AT, an Intel 82542 chip is used in the same way. Clones from other manufacturers use a variety of methods to generate timing signals.
Despite these hardware variations, the timer programming interface is the same in all PCs.
In all members of the PC family, the timer chip has three output channels, each with a dedicated function:
Using the System Timer Tick
In all PCs, the input oscillator to the system timer circuit has a frequency of 1.19318 MHz. On each cycle, the timer chip decrements the values in a set of internal 16-bit counters, one for each of the timer's output channels. When the value in a counter reaches 0, the chip generates a single output pulse on the corresponding channel, resets the count, and starts counting down again.
When the ROM BIOS initializes the system timer, it stores a countdown value of 0 in the count register for channel 0. This means that the timer chip decrements the counter 2l6 times between output pulses on channel 0, so out put pulses occur at a rate equal to 1,193,180/65,536 = 18.20648193, or 18.2 times per second. The output from timer channel 0 is used as the signal on interrupt request level 0 (IRQ 0), so interrupt 08H occurs whenever channel 0 of the system timer counts down to 0; that is, 18.2 times per second.
A Timer Example
// The clock function�s era begins (with a value of 0) when the
// C program starts to execute. It returns times measured in
// 1/CLOCKS_PER_SEC (which equals 1/1000 for Microsoft C).
// CLOCK.C: This example prompts for how long
// the program is to run and then continuously
// displays the elapsed time for that period.
#include <iostream.h>
#include <time.h>
void sleep( clock_t wait );
void main( void ) {
long i = 600000000L;
clock_t start, finish;
double duration;
// Delay for a specified time.
cout << "Delay for three seconds" << endl;
sleep( (clock_t)3 * CLOCKS_PER_SEC );
cout << "Done!" << endl;
// Measure the duration of an event.
cout << "Time to do " << i << " empty loops is ";
start = clock();
while( i-- ) ;
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << duration << " seconds" << endl;
}
// Pauses for a specified number of milliseconds.
void sleep( clock_t wait ) {
clock_t goal;
goal = wait + clock();
while( goal > clock() ) ;
}
/* output is:
Delay for three seconds
Done!
Time to do 600000000 empty loops is 14.28 seconds
*/