X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/8b8f49b713d64065775fe538232f8639083601bd..d1b1c8d9119229dbeed06cd252917e54a1cb77f6:/lunaix-os/hal/timer/apic_timer.c diff --git a/lunaix-os/hal/timer/apic_timer.c b/lunaix-os/hal/timer/apic_timer.c deleted file mode 100644 index e195f34..0000000 --- a/lunaix-os/hal/timer/apic_timer.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include - -#include - -LOG_MODULE("APIC_TIMER") - -#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector) -#define APIC_BASETICKS 0x100000 - -// Don't optimize them! Took me an half hour to figure that out... - -static volatile u8_t apic_timer_done = 0; -static volatile ticks_t base_freq = 0; -static volatile ticks_t systicks = 0; - -static timer_tick_cb tick_cb = NULL; - -static void -temp_intr_routine_apic_timer(const isr_param* param) -{ - apic_timer_done = 1; -} - -static void -apic_timer_tick_isr(const isr_param* param) -{ - systicks++; - - if (likely((ptr_t)tick_cb)) { - tick_cb(); - } -} - -static int -apic_timer_check(struct hwtimer* hwt) -{ - // TODO check whether apic timer is supported - return 1; -} - -static ticks_t -apic_get_systicks() -{ - return systicks; -} - -static ticks_t -apic_get_base_freq() -{ - return base_freq; -} - -void -apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb) -{ - ticks_t frequency = hertz; - tick_cb = timer_cb; - - cpu_disable_interrupt(); - - // Setup APIC timer - - // Remap the IRQ 8 (rtc timer's vector) to RTC_TIMER_IV in ioapic - // (Remarks IRQ 8 is pin INTIN8) - // See IBM PC/AT Technical Reference 1-10 for old RTC IRQ - // See Intel's Multiprocessor Specification for IRQ - IOAPIC INTIN - // mapping config. - - // grab ourselves these irq numbers - u32_t iv_timer = isrm_ivexalloc(temp_intr_routine_apic_timer); - - // Setup a one-shot timer, we will use this to measure the bus speed. So we - // can then calibrate apic timer to work at *nearly* accurate hz - apic_write_reg(APIC_TIMER_LVT, - LVT_ENTRY_TIMER(iv_timer, LVT_TIMER_ONESHOT)); - - // Set divider to 64 - apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64); - - /* - Timer calibration process - measure the APIC timer base frequency - - step 1: setup a temporary isr for RTC timer which trigger at each tick - (1024Hz) - step 2: setup a temporary isr for #APIC_TIMER_IV - step 3: setup the divider, APIC_TIMER_DCR - step 4: Startup RTC timer - step 5: Write a large value, v, to APIC_TIMER_ICR to start APIC timer - (this must be followed immediately after step 4) step 6: issue a write to - EOI and clean up. - - When the APIC ICR counting down to 0 #APIC_TIMER_IV triggered, save the - rtc timer's counter, k, and disable RTC timer immediately (although the - RTC interrupts should be blocked by local APIC as we are currently busy - on handling #APIC_TIMER_IV) - - So the apic timer frequency F_apic in Hz can be calculate as - v / F_apic = k / 1024 - => F_apic = v / k * 1024 - - */ - -#ifdef __LUNAIXOS_DEBUG__ - if (frequency < 1000) { - kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy."); - } -#endif - - apic_timer_done = 0; - - primary_rtc->cls_mask(primary_rtc); - apic_write_reg(APIC_TIMER_ICR, APIC_BASETICKS); // start APIC timer - - // enable interrupt, just for our RTC start ticking! - cpu_enable_interrupt(); - - wait_until(apic_timer_done); - - cpu_disable_interrupt(); - - primary_rtc->set_mask(primary_rtc); - - base_freq = primary_rtc->get_counts(primary_rtc); - base_freq = APIC_BASETICKS / base_freq * primary_rtc->base_freq; - - assert_msg(base_freq, "Fail to initialize timer (NOFREQ)"); - - kprintf(KINFO "hw: %u Hz; os: %u Hz\n", base_freq, frequency); - - // cleanup - isrm_ivfree(iv_timer); - - apic_write_reg( - APIC_TIMER_LVT, - LVT_ENTRY_TIMER(isrm_ivexalloc(apic_timer_tick_isr), LVT_TIMER_PERIODIC)); - - timer->base_freq = base_freq; - - ticks_t tphz = base_freq / frequency; - apic_write_reg(APIC_TIMER_ICR, tphz); -} - -struct hwtimer* -apic_hwtimer_context() -{ - static struct hwtimer apic_hwt = { - .name = "apic_timer", - .class = DEVCLASSV(DEVIF_SOC, DEVFN_TIME, DEV_TIMER, DEV_TIMER_APIC), - .init = apic_timer_init, - .supported = apic_timer_check, - .systicks = apic_get_systicks - }; - - return &apic_hwt; -}