BeRTOS
|
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 */