From 507bdb2bc255e095bfe4c1580178db3483b5d9a7 Mon Sep 17 00:00:00 2001 From: Ox03bb Date: Wed, 9 Sep 2026 01:52:19 +0100 Subject: [PATCH 1/6] add pit driver --- includes/{ => interrupt}/pic.h | 0 includes/interrupt/pit.h | 14 +++++++ src/interrupt/irq.asm | 77 +++++++++++++++++----------------- src/interrupt/irq.c | 5 +++ src/interrupt/pit.c | 35 ++++++++++++++++ src/kernel/kernel.c | 14 +++++-- 6 files changed, 103 insertions(+), 42 deletions(-) rename includes/{ => interrupt}/pic.h (100%) create mode 100644 includes/interrupt/pit.h create mode 100644 src/interrupt/pit.c diff --git a/includes/pic.h b/includes/interrupt/pic.h similarity index 100% rename from includes/pic.h rename to includes/interrupt/pic.h diff --git a/includes/interrupt/pit.h b/includes/interrupt/pit.h new file mode 100644 index 0000000..ab61170 --- /dev/null +++ b/includes/interrupt/pit.h @@ -0,0 +1,14 @@ +#ifndef PIT_H +#define PIT_H + +#define PIT_CHANNEL0 0x40 +#define PIT_COMMAND 0x43 +#define PIT_BASE_FREQ 1193182 + +#include + +void pit_init(uint32_t frequency); +void pit_set_frequency(uint32_t frequency); +uint16_t pit_calculate_divisor(uint32_t frequency); + +#endif \ No newline at end of file diff --git a/src/interrupt/irq.asm b/src/interrupt/irq.asm index f34115f..9548965 100644 --- a/src/interrupt/irq.asm +++ b/src/interrupt/irq.asm @@ -1,23 +1,5 @@ -; ============================================================ -; IRQ handlers 0-15 -; -; PIC IRQs: -; IRQ 0 -> IDT vector 32 -; IRQ 1 -> IDT vector 33 -; ... -; IRQ 15 -> IDT vector 47 -; -; The IDT uses vectors 32-47, but we pass IRQ numbers -; 0-15 to the C IRQ handler. -; ============================================================ - [BITS 32] - -; ============================================================ -; Export IRQ handlers and IRQ table -; ============================================================ - global irq0 global irq1 global irq2 @@ -37,31 +19,33 @@ global irq15 global irq_table - extern irq_handler ; ============================================================ ; IRQ macro ; -; IRQs do NOT automatically push an error code. +; Hardware IRQs do NOT automatically push an error code. ; -; We push: +; We push only the IRQ number ourselves. ; -; 1. dummy error code -; 2. IRQ number +; Stack when entering irq_common_stub: ; -; This gives us a predictable stack layout. +; [ESP] = IRQ number +; [ESP + 4] = EIP +; [ESP + 8] = CS +; [ESP + 12] = EFLAGS ; ============================================================ %macro IRQ 1 irq%1: - + ; Interrupt gates already clear IF automatically. + ; This CLI is therefore optional. cli - push dword 0 ; dummy error code - push dword %1 ; IRQ number: 0-15 + ; Push IRQ number + push dword %1 jmp irq_common_stub @@ -69,7 +53,7 @@ irq%1: ; ============================================================ -; IRQ entry points +; IRQ handlers ; ============================================================ IRQ 0 @@ -121,29 +105,44 @@ irq_table: ; ============================================================ -; Common IRQ stub +; Common IRQ handler ; ============================================================ section .text irq_common_stub: - ; Save general-purpose registers + ; Save all general-purpose registers pusha - ; Pass pointer to interrupt frame - push esp + ; After PUSHA: + ; + ; [ESP + 0] = EDI + ; [ESP + 4] = ESI + ; [ESP + 8] = EBP + ; [ESP + 12] = original ESP + ; [ESP + 16] = EBX + ; [ESP + 20] = EDX + ; [ESP + 24] = ECX + ; [ESP + 28] = EAX + ; [ESP + 32] = IRQ number + ; [ESP + 36] = EIP + ; [ESP + 40] = CS + ; [ESP + 44] = EFLAGS + + ; Pass IRQ number to C + push dword [esp + 32] + call irq_handler + + ; Remove argument passed to C add esp, 4 - ; Restore general-purpose registers + ; Restore registers popa - ; Remove: - ; - ; 4 bytes = IRQ number - ; 4 bytes = dummy error code - ; - add esp, 8 + ; Remove IRQ number + add esp, 4 + ; Return from interrupt iretd \ No newline at end of file diff --git a/src/interrupt/irq.c b/src/interrupt/irq.c index 84a97a4..31ec781 100644 --- a/src/interrupt/irq.c +++ b/src/interrupt/irq.c @@ -1,9 +1,14 @@ #include "irq.h" #include "vga.h" #include "vga_lib.h" +#include "pic.h" void irq_handler(uint32_t vector) { + vga_print("IRQ: "); vga_print_hex(vector); vga_print("\n"); + + pic_send_eoi((uint8_t)vector); + } \ No newline at end of file diff --git a/src/interrupt/pit.c b/src/interrupt/pit.c new file mode 100644 index 0000000..10738f7 --- /dev/null +++ b/src/interrupt/pit.c @@ -0,0 +1,35 @@ +#include "pit.h" +#include "utils.h" +#include + +void pit_init(uint32_t frequency){ + pit_set_frequency(frequency); +} + + +void pit_set_frequency(uint32_t frequency){ + uint16_t divisor = pit_calculate_divisor(frequency); + + outb(PIT_COMMAND, 0x34); // ch 0, mode 2, binary + + outb(PIT_CHANNEL0, (uint8_t)(divisor & 0xFF)); // Low byte + outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); // High byte + +} + + +uint16_t pit_calculate_divisor(uint32_t frequency) +{ + if (frequency == 0) + return 0; + + uint32_t divisor = PIT_BASE_FREQ / frequency; + + if (divisor < 1) + divisor = 1; + + if (divisor > 65535) // overflow check + divisor = 65535; + + return (uint16_t)divisor; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 446dac9..72fd6a3 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,6 +2,7 @@ #include "idt.h" #include "panic.h" #include "pic.h" +#include "pit.h" #include "utils.h" #include "vga.h" #include "vga_lib.h" @@ -20,12 +21,19 @@ void kernel_main() { idt_init(); vga_print_at_end_c("... Ok\n", GREEN); - asm volatile("int $0x22"); + vga_log_info("[", "init", "] pit"); + pic_clear_mask(0); + pit_init(100); // 100 Hz + vga_print_at_end_c("... Ok\n", GREEN); + + // asm volatile("int $0x22"); + + // panic("testing panics"); - panic("testing panics"); + asm volatile("sti"); for (;;) { - asm volatile("cli"); + asm volatile("hlt"); } return; From dc3dc6341127aae65ef68837c34ed45029d0097e Mon Sep 17 00:00:00 2001 From: Ox03bb Date: Wed, 9 Sep 2026 01:58:06 +0100 Subject: [PATCH 2/6] update folder structer --- src/interrupt/{ => irq}/irq.asm | 0 src/interrupt/{ => irq}/irq.c | 0 src/interrupt/{ => isr}/isr.asm | 0 src/interrupt/{ => isr}/isr.c | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/interrupt/{ => irq}/irq.asm (100%) rename src/interrupt/{ => irq}/irq.c (100%) rename src/interrupt/{ => isr}/isr.asm (100%) rename src/interrupt/{ => isr}/isr.c (100%) diff --git a/src/interrupt/irq.asm b/src/interrupt/irq/irq.asm similarity index 100% rename from src/interrupt/irq.asm rename to src/interrupt/irq/irq.asm diff --git a/src/interrupt/irq.c b/src/interrupt/irq/irq.c similarity index 100% rename from src/interrupt/irq.c rename to src/interrupt/irq/irq.c diff --git a/src/interrupt/isr.asm b/src/interrupt/isr/isr.asm similarity index 100% rename from src/interrupt/isr.asm rename to src/interrupt/isr/isr.asm diff --git a/src/interrupt/isr.c b/src/interrupt/isr/isr.c similarity index 100% rename from src/interrupt/isr.c rename to src/interrupt/isr/isr.c From 2175b1065d3f39f104f6811a557422f41050a3ea Mon Sep 17 00:00:00 2001 From: Ox03bb Date: Fri, 11 Sep 2026 00:05:09 +0100 Subject: [PATCH 3/6] some updates --- includes/interrupt/pit.h | 30 ++++++++++++++++++++++++++++++ src/interrupt/irq/irq.c | 15 ++++++++++----- src/interrupt/pit.c | 12 ++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/includes/interrupt/pit.h b/includes/interrupt/pit.h index ab61170..9abedc7 100644 --- a/includes/interrupt/pit.h +++ b/includes/interrupt/pit.h @@ -2,13 +2,43 @@ #define PIT_H #define PIT_CHANNEL0 0x40 +#define PIT_CHANNEL1 0x41 +#define PIT_CHANNEL2 0x42 #define PIT_COMMAND 0x43 #define PIT_BASE_FREQ 1193182 #include +/* Channels */ +#define PIT_CHANNEL_0 0 +#define PIT_CHANNEL_1 1 +#define PIT_CHANNEL_2 2 + +/* Access modes */ +#define PIT_ACCESS_LATCH 0x00 +#define PIT_ACCESS_LOBYTE 0x10 +#define PIT_ACCESS_HIBYTE 0x20 +#define PIT_ACCESS_LOHI 0x30 + +/* Operating modes */ +#define PIT_MODE_0 0x00 +#define PIT_MODE_1 0x02 +#define PIT_MODE_2 0x04 +#define PIT_MODE_3 0x06 +#define PIT_MODE_4 0x08 +#define PIT_MODE_5 0x0A + +/* Binary mode */ +#define PIT_BINARY 0x00 + +uint16_t div; +uint32_t freq; + + void pit_init(uint32_t frequency); void pit_set_frequency(uint32_t frequency); uint16_t pit_calculate_divisor(uint32_t frequency); +uint16_t get_divisor(); +uint32_t get_frequency(); #endif \ No newline at end of file diff --git a/src/interrupt/irq/irq.c b/src/interrupt/irq/irq.c index 31ec781..e431b3f 100644 --- a/src/interrupt/irq/irq.c +++ b/src/interrupt/irq/irq.c @@ -5,10 +5,15 @@ void irq_handler(uint32_t vector) { - vga_print("IRQ: "); - vga_print_hex(vector); - vga_print("\n"); - + if (vector == 0){ + vga_print("Time IRQ \n"); + }else{ + vga_print("IRQ: "); + vga_print_hex(vector); + vga_print("\n"); + } + pic_send_eoi((uint8_t)vector); -} \ No newline at end of file +} + diff --git a/src/interrupt/pit.c b/src/interrupt/pit.c index 10738f7..8aa8a16 100644 --- a/src/interrupt/pit.c +++ b/src/interrupt/pit.c @@ -9,6 +9,9 @@ void pit_init(uint32_t frequency){ void pit_set_frequency(uint32_t frequency){ uint16_t divisor = pit_calculate_divisor(frequency); + + div = divisor; + freq = frequency; outb(PIT_COMMAND, 0x34); // ch 0, mode 2, binary @@ -32,4 +35,13 @@ uint16_t pit_calculate_divisor(uint32_t frequency) divisor = 65535; return (uint16_t)divisor; +} + + +uint16_t get_divisor(){ + return div; +} + +uint32_t get_frequency(){ + return freq; } \ No newline at end of file From d77606f18b6ab36fd4f52ef5fc7fe60ad4563414 Mon Sep 17 00:00:00 2001 From: Ox03bb Date: Fri, 11 Sep 2026 00:42:33 +0100 Subject: [PATCH 4/6] fix sone error --- includes/interrupt/idt.h | 1 - includes/interrupt/pit.h | 4 ++-- src/interrupt/pit.c | 3 +++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/includes/interrupt/idt.h b/includes/interrupt/idt.h index c5ec1cd..95909f4 100644 --- a/includes/interrupt/idt.h +++ b/includes/interrupt/idt.h @@ -29,7 +29,6 @@ struct idtr { void idt_set_gate(uint8_t vector, uint32_t handler, uint16_t selector, uint8_t type_attr); void idt_init_descriptor(void); -static void idt_load(void); void idt_init(void); void idt_clear(void); diff --git a/includes/interrupt/pit.h b/includes/interrupt/pit.h index 9abedc7..7770a20 100644 --- a/includes/interrupt/pit.h +++ b/includes/interrupt/pit.h @@ -31,8 +31,8 @@ /* Binary mode */ #define PIT_BINARY 0x00 -uint16_t div; -uint32_t freq; +extern uint16_t div; +extern uint32_t freq; void pit_init(uint32_t frequency); diff --git a/src/interrupt/pit.c b/src/interrupt/pit.c index 8aa8a16..f630a60 100644 --- a/src/interrupt/pit.c +++ b/src/interrupt/pit.c @@ -2,6 +2,9 @@ #include "utils.h" #include +uint16_t div; +uint32_t freq; + void pit_init(uint32_t frequency){ pit_set_frequency(frequency); } From 3dcace98eb80ffe730c3e4c1bf7e3e9f6fa07183 Mon Sep 17 00:00:00 2001 From: Ox03bb Date: Fri, 11 Sep 2026 01:45:52 +0100 Subject: [PATCH 5/6] complite the timer --- includes/interrupt/pit.h | 12 ++++-------- includes/timer.h | 20 ++++++++++++++++++++ src/driver/vga.c | 2 +- src/interrupt/irq/irq.c | 21 ++++++++++++--------- src/interrupt/pit.c | 23 ++++++----------------- src/kernel/kernel.c | 25 ++++++++++++++++--------- src/kernel/timer.c | 31 +++++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 44 deletions(-) create mode 100644 includes/timer.h create mode 100644 src/kernel/timer.c diff --git a/includes/interrupt/pit.h b/includes/interrupt/pit.h index 7770a20..80c244e 100644 --- a/includes/interrupt/pit.h +++ b/includes/interrupt/pit.h @@ -15,10 +15,10 @@ #define PIT_CHANNEL_2 2 /* Access modes */ -#define PIT_ACCESS_LATCH 0x00 -#define PIT_ACCESS_LOBYTE 0x10 -#define PIT_ACCESS_HIBYTE 0x20 -#define PIT_ACCESS_LOHI 0x30 +#define PIT_ACCESS_LATCH 0x00 +#define PIT_ACCESS_LOBYTE 0x10 +#define PIT_ACCESS_HIBYTE 0x20 +#define PIT_ACCESS_LOHI 0x30 /* Operating modes */ #define PIT_MODE_0 0x00 @@ -31,10 +31,6 @@ /* Binary mode */ #define PIT_BINARY 0x00 -extern uint16_t div; -extern uint32_t freq; - - void pit_init(uint32_t frequency); void pit_set_frequency(uint32_t frequency); uint16_t pit_calculate_divisor(uint32_t frequency); diff --git a/includes/timer.h b/includes/timer.h new file mode 100644 index 0000000..c1979dc --- /dev/null +++ b/includes/timer.h @@ -0,0 +1,20 @@ +#ifndef TIMER_H +#define TIMER_H + +#include + +void timer_init(uint32_t frequency); + +void timer_irq_handler(void); + +uint32_t timer_get_ticks(void); + +uint32_t timer_get_seconds(void); + +uint32_t timer_get_frequency(void); + +void timer_sleep_m(uint32_t milliseconds); +void timer_sleep_s(uint32_t seconds); +void timer_sleep(float seconds); + +#endif \ No newline at end of file diff --git a/src/driver/vga.c b/src/driver/vga.c index d475c34..d489ce7 100644 --- a/src/driver/vga.c +++ b/src/driver/vga.c @@ -35,7 +35,7 @@ void vga_print(const char *str) { return; } - for (uint64_t i = 0; str[i] != '\0'; i++) { + for (uint32_t i = 0; str[i] != '\0'; i++) { if (str[i] == '\n') { uint8_t y = vga_get_cursor_y() + 1; vga_set_cursor(0, y); diff --git a/src/interrupt/irq/irq.c b/src/interrupt/irq/irq.c index e431b3f..33d5b7a 100644 --- a/src/interrupt/irq/irq.c +++ b/src/interrupt/irq/irq.c @@ -1,19 +1,22 @@ #include "irq.h" +#include "pic.h" +#include "timer.h" #include "vga.h" #include "vga_lib.h" -#include "pic.h" void irq_handler(uint32_t vector) { - if (vector == 0){ - vga_print("Time IRQ \n"); - }else{ + switch (vector) { + case 0: + timer_irq_handler(); + pic_send_eoi((uint8_t)vector); + break; + + default: vga_print("IRQ: "); vga_print_hex(vector); vga_print("\n"); - } - - pic_send_eoi((uint8_t)vector); - -} + pic_send_eoi((uint8_t)vector); + } +} \ No newline at end of file diff --git a/src/interrupt/pit.c b/src/interrupt/pit.c index f630a60..1737898 100644 --- a/src/interrupt/pit.c +++ b/src/interrupt/pit.c @@ -5,14 +5,11 @@ uint16_t div; uint32_t freq; -void pit_init(uint32_t frequency){ - pit_set_frequency(frequency); -} - +void pit_init(uint32_t frequency) { pit_set_frequency(frequency); } -void pit_set_frequency(uint32_t frequency){ +void pit_set_frequency(uint32_t frequency) { uint16_t divisor = pit_calculate_divisor(frequency); - + div = divisor; freq = frequency; @@ -20,12 +17,9 @@ void pit_set_frequency(uint32_t frequency){ outb(PIT_CHANNEL0, (uint8_t)(divisor & 0xFF)); // Low byte outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); // High byte - } - -uint16_t pit_calculate_divisor(uint32_t frequency) -{ +uint16_t pit_calculate_divisor(uint32_t frequency) { if (frequency == 0) return 0; @@ -40,11 +34,6 @@ uint16_t pit_calculate_divisor(uint32_t frequency) return (uint16_t)divisor; } +uint16_t get_divisor() { return div; } -uint16_t get_divisor(){ - return div; -} - -uint32_t get_frequency(){ - return freq; -} \ No newline at end of file +uint32_t get_frequency() { return freq; } \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 72fd6a3..a907122 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,12 +1,18 @@ #include "kernel.h" + #include "idt.h" -#include "panic.h" + #include "pic.h" #include "pit.h" -#include "utils.h" +#include "timer.h" + #include "vga.h" #include "vga_lib.h" +#include "panic.h" + +#include "utils.h" + void kernel_main() { vga_init(); @@ -21,16 +27,17 @@ void kernel_main() { idt_init(); vga_print_at_end_c("... Ok\n", GREEN); - vga_log_info("[", "init", "] pit"); + vga_log_info("[", "init", "] pit and timer"); pic_clear_mask(0); - pit_init(100); // 100 Hz - vga_print_at_end_c("... Ok\n", GREEN); + timer_init(1000); // 1000 Hz + sti(); - // asm volatile("int $0x22"); - - // panic("testing panics"); + for (int i = 0; i < 53; i++) { + vga_print("."); + timer_sleep(0.02); + } - asm volatile("sti"); + vga_print_at_end_c("... Ok\n", GREEN); for (;;) { asm volatile("hlt"); diff --git a/src/kernel/timer.c b/src/kernel/timer.c new file mode 100644 index 0000000..17d661f --- /dev/null +++ b/src/kernel/timer.c @@ -0,0 +1,31 @@ +#include "timer.h" +#include "pit.h" +#include "vga.h" + +static uint32_t ticks = 0; +static uint32_t timer_frequency = 0; + +void timer_init(uint32_t frequency) { + timer_frequency = frequency; + pit_init(frequency); +} + +void timer_irq_handler(void) { ticks++; } + +uint32_t timer_get_ticks(void) { return ticks; } + +uint32_t timer_get_seconds(void) { return ticks / timer_frequency; } + +uint32_t timer_get_frequency(void) { return timer_frequency; } + +void timer_sleep_m(uint32_t milliseconds) { + uint32_t start = timer_get_ticks(); + uint32_t wait_ticks = ((uint32_t)milliseconds * timer_frequency) / 1000; + + while (timer_get_ticks() - start < wait_ticks) { + } +} + +void timer_sleep_s(uint32_t seconds) { timer_sleep_m(seconds * 1000); } + +void timer_sleep(float seconds) { timer_sleep_m((uint32_t)(seconds * 1000)); } \ No newline at end of file From ab86e07d4a0aa1a70fe8fd6e53f6bb3034b946a5 Mon Sep 17 00:00:00 2001 From: Ox03bb Date: Fri, 11 Sep 2026 01:46:12 +0100 Subject: [PATCH 6/6] complite timer --- src/kernel/kernel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index a907122..775cd3c 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -30,14 +30,14 @@ void kernel_main() { vga_log_info("[", "init", "] pit and timer"); pic_clear_mask(0); timer_init(1000); // 1000 Hz + sti(); for (int i = 0; i < 53; i++) { vga_print("."); timer_sleep(0.02); } - - vga_print_at_end_c("... Ok\n", GREEN); + vga_print_at_end_c("... Ok\n", GREEN); // timer for (;;) { asm volatile("hlt");