From bc0a94b70578648aa97861e09240eab6086a87bd Mon Sep 17 00:00:00 2001 From: Eggert Jung Date: Tue, 8 Jul 2025 01:11:22 +0200 Subject: [PATCH] timer/scheduler working --- arch/core_interrupt.h | 5 ++- arch/lapic_timer.cc | 116 ++++++++++++++++++++++++++++++++++++++++++------- interrupt/epilogues.cc | 21 ++++++++- interrupt/handlers.cc | 13 +++--- main.cc | 18 ++++---- user/app1/appl.cc | 8 ++-- 6 files changed, 143 insertions(+), 38 deletions(-) diff --git a/arch/core_interrupt.h b/arch/core_interrupt.h index b3a9ec6..4ed6541 100644 --- a/arch/core_interrupt.h +++ b/arch/core_interrupt.h @@ -68,7 +68,10 @@ enum Vector { // Interrupts KEYBOARD=32, - PANIC=33 + PANIC=33, + + TIMER = 251, + ASSASSIN = 252, }; constexpr size_t VECTORS = 256; diff --git a/arch/lapic_timer.cc b/arch/lapic_timer.cc index 2597cd1..694c42b 100644 --- a/arch/lapic_timer.cc +++ b/arch/lapic_timer.cc @@ -1,5 +1,9 @@ #include "lapic.h" #include "lapic_registers.h" +#include "core.h" +#include "pit.h" + +#include "../debug/output.h" namespace LAPIC { namespace Timer { @@ -56,36 +60,118 @@ static const Register div_masks[] = { * \param div Divider, must be power of two: 1, 2, 4, 8, 16, 32, 64, 128 * \return Bit mask for LAPIC::setTimer() or `0xff` if `div` is invalid. */ -Register getClockDiv(uint8_t div) { - (void)div; - return 0; +static Register getClockDiv(uint8_t div) { + switch (div) { + case 1: return div_masks[0]; + case 2: return div_masks[1]; + case 4: return div_masks[2]; + case 8: return div_masks[3]; + case 16: return div_masks[4]; + case 32: return div_masks[5]; + case 64: return div_masks[6]; + case 128: return div_masks[7]; + default : return 0xff; + } +} +/*! \brief Calculate the LAPIC-timer divider for the bit mask. + * \param div_mask The bit mask, must be one of: 0xb, 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xa + * \return LAPIC-timer divider or `0xff` if `div_mask` is invalid. + */ +static uint8_t fromClockDiv(Register div_mask) { + if (div_mask == div_masks[0]) return 1; + if (div_mask == div_masks[1]) return 2; + if (div_mask == div_masks[2]) return 4; + if (div_mask == div_masks[3]) return 8; + if (div_mask == div_masks[4]) return 16; + if (div_mask == div_masks[5]) return 32; + if (div_mask == div_masks[6]) return 64; + if (div_mask == div_masks[7]) return 128; + return 0xff; } + uint32_t ticks(void) { - uint32_t ticks = 0; // ticks per millisecond - // Calculation (Assignment 5) + static uint32_t ticks = 0; // ticks per millisecond + if (ticks != 0) return ticks; + + // Prepare Counter + LAPIC::Timer::set(0, 1, 0, false, true); + + // Set timer for 10ms + PIT::set(10 * 1000); + // Start LAPIC-Timer + LAPIC::write(TIMER_INITIAL_COUNTER, UINT32_MAX); + PIT::waitForTimeout(); + // Get final Count + uint32_t counter = LAPIC::read(TIMER_CURRENT_COUNTER); + // Disable LAPIC-Timer + LAPIC::write(TIMER_INITIAL_COUNTER, 0); + // Calculate tick count. + ticks = (UINT32_MAX - counter) / 10; + + DBG << "LAPIC-Timer calibration using PIT" << endl; return ticks; } void set(uint32_t counter, uint8_t divide, uint8_t vector, bool periodic, bool masked) { - (void)counter; - (void)divide; - (void)vector; - (void)periodic; - (void)masked; + if (divide == 0 || (divide & (divide - 1)) != 0) { + // Not a power of 2 + return; + } + + ControlRegister tcr; + tcr.vector = Core::Interrupt::Vector::TIMER; + tcr.timer_mode = periodic ? PERIODIC : ONE_SHOT; + tcr.masked = masked ? MASKED : NOT_MASKED; + LAPIC::write(TIMER_CONTROL, tcr.value); + + LAPIC::write(TIMER_DIVIDE_CONFIGURATION, getClockDiv(divide)); + LAPIC::write(TIMER_INITIAL_COUNTER, counter); } bool setup(uint32_t us) { - (void)us; - return false; + uint64_t timer_ticks = (static_cast(ticks()) * us) / 1000ULL; + + uint8_t divisor = 1; + while (timer_ticks > UINT32_MAX) { + // While timer_ticks is to large to fit in 32bits. + timer_ticks >>= 1; + divisor <<= 1; + } + if (divisor > 128) + return false; // Timer interval is to large. + + // Setup Masked interrupts to effectively disable the timer. + set(static_cast(timer_ticks), divisor, Core::Interrupt::TIMER, true, true); + return true; +} + +uint32_t interval() { + uint32_t timer_ticks = LAPIC::read(TIMER_INITIAL_COUNTER); + uint32_t divisor = fromClockDiv(LAPIC::read(TIMER_DIVIDE_CONFIGURATION)); + + uint64_t us = (static_cast(timer_ticks) * divisor * 1000ULL) / static_cast(ticks()); + return static_cast(us); } -uint32_t interval() { return 0; } +void activate() { + uint32_t timer_ticks = LAPIC::read(TIMER_INITIAL_COUNTER); + // Disable Counter to avoid spouriose interrupts. + LAPIC::write(TIMER_INITIAL_COUNTER, 0); -void activate() {} + // Activate Timer interrupts. + setMasked(false); -void setMasked(bool masked) { (void)masked; } + // enable counter with correct value. + LAPIC::write(TIMER_INITIAL_COUNTER, timer_ticks); +} +void setMasked(bool masked) { + ControlRegister tcr; + tcr.value = LAPIC::read(TIMER_CONTROL); + tcr.masked = masked ? MASKED : NOT_MASKED; + LAPIC::write(TIMER_CONTROL, tcr.value); +} } // namespace Timer } // namespace LAPIC diff --git a/interrupt/epilogues.cc b/interrupt/epilogues.cc index 4572b75..b4ba0ce 100644 --- a/interrupt/epilogues.cc +++ b/interrupt/epilogues.cc @@ -2,8 +2,10 @@ #include "../debug/output.h" #include "guard.h" +#include "../thread/scheduler.h" extern Key kout_key; +extern Scheduler sch; namespace Epilogues { @@ -13,7 +15,22 @@ void keyboard(Vault& g) { } -void timer(Vault& g) { (void)g; } +void timer(Vault& g) { + static int counter = 0; + int x, y; + if(Core::getID() == 0) { + g.kout.getPos(x, y); + g.kout.setPos(65U, 0U); + g.kout << counter++ << " " << flush; + g.kout.setPos(x, y); + } -void assassin(Vault& g) { (void)g; } + sch.resume(true); +} + +void assassin(Vault& g) { + if (sch.active()->kill_flag) { + sch.exit(); + } +} }; // namespace Epilogues diff --git a/interrupt/handlers.cc b/interrupt/handlers.cc index 8ef2a84..6a4e1e4 100644 --- a/interrupt/handlers.cc +++ b/interrupt/handlers.cc @@ -71,9 +71,6 @@ enum PAGE_FAULT_ERROR { kernelpanic("Page fault!"); } -extern Ticketlock koutlock; -extern Vault keyboard_vault; - void handle_keyboard() { //Key key = Key(); if (PS2Controller::fetch(kout_key)) { @@ -81,9 +78,6 @@ void handle_keyboard() { if (kout_key.ctrl() && kout_key.alt() && kout_key.scancode == Key::KEY_DEL) System::reboot(); Guard::relay(Epilogues::keyboard); - //koutlock.lock(); - //kout << key.ascii() << endl << flush ; - //koutlock.unlock(); } else LAPIC::endOfInterrupt(); @@ -97,10 +91,14 @@ void handle_keyboard() { [[gnu::interrupt]] void handle_timer(InterruptContext *context) { (void)context; + LAPIC::endOfInterrupt(); + Guard::relay(Epilogues::timer); } [[gnu::interrupt]] void handle_assassin(InterruptContext *context) { (void)context; + LAPIC::endOfInterrupt(); + Guard::relay(Epilogues::assassin); } [[gnu::interrupt]] void handle_wakeup(InterruptContext *context) { (void)context; @@ -120,6 +118,9 @@ void initInterruptHandlers() { IDT::set(Core::Interrupt::Vector::PAGE_FAULT, IDT::InterruptDescriptor::ReturningWithError(handle_page_fault)); + IDT::set(Core::Interrupt::Vector::TIMER, + IDT::InterruptDescriptor::Returning(handle_timer)); + // TODO: Add more handlers here IDT::set(Core::Interrupt::Vector::KEYBOARD, IDT::InterruptDescriptor::Returning(handle_keyboard_asm)); diff --git a/main.cc b/main.cc index 8cfb119..f10e7f0 100644 --- a/main.cc +++ b/main.cc @@ -71,17 +71,12 @@ OutputStream* copyout[Core::MAX]{ unsigned int testx, testy; -uint8_t test1_stack[1024]; -uint8_t test2_stack[1024]; -uint8_t test3_stack[1024]; -uint8_t test4_stack[1024]; -uint8_t test5_stack[1024]; +#define APP_NUM 7 -Application application1 = Application(&test1_stack[sizeof(test1_stack)-1]); -Application application2 = Application(&test2_stack[sizeof(test2_stack)-1]); -Application application3 = Application(&test3_stack[sizeof(test3_stack)-1]); -Application application4 = Application(&test4_stack[sizeof(test4_stack)-1]); -Application application5 = Application(&test5_stack[sizeof(test5_stack)-1]); +uint8_t app_stack[1024][APP_NUM]; +Application application[APP_NUM]; + +application[0] = Application(&app_stack[sizeof(app_stack[0])-1]); // Main function @@ -105,6 +100,8 @@ extern "C" int main() { sch.ready(&application5); } + LAPIC::Timer::setup(1000000); + ApplicationProcessor::boot(); PS2Controller::init(); @@ -115,6 +112,7 @@ extern "C" int main() { Core::Interrupt::enable(); + LAPIC::Timer::activate(); PS2Controller::drainBuffer(); DBG << "Main CPU " << static_cast(LAPIC::getID()) << endl << flush; diff --git a/user/app1/appl.cc b/user/app1/appl.cc index 5511df2..3d045fe 100644 --- a/user/app1/appl.cc +++ b/user/app1/appl.cc @@ -58,10 +58,10 @@ void Application::action() { // NOLINT //activeWaitDelay(10000000); - { - Guarded g = Guard::enter(); - sch.resume(true); - } + //{ + // Guarded g = Guard::enter(); + // sch.resume(true); + //} if(cnt >= sizeof(text)-1) cnt=0;