timer.h

Go to the documentation of this file.
00001 
00041 #ifndef DRV_TIMER_H
00042 #define DRV_TIMER_H
00043 
00044 #include <cfg/os.h>
00045 #include <cfg/macros.h>
00046 #include <cpu/attr.h>
00047 #include <cpu/irq.h>
00048 
00049 
00050 /*
00051  * Include platform-specific binding header if we're hosted.
00052  * Try the CPU specific one for bare-metal environments.
00053  */
00054 #if OS_HOSTED
00055     #include OS_HEADER(timer)
00056 #else
00057     #include CPU_HEADER(timer)
00058 #endif
00059 
00060 #include <mware/list.h>
00061 #include <cfg/debug.h>
00062 #include <cfg/compiler.h>
00063 #include <appconfig.h>
00064 
00065 
00066 extern volatile ticks_t _clock;
00067 
00089 INLINE ticks_t timer_clock(void)
00090 {
00091     ticks_t result;
00092 
00093     ATOMIC(result = _clock);
00094 
00095     return result;
00096 }
00097 
00105 INLINE ticks_t timer_clock_unlocked(void)
00106 {
00107     return _clock;
00108 }
00109 
00111 INLINE ticks_t ms_to_ticks(mtime_t ms)
00112 {
00113 #if TIMER_TICKS_PER_SEC < 1000
00114     /* Slow timer: avoid rounding down too much. */
00115     return (ms * TIMER_TICKS_PER_SEC) / 1000;
00116 #else
00117     /* Fast timer: don't overflow ticks_t. */
00118     return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000);
00119 #endif
00120 }
00121 
00123 INLINE ticks_t us_to_ticks(utime_t us)
00124 {
00125 #if TIMER_TICKS_PER_SEC < 1000
00126     /* Slow timer: avoid rounding down too much. */
00127     return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000;
00128 #else
00129     /* Fast timer: don't overflow ticks_t. */
00130     return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000;
00131 #endif
00132 }
00133 
00135 INLINE mtime_t ticks_to_ms(ticks_t ticks)
00136 {
00137 #if TIMER_TICKS_PER_SEC < 1000
00138     /* Slow timer: avoid rounding down too much. */
00139     return (ticks * 1000) / TIMER_TICKS_PER_SEC;
00140 #else
00141     /* Fast timer: avoid overflowing ticks_t. */
00142     return ticks / (TIMER_TICKS_PER_SEC / 1000);
00143 #endif
00144 }
00145 
00147 INLINE utime_t ticks_to_us(ticks_t ticks)
00148 {
00149 #if TIMER_TICKS_PER_SEC < 1000
00150     /* Slow timer: avoid rounding down too much. */
00151     return ((ticks * 1000) / TIMER_TICKS_PER_SEC) * 1000;
00152 #else
00153     /* Fast timer: avoid overflowing ticks_t. */
00154     return (ticks / (TIMER_TICKS_PER_SEC / 1000)) * 1000;
00155 #endif
00156 }
00157 
00159 INLINE hptime_t us_to_hptime(utime_t us)
00160 {
00161 #if TIMER_HW_HPTICKS_PER_SEC > 10000000UL
00162     return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL);
00163 #else
00164     return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL;
00165 #endif
00166 }
00167 
00169 INLINE utime_t hptime_to_us(hptime_t hpticks)
00170 {
00171 #if TIMER_HW_HPTICKS_PER_SEC < 100000UL
00172     return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC);
00173 #else
00174     return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL);
00175 #endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */
00176 }
00177 
00178 
00179 void timer_init(void);
00180 void timer_delayTicks(ticks_t delay);
00181 INLINE void timer_delay(mtime_t delay)
00182 {
00183     timer_delayTicks(ms_to_ticks(delay));
00184 }
00185 
00186 #if !defined(CONFIG_TIMER_DISABLE_UDELAY)
00187 void timer_busyWait(hptime_t delay);
00188 void timer_delayHp(hptime_t delay);
00189 INLINE void timer_udelay(utime_t delay)
00190 {
00191     timer_delayHp(us_to_hptime(delay));
00192 }
00193 #endif
00194 
00195 #ifndef CONFIG_TIMER_DISABLE_EVENTS
00196 
00197 #include <mware/event.h>
00198 
00206 typedef struct Timer
00207 {
00208     Node    link;     
00209     ticks_t _delay;   
00210     ticks_t tick;     
00211     Event   expire;   
00212     DB(uint16_t magic;)
00213 } Timer;
00214 
00216 #define TIMER_MAGIC_ACTIVE    0xABBA
00217 #define TIMER_MAGIC_INACTIVE  0xBAAB
00218 
00219 extern void timer_add(Timer *timer);
00220 extern Timer *timer_abort(Timer *timer);
00221 
00223 INLINE void timer_set_event_softint(Timer *timer, Hook func, iptr_t user_data)
00224 {
00225     event_initSoftInt(&timer->expire, func, user_data);
00226 }
00227 
00229 INLINE void timer_setDelay(Timer *timer, ticks_t delay)
00230 {
00231     timer->_delay = delay;
00232 }
00233 
00234 #endif /* CONFIG_TIMER_DISABLE_EVENTS */
00235 
00236 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
00237 
00239 INLINE void timer_set_event_signal(Timer *timer, struct Process *proc, sigmask_t sigs)
00240 {
00241     event_initSignal(&timer->expire, proc, sigs);
00242 }
00243 
00244 #endif /* CONFIG_KERN_SIGNALS */
00245 
00246 
00247 #endif /* DRV_TIMER_H */