Page 1 of 1

Cannot get PIT timer to work

Posted: Thu Aug 10, 2023 7:35 pm
by Nemanja
I've been trying to get this to work for a long time, and have failed numerous times to do so.
I have been working on the IDT on my kernel, and have gotten exceptions like `division by zero` to get triggered, but I can't seem to get the PIT to trigger an interrupt for me. Here's my idt.c file:

Code: Select all

#include <stdint.h>
#include <stddef.h>
#include <kernel/terminal.h>
#include <kernel/idt.h>
#include <kernel/hang.h>

static idt_t idt[256];
void *isr[256];
extern void *isr_wrappers[];

static void register_handler(uint8_t vector, void *handler, uint8_t flags)
{
    uint64_t handler_int = (uint64_t)handler;

    idt[vector] = (idt_t) {
        .offset_low = (uint16_t)handler_int,
        .selector = 0x28,
        .ist = 0,
        .flags = flags,
        .offset_mid = (uint16_t)(handler_int >> 16),
        .offset_hi = (uint32_t)(handler_int >> 32),
        .reserved = 0
    };
}

uint8_t idt_allocate_vector()
{
    static uint8_t free_vector = 32;

    if (free_vector == 0xf0)
    {
        terminal_printf(current_terminal, "IDT is full!\n");
        hang();
    }

    uint8_t ret = free_vector++;

    return ret;
}

void feed_idt() 
{
    idt_pointer_t idtr = {
        .limit = sizeof(idt) - 1,
        .base = (uint64_t)idt
    };

    asm volatile ("lidt %0" :: "m"(idtr) : "memory");
}

void idt_initialize()
{
    for (size_t i = 0; i < 256; i++)
    {
        register_handler(i, isr_wrappers[i], 0x8e);
    }

    feed_idt();
}
Then my idt.h file:

Code: Select all

#pragma once

#include <stdint.h>

extern void *isr[];

typedef struct
{
    uint16_t offset_low;
    uint16_t selector;
    uint8_t ist;
    uint8_t flags;
    uint16_t offset_mid;
    uint32_t offset_hi;
    uint32_t reserved;
} idt_t;

typedef struct
{
    uint16_t limit;
    uint64_t base;
} __attribute__((packed)) idt_pointer_t;

uint8_t idt_allocate_vector();
void feed_idt();
void idt_initialize();
Then the code that handles interrupts (affair.c):

Code: Select all

#define PIT_COMMAND 0x43
#define PIT_CHANNEL0_DATA 0x40
#define PIT_FREQUENCY 1193180
#define TARGET_FREQUENCY 100
#define DIVISOR (PIT_FREQUENCY / TARGET_FREQUENCY)

static void affair_handler(uint8_t vector, registers_t * registers)
{
    switch(vector)
    {
    case 0:
        terminal_printf(current_terminal, "Division by zero exception triggered!\n");
        print_registers(current_terminal, registers);
        terminal_printf(current_terminal, "Halting CPU...\n");
        hang();
        break;
    case 32:
        terminal_printf(current_terminal, "Timer interrupt fired!\n");
        break;
    }
}

void affair_initialize()
{
    out8(PIT_COMMAND, 0x36);
    out8(PIT_CHANNEL0_DATA, (uint8_t)(DIVISOR & 0xFF));
    out8(PIT_CHANNEL0_DATA, (uint8_t)((DIVISOR >> 8) & 0xFF));

    for (size_t i = 0; i < 256; i++)
    {
        isr[i] = affair_handler;
    }
}
And affair.h:
#pragma once

void exceptions_initialize();
Lines 34-36 are intended to start the PIT timer, but even then I can't get the PIT timer to trigger line 27 (in affair.c).
If anyone knows what's causing this issue, It would be greatly appreciated if you could tell me what the issue is!

Re: Cannot get PIT timer to work

Posted: Sat Aug 12, 2023 11:07 pm
by Octocontrabass
Where is your code to set the interrupt flag and initialize the interrupt controllers?