PIT not triggering interupt
Posted: Mon Jul 16, 2018 11:32 pm
For some reason, I can't seem to get my timer interrupt to trigger. I'm following James Molloy's tutorial and trying to keep in mind the standard known issues listed on the wiki. It might just be some dumb C bug but I can't seem to find it.
I expect this code to print out a ton of "Tick" messages but instead, it just prints out the following
(Chunks of my code that I think are relevant posted below)
kernel_main
The relevant assembly for irq1-15
isr_init
some other irq related functions form the tutorial
and finally the timer code from the tutorial (as I've written/copied it)
I expect this code to print out a ton of "Tick" messages but instead, it just prints out the following
The first two show that I made it past the timer init. The fact that printing works (even for manually triggered interrupts) and that I should be printing "irq hit" if I was getting to irq_handle indicates to me that I'm not managing to get into irq0 like I wanted. I'm not particularlly sure why I'm not getting there though. Any idea what I might be doing wrong?setting up timer
registering interrupt handler
Unhandled Interupt: 0x03
Unhandled Interupt: 0x04
(Chunks of my code that I think are relevant posted below)
kernel_main
Code: Select all
void kernel_main(void) {
gdt_init();
idt_init();
t_init();
timer_init(100);
asm volatile ("int $0x3");
asm volatile ("int $0x4");
}
Code: Select all
.global irq_handler
.type irq_handler, @function
irq_common_stub:
pusha
mov %ds, %ax
push %eax
push %esp
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
call irq_handler
add $0x04, %esp
pop %eax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
popa
add $0x08,%esp
iret
.macro make_iqr n irqn
.global irq\n
.type irq\n, @function
irq\n:
cli
push $0
push $\irqn
jmp irq_common_stub
.endm
make_iqr 0,32
...
make_iqr 15,47
Code: Select all
void idt_init() {
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
idt_ptr.base = (uint32_t)&idt_entries;
kmemset((void *)&idt_entries, 0, sizeof(idt_entry_t) * 256);
kmemset((void *)&interrupt_handlers, 0, sizeof(isr_t) * 256);
// Remap the irq tables
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
idt_set_gate(0, (uint32_t)isr0, 0x08, 0x8E);
...
idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E);
idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E);
idt_set_gate(34, (uint32_t)irq2, 0x08, 0x8E);
idt_set_gate(35, (uint32_t)irq3, 0x08, 0x8E);
idt_set_gate(36, (uint32_t)irq4, 0x08, 0x8E);
idt_set_gate(37, (uint32_t)irq5, 0x08, 0x8E);
idt_set_gate(38, (uint32_t)irq6, 0x08, 0x8E);
idt_set_gate(39, (uint32_t)irq7, 0x08, 0x8E);
idt_set_gate(40, (uint32_t)irq8, 0x08, 0x8E);
idt_set_gate(41, (uint32_t)irq9, 0x08, 0x8E);
idt_set_gate(42, (uint32_t)irq10, 0x08, 0x8E);
idt_set_gate(43, (uint32_t)irq11, 0x08, 0x8E);
idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E);
idt_set_gate(45, (uint32_t)irq13, 0x08, 0x8E);
idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E);
idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E);
idt_flush((uint32_t)&idt_ptr);
}
Code: Select all
void isr_handler(registers_t *regs) {
if (interrupt_handlers[regs->int_no])
interrupt_handlers[regs->int_no](regs);
else {
term_t *term = t_curterm();
static const char *lookup = "0123456789ABCDEF";
t_print(term, "\n\nUnhandled interrupt: 0x");
t_putchar(term, lookup[(regs->int_no >> 4) & 0xF]);
t_putchar(term, lookup[regs->int_no & 0xF]);
t_print(term, "\n");
}
}
void register_interrupt_handler(uint8_t n, isr_t h) {
t_print(t_curterm(), "registering interrupt handler\n");
interrupt_handlers[n] = h;
}
void irq_handler(registers_t *regs);
void irq_handler(registers_t *regs) {
t_print(t_curterm(), "irq hit\n");
if (regs->int_no >= 40) {
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
if (interrupt_handlers[regs->int_no] != 0)
interrupt_handlers[regs->int_no](regs);
}
Code: Select all
static void timer_callback(registers_t* regs) {
term_t *term = t_curterm();
t_print(term, "Tick\n");
tick++;
}
void timer_init(uint16_t frequency) {
t_print(t_curterm(), "setting up timer\n");
// Firstly, register our timer callback.
register_interrupt_handler(IRQ0, &timer_callback);
// The value we send to the PIT is the value to divide it's input clock
// (1193180 Hz) by, to get our required frequency. Important to note is
// that the divisor must be small enough to fit into 16-bits.
uint32_t divisor = 1193180 / frequency;
// Send the command byte.
outb(0x43, 0x36);
// Divisor has to be sent byte-wise, so split here into upper/lower bytes.
uint8_t l = (uint8_t)(divisor & 0xFF);
uint8_t h = (uint8_t)((divisor >> 8) & 0xFF);
// Send the frequency divisor.
outb(0x40, l);
outb(0x40, h);
}