timer.h

Go to the documentation of this file.
00001 
00052 #ifndef DRV_TIMER_H
00053 #define DRV_TIMER_H
00054 
00055 #include <cfg/os.h>
00056 #include <cfg/macros.h>
00057 
00058 #include <cpu/attr.h>
00059 #include <cpu/irq.h>
00060 
00061 
00062 /*
00063  * Include platform-specific binding header if we're hosted.
00064  * Try the CPU specific one for bare-metal environments.
00065  */
00066 #if OS_HOSTED
00067     //#include OS_HEADER(timer)
00068     #include <emul/timer_posix.h>
00069 #else
00070     #include CPU_HEADER(timer)
00071 #endif
00072 
00073 STATIC_ASSERT(sizeof(hptime_t) == SIZEOF_HPTIME_T);
00074 
00075 #include "cfg/cfg_timer.h"
00076 #include <cfg/debug.h>
00077 #include <cfg/compiler.h>
00078 
00079 #include <struct/list.h>
00080 
00081 /*
00082  * Sanity check for config parameters required by this module.
00083  */
00084 #if !defined(CONFIG_TIMER_EVENTS) || ((CONFIG_TIMER_EVENTS != 0) && CONFIG_TIMER_EVENTS != 1)
00085     #error CONFIG_TIMER_EVENTS must be set to either 0 or 1 in cfg_timer.h
00086 #endif
00087 #if !defined(CONFIG_TIMER_UDELAY) || ((CONFIG_TIMER_UDELAY != 0) && CONFIG_TIMER_EVENTS != 1)
00088     #error CONFIG_TIMER_UDELAY must be set to either 0 or 1 in cfg_timer.h
00089 #endif
00090 #if defined(CONFIG_TIMER_DISABLE_UDELAY)
00091     #error Obosolete config option CONFIG_TIMER_DISABLE_UDELAY.  Use CONFIG_TIMER_UDELAY
00092 #endif
00093 #if defined(CONFIG_TIMER_DISABLE_EVENTS)
00094     #error Obosolete config option CONFIG_TIMER_DISABLE_EVENTS.  Use CONFIG_TIMER_EVENTS
00095 #endif
00096 
00097 extern volatile ticks_t _clock;
00098 
00127 INLINE ticks_t timer_clock(void)
00128 {
00129     ticks_t result;
00130 
00131     ATOMIC(result = _clock);
00132 
00133     return result;
00134 }
00135 
00143 INLINE ticks_t timer_clock_unlocked(void)
00144 {
00145     return _clock;
00146 }
00147 
00148 
00150 INLINE ticks_t ms_to_ticks(mtime_t ms)
00151 {
00152 #if TIMER_TICKS_PER_SEC < 1000
00153     /* Slow timer: avoid rounding down too much. */
00154     return (ms * TIMER_TICKS_PER_SEC) / 1000;
00155 #else
00156     /* Fast timer: don't overflow ticks_t. */
00157     return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000);
00158 #endif
00159 }
00160 
00162 INLINE ticks_t us_to_ticks(utime_t us)
00163 {
00164 #if TIMER_TICKS_PER_SEC < 1000
00165     /* Slow timer: avoid rounding down too much. */
00166     return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000;
00167 #else
00168     /* Fast timer: don't overflow ticks_t. */
00169     return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000;
00170 #endif
00171 }
00172 
00174 INLINE mtime_t ticks_to_ms(ticks_t ticks)
00175 {
00176 #if TIMER_TICKS_PER_SEC < 1000
00177     /* Slow timer: avoid rounding down too much. */
00178     return (ticks * 1000) / TIMER_TICKS_PER_SEC;
00179 #else
00180     /* Fast timer: avoid overflowing ticks_t. */
00181     return ticks / (TIMER_TICKS_PER_SEC / 1000);
00182 #endif
00183 }
00184 
00186 INLINE utime_t ticks_to_us(ticks_t ticks)
00187 {
00188 #if TIMER_TICKS_PER_SEC < 1000
00189     /* Slow timer: avoid rounding down too much. */
00190     return ((ticks * 1000) / TIMER_TICKS_PER_SEC) * 1000;
00191 #else
00192     /* Fast timer: avoid overflowing ticks_t. */
00193     return (ticks / (TIMER_TICKS_PER_SEC / 1000)) * 1000;
00194 #endif
00195 }
00196 
00198 INLINE hptime_t us_to_hptime(utime_t us)
00199 {
00200 #if TIMER_HW_HPTICKS_PER_SEC > 10000000UL
00201     return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL);
00202 #else
00203     return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL;
00204 #endif
00205 }
00206 
00208 INLINE utime_t hptime_to_us(hptime_t hpticks)
00209 {
00210 #if TIMER_HW_HPTICKS_PER_SEC < 100000UL
00211     return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC);
00212 #else
00213     return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL);
00214 #endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */
00215 }
00216 
00217 void timer_delayTicks(ticks_t delay);
00224 INLINE void timer_delay(mtime_t delay)
00225 {
00226     timer_delayTicks(ms_to_ticks(delay));
00227 }
00228 
00229 void timer_init(void);
00230 void timer_cleanup(void);
00231 
00232 int timer_testSetup(void);
00233 int timer_testRun(void);
00234 int timer_testTearDown(void);
00235 
00236 #if CONFIG_TIMER_UDELAY
00237 void timer_busyWait(hptime_t delay);
00238 void timer_delayHp(hptime_t delay);
00239 INLINE void timer_udelay(utime_t delay)
00240 {
00241     timer_delayHp(us_to_hptime(delay));
00242 }
00243 #endif
00244 
00245 #if CONFIG_TIMER_EVENTS
00246 
00247 #include <mware/event.h>
00248 
00256 typedef struct Timer
00257 {
00258     Node    link;     
00259     ticks_t _delay;   
00260     ticks_t tick;     
00261     Event   expire;   
00262     DB(uint16_t magic;)
00263 } Timer;
00264 
00265 /* Timer is active when Timer.magic contains this value (for debugging purposes). */
00266 #define TIMER_MAGIC_ACTIVE    0xABBA
00267 #define TIMER_MAGIC_INACTIVE  0xBAAB
00268 
00269 void timer_add(Timer *timer);
00270 Timer *timer_abort(Timer *timer);
00271 
00282 INLINE void timer_setSoftint(Timer *timer, Hook func, iptr_t user_data)
00283 {
00284     event_initSoftint(&timer->expire, func, user_data);
00285 }
00286 
00288 INLINE void timer_setDelay(Timer *timer, ticks_t delay)
00289 {
00290     timer->_delay = delay;
00291 }
00292 
00293 
00294 void synctimer_add(Timer *timer, List* q);
00295 
00297 #define synctimer_abort(t) timer_abort(t)
00298 
00299 void synctimer_poll(List* q);
00300 
00301 
00302 #endif /* CONFIG_TIMER_EVENTS */
00303 
00304 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
00305 
00307 INLINE void timer_setSignal(Timer *timer, struct Process *proc, sigmask_t sigs)
00308 {
00309     event_initSignal(&timer->expire, proc, sigs);
00310 }
00311 
00312 #define timer_set_event_signal timer_setSignal
00313 
00314 #endif /* CONFIG_KERN_SIGNALS */
00315 
00316 #endif /* DRV_TIMER_H */