#include <hal/apic_timer.h>
-#include <hal/hwrtc.h>
#include <hal/hwtimer.h>
+#include <lunaix/clock.h>
#include <lunaix/compiler.h>
#include <lunaix/isrm.h>
#include <lunaix/spike.h>
LOG_MODULE("APIC_TIMER")
#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
-#define APIC_CALIBRATION_CONST 0x100000
+#define APIC_BASETICKS 0x100000
// Don't optimize them! Took me an half hour to figure that out...
-static volatile u32_t rtc_counter = 0;
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
-__rtc_on_tick_cb(struct hwrtc* param)
-{
- rtc_counter++;
-}
-
static void
temp_intr_routine_apic_timer(const isr_param* param)
{
- base_freq = APIC_CALIBRATION_CONST / rtc_counter * current_rtc->base_freq;
apic_timer_done = 1;
}
}
static int
-apic_timer_check(struct hwtimer_context* hwt)
+apic_timer_check(struct hwtimer* hwt)
{
// TODO check whether apic timer is supported
return 1;
}
void
-apic_timer_init(struct hwtimer_context* timer,
- u32_t hertz,
- timer_tick_cb timer_cb)
+apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb)
{
ticks_t frequency = hertz;
tick_cb = timer_cb;
#ifdef __LUNAIXOS_DEBUG__
if (frequency < 1000) {
- kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy.");
+ WARN("Frequency too low. Millisecond timer might be dodgy.");
}
#endif
- rtc_counter = 0;
apic_timer_done = 0;
- current_rtc->do_ticking(current_rtc, __rtc_on_tick_cb);
- apic_write_reg(APIC_TIMER_ICR, APIC_CALIBRATION_CONST); // start APIC timer
+ sysrtc->cls_mask(sysrtc);
+ 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);
- current_rtc->end_ticking(current_rtc);
-
cpu_disable_interrupt();
+ sysrtc->set_mask(sysrtc);
+
+ base_freq = sysrtc->get_counts(sysrtc);
+ base_freq = APIC_BASETICKS / base_freq * sysrtc->base_freq;
+
assert_msg(base_freq, "Fail to initialize timer (NOFREQ)");
- kprintf(KINFO "hw: %u Hz; os: %u Hz\n", base_freq, frequency);
+ kprintf("hw: %u Hz; os: %u Hz", base_freq, frequency);
// cleanup
isrm_ivfree(iv_timer);
+ ticks_t tphz = base_freq / frequency;
+ timer->base_freq = base_freq;
+ apic_write_reg(APIC_TIMER_ICR, tphz);
+
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_context*
+struct hwtimer*
apic_hwtimer_context()
{
- static struct hwtimer_context apic_hwt = { .name = "apic_timer",
- .init = apic_timer_init,
- .supported = apic_timer_check,
- .systicks = apic_get_systicks };
+ 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;
}