timer/scheduler working
This commit is contained in:
@@ -68,7 +68,10 @@ enum Vector {
|
||||
|
||||
// Interrupts
|
||||
KEYBOARD=32,
|
||||
PANIC=33
|
||||
PANIC=33,
|
||||
|
||||
TIMER = 251,
|
||||
ASSASSIN = 252,
|
||||
};
|
||||
constexpr size_t VECTORS = 256;
|
||||
|
||||
|
||||
@@ -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<uint64_t>(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<uint32_t>(timer_ticks), divisor, Core::Interrupt::TIMER, true, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t interval() { return 0; }
|
||||
uint32_t interval() {
|
||||
uint32_t timer_ticks = LAPIC::read(TIMER_INITIAL_COUNTER);
|
||||
uint32_t divisor = fromClockDiv(LAPIC::read(TIMER_DIVIDE_CONFIGURATION));
|
||||
|
||||
void activate() {}
|
||||
uint64_t us = (static_cast<uint64_t>(timer_ticks) * divisor * 1000ULL) / static_cast<uint64_t>(ticks());
|
||||
return static_cast<uint32_t>(us);
|
||||
}
|
||||
|
||||
void setMasked(bool masked) { (void)masked; }
|
||||
void activate() {
|
||||
uint32_t timer_ticks = LAPIC::read(TIMER_INITIAL_COUNTER);
|
||||
// Disable Counter to avoid spouriose interrupts.
|
||||
LAPIC::write(TIMER_INITIAL_COUNTER, 0);
|
||||
|
||||
// Activate Timer interrupts.
|
||||
setMasked(false);
|
||||
|
||||
// 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
18
main.cc
18
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<int>(LAPIC::getID()) << endl << flush;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user