summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/export/timer.h5
-rw-r--r--firmware/target/hosted/kernel-unix.c16
-rw-r--r--firmware/timer.c4
3 files changed, 21 insertions, 4 deletions
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();