[INTERRUPTS] Enabling the APIC timer
This commit is contained in:
parent
9ae3b014da
commit
d3d065b2e2
@ -11,6 +11,7 @@
|
||||
#include <apic.h>
|
||||
#include <sse.h>
|
||||
#include <timer.h>
|
||||
#include <pit.h>
|
||||
|
||||
void thread_function()
|
||||
{
|
||||
@ -18,6 +19,7 @@ void thread_function()
|
||||
{
|
||||
debug((char *)0x10000);
|
||||
schedule();
|
||||
pit_delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
void apic_init();
|
||||
void apic_interrupt(uint8_t destination, uint8_t level, uint8_t type, uint8_t vector);
|
||||
void apic_ack();
|
||||
void apic_timer(uint64_t us);
|
||||
void apic_timer_stop();
|
||||
#define APIC_INT_LEVEL_ASSERT 0x1
|
||||
#define APIC_INT_LEVEL_DEASSERT 0x0
|
||||
#define APIC_INT_TYPE_FIXED 0x0
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <apic.h>
|
||||
#include <int.h>
|
||||
#include <pit.h>
|
||||
#include <msr.h>
|
||||
#include <debug.h>
|
||||
#include <mem.h>
|
||||
@ -25,9 +25,28 @@
|
||||
|
||||
#define SPURIOUS_LVT_ENABLED 0x100
|
||||
|
||||
#define TIMER_LVT_ONESHOT 0x00000
|
||||
#define TIMER_LVT_PERIODIC 0x20000
|
||||
#define TIMER_LVT_DEADLINE 0x40000
|
||||
|
||||
#define R_TIMER_INIT 0x380
|
||||
#define R_TIMER_CURR 0x390
|
||||
#define R_TIMER_DIV 0x3E0
|
||||
#define TIMER_DIV1 0xB
|
||||
#define TIMER_DIV2 0x0
|
||||
#define TIMER_DIV4 0x1
|
||||
#define TIMER_DIV8 0x2
|
||||
#define TIMER_DIV16 0x3
|
||||
#define TIMER_DIV32 0x8
|
||||
#define TIMER_DIV64 0x9
|
||||
#define TIMER_DIV128 0xA
|
||||
|
||||
|
||||
#define APIC(reg) apic[reg/4]
|
||||
uint32_t volatile *apic = P2V(APIC_BASE);
|
||||
|
||||
uint32_t apic_ticks_per_us;
|
||||
|
||||
void apic_interrupt(uint8_t destination, uint8_t level, uint8_t type, uint8_t vector)
|
||||
{
|
||||
uint64_t data = ((level & 0x1)<<14) | ((type & 0x7)<<8) | vector;
|
||||
@ -39,6 +58,36 @@ void apic_ack()
|
||||
{
|
||||
APIC(R_EOI) = 0;
|
||||
}
|
||||
registers_t *apic_timer_handler(registers_t *r)
|
||||
{
|
||||
// APIC timer timeout occurred
|
||||
APIC(R_EOI) = 0;
|
||||
debug_putch('-');
|
||||
apic_timer(1000000);
|
||||
return r;
|
||||
}
|
||||
void apic_timer(uint64_t us)
|
||||
{
|
||||
APIC(R_TIMER_DIV) = TIMER_DIV1;
|
||||
APIC(R_TIMER_INIT) = us*apic_ticks_per_us;
|
||||
APIC(R_TIMER_LVT) = TIMER_LVT_ONESHOT | INT_APIC_TIMER;
|
||||
}
|
||||
void apic_timer_stop()
|
||||
{
|
||||
APIC(R_TIMER_LVT) = LVT_MASKED | INT_APIC_TIMER;
|
||||
}
|
||||
|
||||
uint32_t calibrate_apic_timer(uint32_t resolution)
|
||||
{
|
||||
// Use the PIT to calibrate the APIC timer
|
||||
// Returns number of apic timer ticks per ms
|
||||
APIC(R_TIMER_DIV) = TIMER_DIV1;
|
||||
APIC(R_TIMER_LVT) = LVT_MASKED | INT_APIC_TIMER;
|
||||
APIC(R_TIMER_INIT) = 0xFFFFFFFF;
|
||||
pit_delay(resolution);
|
||||
uint32_t ticks = APIC(R_TIMER_CURR);
|
||||
return (0xFFFFFFFF-ticks)/resolution/1000;
|
||||
}
|
||||
|
||||
void apic_init()
|
||||
{
|
||||
@ -55,4 +104,14 @@ void apic_init()
|
||||
|
||||
APIC(R_SPURIOUS) = SPURIOUS_LVT_ENABLED | INT_APIC_SPUR;
|
||||
APIC(R_EOI) = 0;
|
||||
|
||||
// Calibrate timer
|
||||
apic_ticks_per_us = calibrate_apic_timer(100);
|
||||
debug_info("APIC - ticks per us:%d\n", apic_ticks_per_us);
|
||||
debug(" corresponds to processor frequency: %d MHz\n", apic_ticks_per_us);
|
||||
|
||||
// Register temporary timer handler to go off every 10 ms
|
||||
register_int_handler(INT_APIC_TIMER, apic_timer_handler);
|
||||
|
||||
apic_timer(1000000);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user