timer.h

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