Update to new kernel config; use cpu_relax().
[bertos.git] / bertos / drv / timer.c
index 81f87942716989f62d3fe375a8e59dfd50993597..7e99d78ee8822b9e6eeaadbdd434b09c221fc8ac 100644 (file)
  * the GNU General Public License.
  *
  * Copyright 2003, 2004, 2005, 2006 Develer S.r.l. (http://www.develer.com/)
- * Copyright 2000 Bernardo Innocenti <bernie@develer.com>
- *
+ * Copyright 2000, 2008 Bernie Innocenti <bernie@codewiz.org>
  * -->
  *
  * \brief Hardware independent timer driver (implementation)
  *
  * \version $Id$
- * \author Bernardo Innocenti <bernie@develer.com>
+ * \author Bernie Innocenti <bernie@codewiz.org>
  */
 
 #include "timer.h"
 
 #include "cfg/cfg_timer.h"
 #include "cfg/cfg_wdt.h"
-#include "cfg/cfg_kern.h"
+#include "cfg/cfg_proc.h"
+#include "cfg/cfg_signal.h"
 #include <cfg/os.h>
 #include <cfg/debug.h>
 #include <cfg/module.h>
 #include <cpu/attr.h>
 #include <cpu/types.h>
 #include <cpu/irq.h>
+#include <cpu/power.h> // cpu_relax()
 
 /*
  * Include platform-specific binding code if we're hosted.
  * Try the CPU specific one for bare-metal environments.
  */
 #if OS_HOSTED
-       #include OS_CSOURCE(timer)
+       //#include OS_CSOURCE(timer)
+       #include <emul/timer_posix.c>
 #else
        #include CPU_CSOURCE(timer)
 #endif
@@ -63,8 +65,8 @@
 /*
  * Sanity check for config parameters required by this module.
  */
-#if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1)
-       #error CONFIG_KERNEL must be set to either 0 or 1 in config.h
+#if !defined(CONFIG_KERN) || ((CONFIG_KERN != 0) && CONFIG_KERN != 1)
+       #error CONFIG_KERN must be set to either 0 or 1 in config.h
 #endif
 #if !defined(CONFIG_WATCHDOG) || ((CONFIG_WATCHDOG != 0) && CONFIG_WATCHDOG != 1)
        #error CONFIG_WATCHDOG must be set to either 0 or 1 in config.h
        #include <drv/wdt.h>
 #endif
 
-#if CONFIG_KERNEL
-       #if CONFIG_KERN_PREEMPTIVE
-               #include <hw/switch.h>
-       #endif
-       #if CONFIG_KERN_SIGNALS
-               #include <kern/signal.h> /* sig_wait(), sig_check() */
-               #include <kern/proc.h>   /* proc_current() */
-               #include <cfg/macros.h>  /* BV() */
-       #endif
+#if defined (CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
+       #include <kern/signal.h> /* sig_wait(), sig_check() */
+       #include <kern/proc.h>   /* proc_current() */
+       #include <cfg/macros.h>  /* BV() */
 #endif
 
 
 volatile ticks_t _clock;
 
 
-#ifndef CONFIG_TIMER_DISABLE_EVENTS
+#if CONFIG_TIMER_EVENTS
 
 /**
  * List of active asynchronous timers.
@@ -125,7 +122,7 @@ REGISTER static List timers_queue;
 void timer_add(Timer *timer)
 {
        Timer *node;
-       cpuflags_t flags;
+       cpu_flags_t flags;
 
 
        /* Inserting timers twice causes mayhem. */
@@ -163,7 +160,10 @@ void timer_add(Timer *timer)
 
 
 /**
- * Remove a timer from the timer queue before it has expired.
+ * Remove a timer from the timers queue before it has expired.
+ *
+ * \note Attempting to remove a timer already expired cause
+ *       undefined behaviour.
  */
 Timer *timer_abort(Timer *timer)
 {
@@ -173,7 +173,7 @@ Timer *timer_abort(Timer *timer)
        return timer;
 }
 
-#endif /* CONFIG_TIMER_DISABLE_EVENTS */
+#endif /* CONFIG_TIMER_EVENTS */
 
 
 /**
@@ -181,16 +181,14 @@ Timer *timer_abort(Timer *timer)
  */
 void timer_delayTicks(ticks_t delay)
 {
-#if defined(IRQ_ENABLED)
        /* We shouldn't sleep with interrupts disabled */
-       ASSERT(IRQ_ENABLED());
-#endif
+       IRQ_ASSERT_ENABLED();
 
 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
        Timer t;
 
        ASSERT(!sig_check(SIG_SINGLE));
-       timer_set_event_signal(&t, proc_current(), SIG_SINGLE);
+       timer_setSignal(&t, proc_current(), SIG_SINGLE);
        timer_setDelay(&t, delay);
        timer_add(&t);
        sig_wait(SIG_SINGLE);
@@ -201,17 +199,13 @@ void timer_delayTicks(ticks_t delay)
 
        /* Busy wait */
        while (timer_clock() - start < delay)
-       {
-#if CONFIG_WATCHDOG
-               wdt_reset();
-#endif
-       }
+               cpu_relax();
 
 #endif /* !CONFIG_KERN_SIGNALS */
 }
 
 
-#ifndef CONFIG_TIMER_DISABLE_UDELAY
+#if CONFIG_TIMER_UDELAY
 
 /**
  * Busy wait until the specified amount of high-precision ticks have elapsed.
@@ -257,7 +251,7 @@ void timer_delayHp(hptime_t delay)
 
        timer_busyWait(delay);
 }
-#endif /* CONFIG_TIMER_DISABLE_UDELAY */
+#endif /* CONFIG_TIMER_UDELAY */
 
 
 /**
@@ -275,9 +269,10 @@ DEFINE_TIMER_ISR
        #pragma interrupt saveall
        #endif
 
-#ifndef CONFIG_TIMER_DISABLE_EVENTS
+#if CONFIG_TIMER_EVENTS
        Timer *timer;
 #endif
+
        /*
         * On systems sharing IRQ line and vector, this check is needed
         * to ensure that IRQ is generated by timer source.
@@ -293,7 +288,7 @@ DEFINE_TIMER_ISR
        /* Update the master ms counter */
        ++_clock;
 
-#ifndef CONFIG_TIMER_DISABLE_EVENTS
+#if CONFIG_TIMER_EVENTS
        /*
         * Check the first timer request in the list and process
         * it when it has expired. Repeat this check until the
@@ -314,7 +309,7 @@ DEFINE_TIMER_ISR
                /* Execute the associated event */
                event_do(&timer->expire);
        }
