4 * @brief A simple timer implementation based on APIC with adjustable frequency
5 * and subscribable "timerlets"
9 * @copyright Copyright (c) 2022
13 #include <lunaix/mm/cake.h>
14 #include <lunaix/mm/valloc.h>
15 #include <lunaix/sched.h>
16 #include <lunaix/spike.h>
17 #include <lunaix/syslog.h>
18 #include <lunaix/timer.h>
19 #include <lunaix/pcontext.h>
21 #include <hal/hwtimer.h>
28 static volatile struct lx_timer_context* timer_ctx = NULL;
30 static volatile u32_t sched_ticks = 0;
31 static volatile u32_t sched_ticks_counter = 0;
33 static struct cake_pile* timer_pile;
38 timer_pile = cake_new_pile("timer", sizeof(struct lx_timer), 1, 0);
40 (struct lx_timer_context*)valloc(sizeof(struct lx_timer_context));
42 assert_msg(timer_ctx, "Fail to initialize timer contex");
44 timer_ctx->active_timers = (struct lx_timer*)cake_grab(timer_pile);
45 llist_init_head(&timer_ctx->active_timers->link);
53 hwtimer_init(SYS_TIMER_FREQUENCY_HZ, timer_update);
55 timer_ctx->base_frequency = hwtimer_base_frequency();
57 sched_ticks = (SYS_TIMER_FREQUENCY_HZ * SCHED_TIME_SLICE) / 1000;
58 sched_ticks_counter = 0;
62 timer_run_second(u32_t second,
63 void (*callback)(void*),
67 ticks_t t = hwtimer_to_ticks(second, TIME_SEC);
68 return timer_run(t, callback, payload, flags);
72 timer_run_ms(u32_t millisecond,
73 void (*callback)(void*),
77 ticks_t t = hwtimer_to_ticks(millisecond, TIME_MS);
78 return timer_run(t, callback, payload, flags);
82 timer_run(ticks_t ticks, void (*callback)(void*), void* payload, u8_t flags)
84 struct lx_timer* timer = (struct lx_timer*)cake_grab(timer_pile);
89 timer->callback = callback;
90 timer->counter = ticks;
91 timer->deadline = ticks;
92 timer->payload = payload;
95 llist_append(&timer_ctx->active_timers->link, &timer->link);
103 struct lx_timer *pos, *n;
104 struct lx_timer* timer_list_head = timer_ctx->active_timers;
106 llist_for_each(pos, n, &timer_list_head->link, link)
108 if (--(pos->counter)) {
112 pos->callback ? pos->callback(pos->payload) : 1;
114 if ((pos->flags & TIMER_MODE_PERIODIC)) {
115 pos->counter = pos->deadline;
117 llist_delete(&pos->link);
118 cake_release(timer_pile, pos);
122 sched_ticks_counter++;
124 if (sched_ticks_counter >= sched_ticks) {
125 sched_ticks_counter = 0;
130 struct lx_timer_context*
133 return (struct lx_timer_context*)timer_ctx;