Page 1 of 1

PIT Setup and Initialization

Posted: Wed Jul 26, 2023 12:03 am
by FunnyGuy9796
I am currently trying to configure the PIT but can't seem to trigger any interrupts using it.

pit.h

Code: Select all

#ifndef PIT_H_INCLUDED
#define PIT_H_INCLUDED

#include <stdint.h>
#include "../terminal.h"
#include "../byte.h"
#include "idt.h"

#define PIT_CHANNEL0 0x40
#define PIT_COMMAND 0x43
#define PIT_FREQUENCY 1193182

#define DESIRED_FREQUENCY 10

void pit_init();

#endif
pit.c

Code: Select all

#include "pit.h"

void pit_irq_handler() {
    print("hello");
    outb(0x20, 0x20);
}

void pit_init() {
    uint16_t divisor = PIT_FREQUENCY / DESIRED_FREQUENCY;
    outb(PIT_COMMAND, 0x36);
    outb(PIT_CHANNEL0, (uint8_t)(divisor & 0xFF));
    outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF));
    idt_set_descriptor(0x20, pit_irq_handler, 0x8E);
    print("PIT: Initialized\n");
}
I receive other interrupts so I know that it does not have to do with my IDT but I still am unable to figure it out. Help is much appreciated! :)

Re: PIT Setup and Initialization

Posted: Wed Jul 26, 2023 1:23 pm
by Barry
If you're using the IOAPIC you'll need to route the PIT's interrupt to a core, or use the LAPIC timer instead. Assuming you're using the 8259 PIC, have you reprogrammed it to route the interrupts to your desired range (0x20 to 0x30)?

Does your function "idt_set_descriptor" actually set the given function as the IDT entry? If so, your function will need the appropriate prologue and epilogue. Either mark pit_irq_handler with __attribute__((interrupt)), or write an interrupt stub that calls into a central function, which can then call out into your registered function, pit_irq_handler. The stub function is preferable as it gives you more control over the information you save.

Re: PIT Setup and Initialization

Posted: Wed Jul 26, 2023 6:35 pm
by Octocontrabass
FunnyGuy9796 wrote:

Code: Select all

#define DESIRED_FREQUENCY 10
The lowest possible PIT frequency is about 18.2 Hz.
FunnyGuy9796 wrote:

Code: Select all

void pit_irq_handler() {
...
    idt_set_descriptor(0x20, pit_irq_handler, 0x8E);
As Barry already mentioned, placing an ordinary function pointer in your IDT will cause problems because the ABI is incorrect. GCC and Clang support a function attribute that can correct the ABI for basic ring 0 bare-metal applications, but for a proper OS you'll need to write some assembly code.
FunnyGuy9796 wrote:I receive other interrupts so I know that it does not have to do with my IDT but I still am unable to figure it out.
There can be more than one problem. Did you unmask IRQ0 after setting up the IDT?