diff --git a/firmware/export/timer.h b/firmware/export/timer.h index b12ec55881..92b26db216 100644 --- a/firmware/export/timer.h +++ b/firmware/export/timer.h @@ -30,6 +30,7 @@ #define TIMER_FREQ 1000000 #endif +/* NOTE: if unreg cb is defined you are in charge of calling timer_unregister() */ bool timer_register(int reg_prio, void (*unregister_callback)(void), long cycles, void (*timer_callback)(void) IF_COP(,int core)); @@ -37,6 +38,10 @@ bool timer_set_period(long cycles); #ifdef CPU_COLDFIRE void timers_adjust_prescale(int multiplier, bool enable_irq); #endif + +/* NOTE: unregister callbacks are not called by timer_unregister() +* the unregister_callback only gets called when your timer gets +* overwritten by a lower priority timer using timer_register() */ void timer_unregister(void); /* target-specific interface */ diff --git a/firmware/target/hosted/kernel-unix.c b/firmware/target/hosted/kernel-unix.c index e3c492a8cc..ed1f83cd8c 100644 --- a/firmware/target/hosted/kernel-unix.c +++ b/firmware/target/hosted/kernel-unix.c @@ -113,8 +113,8 @@ void (*global_timer_callback)(void); static void timer_cb(union sigval arg) { - (void)arg; - if (global_timer_callback) + /* check for spurious callbacks [arg.sival_ptr] */ + if (global_timer_callback && global_timer_callback == arg.sival_ptr) global_timer_callback(); } @@ -129,12 +129,18 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), if (reg_prio <= timer_prio || in_us <= 0) return false; - if (timer_prio >= 0 && global_unreg_callback) - global_unreg_callback(); + if(timer_prio >= 0) + { + if (global_unreg_callback) /* timer has callback user needs to unreg */ + global_unreg_callback(); + else /* no callback -- delete timer */ + timer_delete(timer_tid); + } memset(&sigev, 0, sizeof(sigevent_t)); sigev.sigev_notify = SIGEV_THREAD, sigev.sigev_notify_function = timer_cb; + sigev.sigev_value.sival_ptr = timer_callback; /* store cb to check later */ div_t q = div(in_us, 1000000); ts.it_value.tv_sec = ts.it_interval.tv_sec = q.quot; @@ -166,4 +172,6 @@ void timer_unregister(void) { timer_delete(timer_tid); timer_prio = -1; + global_unreg_callback = NULL; + global_timer_callback = NULL; } diff --git a/firmware/timer.c b/firmware/timer.c index a923290a94..c618f72e02 100644 --- a/firmware/timer.c +++ b/firmware/timer.c @@ -42,6 +42,7 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), return false; pfn_timer = timer_callback; + /* NOTE: if unreg cb is defined you are in charge of calling timer_unregister() */ pfn_unregister = unregister_callback; timer_prio = reg_prio; @@ -53,6 +54,9 @@ bool timer_set_period(long cycles) return timer_set(cycles, false); } +/* NOTE: unregister callbacks are not called by timer_unregister() +* the unregister_callback only gets called when your timer gets +* overwritten by a lower priority timer using timer_register() */ void timer_unregister(void) { timer_stop();