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 
00149 INLINE ticks_t ms_to_ticks(mtime_t ms)
00150 {
00151 #if TIMER_TICKS_PER_SEC < 1000
00152     /* Slow timer: avoid rounding down too much. */
00153     return (ms * TIMER_TICKS_PER_SEC) / 1000;
00154 #else
00155     /* Fast timer: don't overflow ticks_t. */
00156     return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000);
00157 #endif
00158 }
00159 
00161 INLINE ticks_t us_to_ticks(utime_t us)
00162 {
00163 #if TIMER_TICKS_PER_SEC < 1000
00164     /* Slow timer: avoid rounding down too much. */
00165     return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000;
00166 #else
00167     /* Fast timer: don't overflow ticks_t. */
00168     return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000;
00169 #endif
00170 }
00171 
00173 INLINE mtime_t ticks_to_ms(ticks_t ticks)
00174 {
00175 #if TIMER_TICKS_PER_SEC < 1000
00176     /* Slow timer: avoid rounding down too much. */
00177     return (ticks * 1000) / TIMER_TICKS_PER_SEC;
00178 #else
00179     /* Fast timer: avoid overflowing ticks_t. */
00180     return ticks / (TIMER_TICKS_PER_SEC / 1000);
00181 #endif
00182 }
00183 
00185 INLINE utime_t ticks_to_us(ticks_t ticks)
00186 {
00187 #if TIMER_TICKS_PER_SEC < 1000
00188     /* Slow timer: avoid rounding down too much. */
00189     return ((ticks * 1000) / TIMER_TICKS_PER_SEC) * 1000;
00190 #else
00191     /* Fast timer: avoid overflowing ticks_t. */
00192     return (ticks / (TIMER_TICKS_PER_SEC / 1000)) * 1000;
00193 #endif
00194 }
00195 
00197 INLINE hptime_t us_to_hptime(utime_t us)
00198 {
00199 #if TIMER_HW_HPTICKS_PER_SEC > 10000000UL
00200     return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL);
00201 #else
00202     return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL;
00203 #endif
00204 }
00205 
00207 INLINE utime_t hptime_to_us(hptime_t hpticks)
00208 {
00209 #if TIMER_HW_HPTICKS_PER_SEC < 100000UL
00210     return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC);
00211 #else
00212     return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL);
00213 #endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */
00214 }
00215 
00216 void timer_delayTicks(ticks_t delay);
00223 INLINE void timer_delay(mtime_t delay)
00224 {
00225     timer_delayTicks(ms_to_ticks(delay));
00226 }
00227 
00228 void timer_init(void);
00229 void timer_cleanup(void);
00230 
00231 int timer_testSetup(void);
00232 int timer_testRun(void);
00233 int timer_testTearDown(void);
00234 
00235 #if CONFIG_TIMER_UDELAY
00236 void timer_busyWait(hptime_t delay);
00237 void timer_delayHp(hptime_t delay);
00238 INLINE void timer_udelay(utime_t delay)
00239 {
00240     timer_delayHp(us_to_hptime(delay));
00241 }
00242 #endif
00243 
00244 #if CONFIG_TIMER_EVENTS
00245 
00246 #include <mware/event.h>
00247 
00255 typedef struct Timer
00256 {
00257     Node    link;     
00258     ticks_t _delay;   
00259     ticks_t tick;     
00260     Event   expire;   
00261     DB(uint16_t magic;)
00262 } Timer;
00263 
00264 /* Timer is active when Timer.magic contains this value (for debugging purposes). */
00265 #define TIMER_MAGIC_ACTIVE    0xABBA
00266 #define TIMER_MAGIC_INACTIVE  0xBAAB
00267 
00268 void timer_add(Timer *timer);
00269 Timer *timer_abort(Timer *timer);
00270 
00281 INLINE void timer_setSoftint(Timer *timer, Hook func, iptr_t user_data)
00282 {
00283     event_initSoftint(&timer->expire, func, user_data);
00284 }
00285 
00287 INLINE void timer_setDelay(Timer *timer, ticks_t delay)
00288 {
00289     timer->_delay = delay;
00290 }
00291 
00292 #endif /* CONFIG_TIMER_EVENTS */
00293 
00294 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
00295 
00297 INLINE void timer_setSignal(Timer *timer, struct Process *proc, sigmask_t sigs)
00298 {
00299     event_initSignal(&timer->expire, proc, sigs);
00300 }
00301 
00302 #define timer_set_event_signal timer_setSignal
00303 
00304 #endif /* CONFIG_KERN_SIGNALS */
00305 
00306 #endif /* DRV_TIMER_H */