Cannot get PIT timer to work
Posted: Thu Aug 10, 2023 7:35 pm
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:
Then my idt.h file:
Then the code that handles interrupts (affair.c):
And affair.h:
If anyone knows what's causing this issue, It would be greatly appreciated if you could tell me what the issue is!
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();
}
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();
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;
}
}
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).#pragma once
void exceptions_initialize();
If anyone knows what's causing this issue, It would be greatly appreciated if you could tell me what the issue is!