CLOSE

1 timer.c

#include <system.h>

/* 
 * Configure the Programmable Interval Timer (PIT) to generate interrupts at a specific frequency.
 */
void timer_phase(int hz) {
    // Calculate the divisor needed for the desired frequency
    int divisor = 1193180 / hz;
    
    // Send the command byte to PIT control register
    outportb(0x43, 0x36);
    
    // Send the divisor to the PIT data register
    outportb(0x40, divisor & 0xFF);    // Low byte
    outportb(0x40, divisor >> 8);      // High byte
}

// Global variables to keep track of timer ticks and ticker
int timer_ticks = 0;
unsigned long ticker = 0;

/* 
 * Timer interrupt handler.
 * This function will be called every time the timer interrupt occurs.
 */
void timer_handler(struct regs *r) {
    // Increment the timer ticks
    ++timer_ticks;
    
    // Perform actions every 18 ticks (~1 second if the frequency is 18.222 Hz)
    if (timer_ticks % 18 == 0) {
        ticker++;  // Increment the ticker
        
        // Print a message to indicate a tick
        puts("Tick. ");
        
        // Display a rotating animation to show timer progress
        if     (ticker % 4 == 0) { putch('|'); }
        else if(ticker % 4 == 1) { putch('/'); }
        else if(ticker % 4 == 2) { putch('-'); }
        else if(ticker % 4 == 3) { putch('\\'); }
        
        // New line for readability
        putch('\n');
    }
}

/* 
 * Install the timer interrupt handler.
 * This function sets up the handler for IRQ0 (the timer interrupt).
 */
void timer_install() {
    irq_install_handler(0, timer_handler);
}

/* 
 * Wait for a specified number of timer ticks.
 * This function will block until the specified number of ticks has passed.
 */
void timer_wait(int ticks) {
    // Calculate the end tick count
    unsigned long eticks = timer_ticks + ticks;
    
    // Wait until the current tick count reaches the end tick count
    while(timer_ticks < eticks);
}

1 timer_phase(int hz);

  • Configures the PIT to generate interrupts at a specific frequency.
  • The hz parameter is the desired frequency in Hertz.
  • The divisor is calculated by dividing the base frequency (1193180 Hz) by the desired frequency.
  • The divisor is then sent to the PIT control and data registers

2 Global Variables:

  • timer_ticks: Keeps track of the number of timer ticks since the timer was initialized.
  • ticker: A counter to keep track of the number of seconds or specific intervals passed.

3 timer_handler(struct regs r):

  • This function is the ISR for the timer.
  • It increments the timer_ticks variable each time it is called.
  • Every 18 ticks (approximately 1 second at 18.222 Hz), it increments the ticker variable and prints a message to the screen.
  • It also prints a rotating animation character to indicate progress.

4 timer_install():

  • Installs the timer_handler function as the handler for IRQ0, which is the timer interrupt.

5 timer_wait(int ticks):

  • Blocks execution for a specified number of timer ticks.
  • It calculates the end tick count and waits in a loop until the current tick count reaches this value.

2 Update system.h

Update system.h file to add extern declarations of the timer functions.

/* Timer */
extern void timer_install();
extern int timer_ticks;
extern void timer_wait(int ticks);

3 Modify main.c

	// Install the timer handler
    timer_install();
    
    // Set the timer phase to the desired frequency (e.g., 18.222 Hz)
    timer_phase(18);
    
    // Enable interrupts
    __asm__ __volatile__("sti");
    
    // Other kernel initialization code...

    // Test the timer by waiting for a few ticks
    timer_wait(100);