BeRTOS
timer.h
Go to the documentation of this file.
00001 
00056 #ifndef DRV_TIMER_H
00057 #define DRV_TIMER_H
00058 
00059 #include <cfg/os.h>
00060 #include <cfg/macros.h>
00061 
00062 #include <cpu/attr.h>
00063 #include <cpu/irq.h>
00064 
00065 
00066 /*
00067  * Include platform-specific binding header if we're hosted.
00068  * Try the CPU specific one for bare-metal environments.
00069  */
00070 #if OS_HOSTED
00071     //#include OS_HEADER(timer)
00072     #include <emul/timer_posix.h>
00073 #else
00074     #include CPU_HEADER(timer)
00075 #endif
00076 
00077 STATIC_ASSERT(sizeof(hptime_t) == SIZEOF_HPTIME_T);
00078 
00079 #include "cfg/cfg_timer.h"
00080 #include <cfg/debug.h>
00081 #include <cfg/compiler.h>
00082 
00083 #include <struct/list.h>
00084 
00085 /*
00086  * Sanity check for config parameters required by this module.
00087  */
00088 #if !defined(CONFIG_TIMER_EVENTS) || ((CONFIG_TIMER_EVENTS != 0) && CONFIG_TIMER_EVENTS != 1)
00089     #error CONFIG_TIMER_EVENTS must be set to either 0 or 1 in cfg_timer.h
00090 #endif
00091 #if !defined(CONFIG_TIMER_UDELAY) || ((CONFIG_TIMER_UDELAY != 0) && CONFIG_TIMER_EVENTS != 1)
00092     #error CONFIG_TIMER_UDELAY must be set to either 0 or 1 in cfg_timer.h
00093 #endif
00094 #if defined(CONFIG_TIMER_DISABLE_UDELAY)
00095     #error Obosolete config option CONFIG_TIMER_DISABLE_UDELAY.  Use CONFIG_TIMER_UDELAY
00096 #endif
00097 #if defined(CONFIG_TIMER_DISABLE_EVENTS)
00098     #error Obosolete config option CONFIG_TIMER_DISABLE_EVENTS.  Use CONFIG_TIMER_EVENTS
00099 #endif
00100 
00101 extern volatile ticks_t _clock;
00102 
00103 #define TIMER_AFTER(x, y) ((long)(y) - (long)(x) < 0)
00104 #define TIMER_BEFORE(x, y) TIMER_AFTER(y, x)
00105 
00134 INLINE ticks_t timer_clock(void)
00135 {
00136     ticks_t result;
00137 
00138     ATOMIC(result = _clock);
00139 
00140     return result;
00141 }
00142 
00150 INLINE ticks_t timer_clock_unlocked(void)
00151 {
00152     return _clock;
00153 }
00154 
00155 
00157 INLINE ticks_t ms_to_ticks(mtime_t ms)
00158 {
00159 #if TIMER_TICKS_PER_SEC < 1000
00160     /* Slow timer: avoid rounding down too much. */
00161     return (ms * TIMER_TICKS_PER_SEC) / 1000;
00162 #else
00163     /* Fast timer: don't overflow ticks_t. */
00164     return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000);
00165 #endif
00166 }
00167 
00169 INLINE ticks_t us_to_ticks(utime_t us)
00170 {
00171 #if TIMER_TICKS_PER_SEC < 1000
00172     /* Slow timer: avoid rounding down too much. */
00173     return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000;
00174 #else
00175     /* Fast timer: don't overflow ticks_t. */
00176     return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000;
00177 #endif
00178 }
00179 
00181 INLINE mtime_t ticks_to_ms(ticks_t ticks)
00182 {
00183 #if TIMER_TICKS_PER_SEC < 1000
00184     /* Slow timer: avoid rounding down too much. */
00185     return (ticks * 1000) / TIMER_TICKS_PER_SEC;
00186 #else
00187     /* Fast timer: avoid overflowing ticks_t. */
00188     return ticks / (TIMER_TICKS_PER_SEC / 1000);
00189 #endif
00190 }
00191 
00193 INLINE utime_t ticks_to_us(ticks_t ticks)
00194 {
00195 #if TIMER_TICKS_PER_SEC < 1000
00196     /* Slow timer: avoid rounding down too much. */
00197     return ((ticks * 1000) / TIMER_TICKS_PER_SEC) * 1000;
00198 #else
00199     /* Fast timer: avoid overflowing ticks_t. */
00200     return (ticks / (TIMER_TICKS_PER_SEC / 1000)) * 1000;
00201 #endif
00202 }
00203 
00205 INLINE hptime_t us_to_hptime(utime_t us)
00206 {
00207 #if TIMER_HW_HPTICKS_PER_SEC > 10000000UL
00208     return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL);
00209 #else
00210     return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL;
00211 #endif
00212 }
00213 
00215 INLINE utime_t hptime_to_us(hptime_t hpticks)
00216 {
00217 #if TIMER_HW_HPTICKS_PER_SEC < 100000UL
00218     return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC);
00219 #else
00220     return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL);
00221 #endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */
00222 }
00223 
00224 void timer_delayTicks(ticks_t delay);
00231 INLINE void timer_delay(mtime_t delay)
00232 {
00233     timer_delayTicks(ms_to_ticks(delay));
00234 }
00235 
00236 void timer_init(void);
00237 void timer_cleanup(void);
00238 
00239 int timer_testSetup(void);
00240 int timer_testRun(void);
00241 int timer_testTearDown(void);
00242 
00243 #if CONFIG_TIMER_UDELAY
00244 void timer_busyWait(hptime_t delay);
00245 void timer_delayHp(hptime_t delay);
00246 INLINE void timer_udelay(utime_t delay)
00247 {
00248     timer_delayHp(us_to_hptime(delay));
00249 }
00250 #endif
00251 
00252 #if CONFIG_TIMER_EVENTS
00253 
00254 #include <mware/event.h>
00255 
00263 typedef struct Timer
00264 {
00265     Node    link;     
00266     ticks_t _delay;   
00267     ticks_t tick;     
00268     Event   expire;   
00269     DB(uint16_t magic;)
00270 } Timer;
00271 
00272 /* Timer is active when Timer.magic contains this value (for debugging purposes). */
00273 #define TIMER_MAGIC_ACTIVE    0xABBA
00274 #define TIMER_MAGIC_INACTIVE  0xBAAB
00275 
00276 void timer_add(Timer *timer);
00277 Timer *timer_abort(Timer *timer);
00278 
00289 INLINE void timer_setSoftint(Timer *timer, Hook func, iptr_t user_data)
00290 {
00291     event_initSoftint(&timer->expire, func, user_data);
00292 }
00293 
00300 INLINE void timer_setDelay(Timer *timer, ticks_t delay)
00301 {
00302     timer->_delay = delay;
00303 }
00304 
00305 
00306 void synctimer_add(Timer *timer, List* q);
00307 
00309 #define synctimer_abort(t) timer_abort(t)
00310 
00311 void synctimer_poll(List* q);
00312 
00313 
00314 #endif /* CONFIG_TIMER_EVENTS */
00315 
00316 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
00317 
00319 INLINE void timer_setEvent(Timer *timer)
00320 {
00321     event_initGeneric(&timer->expire);
00322 }
00323 
00325 INLINE void timer_waitEvent(Timer *timer)
00326 {
00327     event_wait(&timer->expire);
00328 }
00329 
00331 INLINE void timer_setSignal(Timer *timer, struct Process *proc, sigmask_t sigs)
00332 {
00333     event_initSignal(&timer->expire, proc, sigs);
00334 }
00335 
00336 #define timer_set_event_signal timer_setSignal
00337 
00338 #endif /* CONFIG_KERN_SIGNALS */
00339  //defgroup drv_timers
00341 
00342 #endif /* DRV_TIMER_H */