Fixed timer calibration

This commit is contained in:
Alex 2022-10-23 03:47:38 +03:00
parent 782b3fa78a
commit 7918999799
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
3 changed files with 87 additions and 37 deletions

View File

@ -208,6 +208,14 @@ namespace APIC
else if (madt->nmi[i]->lint == 1) else if (madt->nmi[i]->lint == 1)
this->Write(APIC_LINT1, nmi); this->Write(APIC_LINT1, nmi);
} }
// Disable PIT
outb(0x43, 0x28);
outb(0x40, 0x0);
// Disable PIC
outb(0x21, 0xFF);
outb(0xA1, 0xFF);
} }
APIC::~APIC() APIC::~APIC()
@ -224,62 +232,84 @@ namespace APIC
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds) void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
{ {
this->lapic->Write(APIC_TDCR, 0x03); LVTTimer timer = {.raw = 0};
LVTTimer timer = {0, 0, 0, 0, 0, 0, 0};
timer.Vector = Vector; timer.Vector = Vector;
timer.TimerMode = 0; timer.TimerMode = 0;
this->lapic->Write(APIC_TDCR, 0x0);
this->lapic->Write(APIC_TICR, Ticks * Miliseconds);
this->lapic->Write(APIC_TIMER, timer.raw); this->lapic->Write(APIC_TIMER, timer.raw);
this->lapic->Write(APIC_TICR, (TicksIn10ms / 10) * Miliseconds);
} }
Timer::Timer(APIC *apic) : Interrupts::Handler(IRQ0) Timer::Timer(APIC *apic) : Interrupts::Handler(IRQ0)
{ {
trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID);
this->lapic = apic; this->lapic = apic;
this->lapic->Write(APIC_TDCR, 0x3); trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID);
int Count = 10000; /* µs */ // Setup the spurrious interrupt vector
int Ticks = 1193180 / (Count / 100); APICSpurious Spurious = {.raw = this->lapic->Read(APIC_SVR)};
Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
int IOIn = inb(0x61); Spurious.Software = 1;
IOIn = (IOIn & 0xFD) | 1; this->lapic->Write(APIC_SVR, Spurious.raw);
outb(0x61, IOIn);
outb(0x43, 178);
outb(0x40, Ticks & 0xff);
inb(0x60);
outb(0x40, Ticks >> 8);
this->lapic->Write(APIC_TDCR, 0x0);
this->lapic->Write(APIC_TICR, 0xFFFFFFFF); this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
IOIn = inb(0x61); // After PIT sleep is completed. Mask the timer.
IOIn = (IOIn & 0xFC); LVTTimer masktimer = {.raw = 0x10000};
outb(0x61, IOIn);
IOIn |= 1;
outb(0x61, IOIn);
uint32_t Loop = 0;
while ((inb(0x61) & 0x20) != 0)
++Loop;
this->lapic->Write(APIC_TIMER, 0x10000); // // PIT Config
// int Count = 10000; /* µs */
// int Ticks = 1193180 / (Count / 100);
outb(0x43, 0x28); // // https://wiki.osdev.org/Programmable_Interval_Timer#I.2FO_Ports
outb(0x40, 0x0);
outb(0x21, 0xFF); // // PIT Prepare
outb(0xA1, 0xFF); // int IOIn = inb(0x61);
// IOIn = (IOIn & 0xFD) | 1;
// outb(0x61, IOIn);
// outb(0x43, 178);
// outb(0x40, Ticks & 0xff);
// inb(0x60);
// outb(0x40, Ticks >> 8);
TicksIn10ms = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR); // // PIT Start
// IOIn = inb(0x61);
// IOIn = (IOIn & 0xFC);
// outb(0x61, IOIn);
// IOIn |= 1;
// outb(0x61, IOIn);
// uint32_t Loop = 0;
// while ((inb(0x61) & 0x20) != 0)
// ++Loop;
LVTTimer timer = {0, 0, 0, 0, 0, 0, 0}; // 10000ms
for (int i = 0; i < 10000; i++)
inb(0x80); // 1µs
// Mask the timer
this->lapic->Write(APIC_TIMER, masktimer.raw);
// // Disable the PIT
// outb(0x43, 0x28);
// outb(0x40, 0x0);
// outb(0x21, 0xFF);
// outb(0xA1, 0xFF);
Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR);
// Config for IRQ0 timer
LVTTimer timer = {.raw = 0};
timer.Vector = IRQ0; timer.Vector = IRQ0;
timer.Mask = 0; timer.Mask = 0;
timer.TimerMode = 1; timer.TimerMode = 1;
// Initialize APIC timer
this->lapic->Write(APIC_TDCR, 0x0);
this->lapic->Write(APIC_TICR, Ticks);
this->lapic->Write(APIC_TIMER, timer.raw); this->lapic->Write(APIC_TIMER, timer.raw);
this->lapic->Write(APIC_TDCR, 0x3); trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
this->lapic->Write(APIC_TICR, TicksIn10ms / 10); KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
trace("APIC Timer (CPU %d): %d ticks in 10ms", GetCurrentCPU()->ID, TicksIn10ms / 10);
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks in 10ms", TicksIn10ms / 10);
} }
Timer::~Timer() Timer::~Timer()

View File

@ -86,6 +86,26 @@ namespace APIC
uint64_t raw; uint64_t raw;
} __attribute__((packed)) LVTTimer; } __attribute__((packed)) LVTTimer;
typedef union
{
struct
{
/** @brief Spurious Vector */
uint64_t Vector : 8;
/** @brief Enable or disable APIC software */
uint64_t Software : 1;
/** @brief Focus Processor Checking */
uint64_t FocusProcessorChecking : 1;
/** @brief Reserved */
uint64_t Reserved : 2;
/** @brief Disable EOI Broadcast */
uint64_t DisableEOIBroadcast : 1;
/** @brief Reserved */
uint64_t Reserved1 : 19;
};
uint64_t raw;
} __attribute__((packed)) APICSpurious;
typedef union typedef union
{ {
struct struct
@ -123,11 +143,11 @@ namespace APIC
{ {
private: private:
APIC *lapic; APIC *lapic;
uint64_t TicksIn10ms = 0; uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x64::TrapFrame *Frame); void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public: public:
uint64_t GetTicksIn10ms() { return TicksIn10ms; } uint64_t GetTicks() { return Ticks; }
void OneShot(uint32_t Vector, uint64_t Miliseconds); void OneShot(uint32_t Vector, uint64_t Miliseconds);
Timer(APIC *apic); Timer(APIC *apic);
~Timer(); ~Timer();

View File

@ -13,7 +13,7 @@
#elif defined(__aarch64__) #elif defined(__aarch64__)
#endif #endif
// #define DEBUG_SCHEDULER 1 #define DEBUG_SCHEDULER 1
#ifdef DEBUG_SCHEDULER #ifdef DEBUG_SCHEDULER
#define schedbg(m, ...) debug(m, ##__VA_ARGS__) #define schedbg(m, ...) debug(m, ##__VA_ARGS__)