X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/99f2ed669601a61f4f0210e0b481ff877cd9bea7..35a7d633d3f16c1e0539af6ca5d8e7482926cd93:/lunaix-os/hal/timer/timer_device.c diff --git a/lunaix-os/hal/timer/timer_device.c b/lunaix-os/hal/timer/timer_device.c index 1db8147..085f6bd 100644 --- a/lunaix-os/hal/timer/timer_device.c +++ b/lunaix-os/hal/timer/timer_device.c @@ -3,26 +3,23 @@ #include -const struct hwtimer* systimer; +const struct hwtimer_pot* systimer = NULL; -ticks_t -hwtimer_base_frequency() -{ - assert(systimer); - return systimer->base_freq; -} +static struct device_alias* timer_alias; +static DEFINE_LLIST(timer_devices); ticks_t hwtimer_current_systicks() { assert(systimer); - return systimer->systicks(); + return systimer->systick_raw; } ticks_t hwtimer_to_ticks(u32_t value, int unit) { assert(systimer); + // in case system frequency is less than 1000Hz if (unit != TIME_MS) { return systimer->running_freq * unit * value; @@ -33,34 +30,66 @@ hwtimer_to_ticks(u32_t value, int unit) return freq_ms * value; } -static int -__hwtimer_ioctl(struct device* dev, u32_t req, va_list args) +static struct hwtimer_pot* +__select_timer() { - struct hwtimer* hwt = (struct hwtimer*)dev->underlay; - switch (req) { - case TIMERIO_GETINFO: - // TODO - break; - - default: - break; + struct hwtimer_pot *pos, *n, *sel = NULL; + + llist_for_each(pos, n, &timer_devices, timers) + { + if (unlikely(!sel)) { + sel = pos; + continue; + } + + if (sel->precedence < pos->precedence) { + sel = pos; + } } - return 0; + + return sel; } void hwtimer_init(u32_t hertz, void* tick_callback) { - struct hwtimer* hwt_ctx = select_platform_timer(); + struct hwtimer_pot* selected; + struct device* time_dev; + + selected = __select_timer(); - hwt_ctx->init(hwt_ctx, hertz, tick_callback); - hwt_ctx->running_freq = hertz; + assert(selected); + systimer = selected; - systimer = hwt_ctx; + selected->callback = tick_callback; + selected->running_freq = hertz; + + selected->ops->calibrate(selected, hertz); + + time_dev = potens_dev(selected); + timer_alias = device_addalias(NULL, dev_meta(time_dev), "timer"); +} + + +struct hwtimer_pot* +hwtimer_attach_potens(struct device* dev, int precedence, + struct hwtimer_pot_ops* ops) +{ + struct hwtimer_pot* hwpot; + struct potens_meta* pot; + + if (!potens_check_unique(dev, potens(HWTIMER))) + { + return NULL; + } - struct device* timerdev = device_allocsys(NULL, hwt_ctx); + hwpot = new_potens(potens(HWTIMER), struct hwtimer_pot); + hwpot->ops = ops; + hwpot->precedence = precedence; + + device_grant_potens(dev, potens_meta(hwpot)); - timerdev->ops.exec_cmd = __hwtimer_ioctl; + llist_append(&timer_devices, &hwpot->timers); - register_device(timerdev, &hwt_ctx->class, hwt_ctx->name); + return hwpot; } \ No newline at end of file