-#endif /* CONFIG_TIMER_DISABLE_EVENTS */
+#endif /* CONFIG_TIMER_EVENTS */
 
        TIMER_STROBE_OFF;
 }
@@ -326,11 +321,15 @@ MOD_DEFINE(timer)
  */
 void timer_init(void)
 {
-       TIMER_STROBE_INIT;
+       #if CONFIG_KERN_IRQ
+               MOD_CHECK(irq);
+       #endif
 
-#ifndef CONFIG_TIMER_DISABLE_EVENTS
-       LIST_INIT(&timers_queue);
-#endif
+       #if CONFIG_TIMER_EVENTS
+               LIST_INIT(&timers_queue);
+       #endif
+
+       TIMER_STROBE_INIT;
 
        _clock = 0;
 
@@ -338,3 +337,19 @@ void timer_init(void)
 
        MOD_INIT(timer);
 }
+
+
+#if (ARCH & ARCH_EMUL)
+/**
+ * Stop timer (only used by emulator)
+ */
+void timer_cleanup(void)
+{
+       MOD_CLEANUP(timer);
+
+       timer_hw_cleanup();
+
+       // Hmmm... apparently, the demo app does not cleanup properly
+       //ASSERT(LIST_EMPTY(&timers_queue));
+}
+#endif /* ARCH_EMUL */