#pragma once #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct rt_timer; struct rt_timer_command; void rt_timer_start(struct rt_timer *timer); bool rt_timer_trystart(struct rt_timer *timer); bool rt_timer_timedstart(struct rt_timer *timer, unsigned long block_ticks); void rt_timer_stop(struct rt_timer *timer); bool rt_timer_trystop(struct rt_timer *timer); bool rt_timer_timedstop(struct rt_timer *timer, unsigned long block_ticks); void rt_timer_change_period(struct rt_timer *timer, unsigned long period); bool rt_timer_trychange_period(struct rt_timer *timer, unsigned long period); bool rt_timer_timedchange_period(struct rt_timer *timer, unsigned long period, unsigned long block_ticks); void rt_timer_daemon(uintptr_t arg); #define RT_TIMER_QUEUE(name, depth) \ RT_QUEUE(name, struct rt_timer_command, depth) #define RT_TIMER_QUEUE_STATIC(name, depth) \ RT_QUEUE_STATIC(name, struct rt_timer_command, depth) #define RT_TIMER_TASK(queue, stack_size, priority, ...) \ RT_TASK_ARG(rt_timer_daemon, (uintptr_t)queue, stack_size, priority, \ __VA_ARGS__) union rt_timer_fn { void (*no_arg)(void); void (*with_arg)(uintptr_t); }; struct rt_timer { struct rt_list list; unsigned long tick; unsigned long period; const union rt_timer_fn fn; const uintptr_t arg; struct rt_queue *const queue; const bool has_arg; const bool periodic; }; #define RT_TIMER_INIT(name_, queue_, fn_, period_, periodic_) \ { \ .list = RT_LIST_INIT(name_.list), \ .tick = 0UL, \ .period = period_, \ .fn = {.no_arg = fn_}, \ .arg = 0, \ .queue = queue_, \ .has_arg = false, \ .periodic = periodic_, \ } #define RT_TIMER_INIT_ARG(name_, queue_, fn_, arg_, period_, periodic_) \ { \ .list = RT_LIST_INIT(name_.list), \ .tick = 0UL, \ .period = period_, \ .fn = {.with_arg = fn_}, \ .arg = arg_, \ .queue = queue_, \ .has_arg = true, \ .periodic = periodic_, \ } #define RT_TIMER_ONE_SHOT(name, queue, fn, period) \ struct rt_timer name = RT_TIMER_INIT(name, queue, fn, period, false) #define RT_TIMER_ONE_SHOT_ARG(name, queue, fn, arg, period) \ struct rt_timer name = \ RT_TIMER_INIT_ARG(name, queue, fn, arg, period, false) #define RT_TIMER_PERIODIC(name, queue, fn, period) \ struct rt_timer name = RT_TIMER_INIT(name, queue, fn, period, true) #define RT_TIMER_PERIODIC_ARG(name, queue, fn, arg, period) \ struct rt_timer name = RT_TIMER_INIT_ARG(name, queue, fn, arg, period, true) #define RT_TIMER_AUTOSTART(timer) \ __attribute__((constructor, used)) static void timer##_autostart(void) \ { \ rt_assert(rt_timer_trystart(&timer), "can't autostart timer"); \ } \ rt_static_assert(true, "require semicolon") enum rt_timer_op { RT_TIMER_OP_START, RT_TIMER_OP_STOP, RT_TIMER_OP_CHANGE_PERIOD, }; struct rt_timer_command { struct rt_timer *timer; unsigned long period; enum rt_timer_op op; }; #ifdef __cplusplus } #endif