timer.h

Go to the documentation of this file.
00001 
00039 #ifndef DRV_TIMER_H
00040 #define DRV_TIMER_H
00041 
00042 #include <cfg/os.h>
00043 #include <cfg/macros.h>
00044 
00045 #include <cpu/attr.h>
00046 #include <cpu/irq.h>
00047 
00048 
00049 /*
00050  * Include platform-specific binding header if we're hosted.
00051  * Try the CPU specific one for bare-metal environments.
00052  */
00053 #if OS_HOSTED
00054     //#include OS_HEADER(timer)
00055     #include <emul/timer_posix.h>
00056 #else
00057     #include CPU_HEADER(timer)
00058 #endif
00059 
00060 #include "cfg/cfg_timer.h"
00061 #include <cfg/debug.h>
00062 #include <cfg/compiler.h>
00063 
00064 #include <struct/list.h>
00065 
00066 /*
00067  * Sanity check for config parameters required by this module.
00068  */
00069 #if !defined(CONFIG_TIMER_EVENTS) || ((CONFIG_TIMER_EVENTS != 0) && CONFIG_TIMER_EVENTS != 1)
00070     #error CONFIG_TIMER_EVENTS must be set to either 0 or 1 in cfg_timer.h
00071 #endif
00072 #if !defined(CONFIG_TIMER_UDELAY) || ((CONFIG_TIMER_UDELAY != 0) && CONFIG_TIMER_EVENTS != 1)
00073     #error CONFIG_TIMER_UDELAY must be set to either 0 or 1 in cfg_timer.h
00074 #endif
00075 #if defined(CONFIG_TIMER_DISABLE_UDELAY)
00076     #error Obosolete config option CONFIG_TIMER_DISABLE_UDELAY.  Use CONFIG_TIMER_UDELAY
00077 #endif
00078 #if defined(CONFIG_TIMER_DISABLE_EVENTS)
00079     #error Obosolete config option CONFIG_TIMER_DISABLE_EVENTS.  Use CONFIG_TIMER_EVENTS
00080 #endif
00081 
00082 extern volatile ticks_t _clock;
00083 
00111 INLINE ticks_t timer_clock(void)
00112 {
00113     ticks_t result;
00114 
00115     ATOMIC(result = _clock);
00116 
00117     return result;
00118 }
00119 
00127 INLINE ticks_t timer_clock_unlocked(void)
00128 {
00129     return _clock;
00130 }
00131 
00133 INLINE ticks_t ms_to_ticks(mtime_t ms)
00134 {
00135 #if TIMER_TICKS_PER_SEC < 1000
00136     /* Slow timer: avoid rounding down too much. */
00137     return (ms * TIMER_TICKS_PER_SEC) / 1000;
00138 #else
00139     /* Fast timer: don't overflow ticks_t. */
00140     return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000);
00141 #endif
00142 }
00143 
00145 INLINE ticks_t us_to_ticks(utime_t us)
00146 {
00147 #if TIMER_TICKS_PER_SEC < 1000
00148     /* Slow timer: avoid rounding down too much. */
00149     return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000;
00150 #else
00151     /* Fast timer: don't overflow ticks_t. */
00152     return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000;
00153 #endif
00154 }
00155 
00157 INLINE mtime_t ticks_to_ms(ticks_t ticks)
00158 {
00159 #if TIMER_TICKS_PER_SEC < 1000
00160     /* Slow timer: avoid rounding down too much. */
00161     return (ticks * 1000) / TIMER_TICKS_PER_SEC;
00162 #else
00163     /* Fast timer: avoid overflowing ticks_t. */
00164     return ticks / (TIMER_TICKS_PER_SEC / 1000);
00165 #endif
00166 }
00167 
00169 INLINE utime_t ticks_to_us(ticks_t ticks)
00170 {
00171 #if TIMER_TICKS_PER_SEC < 1000
00172     /* Slow timer: avoid rounding down too much. */
00173     return ((ticks * 1000) / TIMER_TICKS_PER_SEC) * 1000;
00174 #else
00175     /* Fast timer: avoid overflowing ticks_t. */
00176     return (ticks / (TIMER_TICKS_PER_SEC / 1000)) * 1000;
00177 #endif
00178 }
00179 
00181 INLINE hptime_t us_to_hptime(utime_t us)
00182 {
00183 #if TIMER_HW_HPTICKS_PER_SEC > 10000000UL
00184     return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL);
00185 #else
00186     return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL;
00187 #endif
00188 }
00189 
00191 INLINE utime_t hptime_to_us(hptime_t hpticks)
00192 {
00193 #if TIMER_HW_HPTICKS_PER_SEC < 100000UL
00194     return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC);
00195 #else
00196     return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL);
00197 #endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */
00198 }
00199 
00200 void timer_delayTicks(ticks_t delay);
00201 INLINE void timer_delay(mtime_t delay)
00202 {
00203     timer_delayTicks(ms_to_ticks(delay));
00204 }
00205 
00206 void timer_init(void);
00207 void timer_cleanup(void);
00208 
00209 int timer_testSetup(void);
00210 int timer_testRun(void);
00211 int timer_testTearDown(void);
00212 
00213 #if CONFIG_TIMER_UDELAY
00214 void timer_busyWait(hptime_t delay);
00215 void timer_delayHp(hptime_t delay);
00216 INLINE void timer_udelay(utime_t delay)
00217 {
00218     timer_delayHp(us_to_hptime(delay));
00219 }
00220 #endif
00221 
00222 #if CONFIG_TIMER_EVENTS
00223 
00224 #include <mware/event.h>
00225 
00233 typedef struct Timer
00234 {
00235     Node    link;     
00236     ticks_t _delay;   
00237     ticks_t tick;     
00238     Event   expire;   
00239     DB(uint16_t magic;)
00240 } Timer;
00241 
00243 #define TIMER_MAGIC_ACTIVE    0xABBA
00244 #define TIMER_MAGIC_INACTIVE  0xBAAB
00245 
00246 void timer_add(Timer *timer);
00247 Timer *timer_abort(Timer *timer);
00248 
00250 INLINE void timer_setSoftint(Timer *timer, Hook func, iptr_t user_data)
00251 {
00252     event_initSoftint(&timer->expire, func, user_data);
00253 }
00254 
00256 INLINE void timer_setDelay(Timer *timer, ticks_t delay)
00257 {
00258     timer->_delay = delay;
00259 }
00260 
00261 #endif /* CONFIG_TIMER_EVENTS */
00262 
00263 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
00264 
00266 INLINE void timer_setSignal(Timer *timer, struct Process *proc, sigmask_t sigs)
00267 {
00268     event_initSignal(&timer->expire, proc, sigs);
00269 }
00270 
00271 #define timer_set_event_signal timer_setSignal
00272 
00273 #endif /* CONFIG_KERN_SIGNALS */
00274 
00275 #endif /* DRV_TIMER_H */