timer.c
Go to the documentation of this file.00001
00040 #include "timer.h"
00041
00042 #include <cpu/attr.h>
00043 #include <cpu/types.h>
00044 #include <cpu/irq.h>
00045
00046 #include <cfg/os.h>
00047 #include <cfg/debug.h>
00048 #include <cfg/module.h>
00049 #include <appconfig.h>
00050
00051
00052
00053
00054
00055 #if OS_HOSTED
00056 #include OS_CSOURCE(timer)
00057 #else
00058 #include CPU_CSOURCE(timer)
00059 #endif
00060
00061
00062
00063
00064 #if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1)
00065 #error CONFIG_KERNEL must be set to either 0 or 1 in config.h
00066 #endif
00067 #if !defined(CONFIG_WATCHDOG) || ((CONFIG_WATCHDOG != 0) && CONFIG_WATCHDOG != 1)
00068 #error CONFIG_WATCHDOG must be set to either 0 or 1 in config.h
00069 #endif
00070
00071 #if CONFIG_WATCHDOG
00072 #include <drv/wdt.h>
00073 #endif
00074
00075 #if CONFIG_KERNEL
00076 #include <config_kern.h>
00077 #if CONFIG_KERN_PREEMPTIVE
00078 #include <hw/switch.h>
00079 #endif
00080 #if CONFIG_KERN_SIGNALS
00081 #include <kern/signal.h>
00082 #include <kern/proc.h>
00083 #include <cfg/macros.h>
00084 #endif
00085 #endif
00086
00087
00098 #if !defined(CONFIG_TIMER_STROBE) || !CONFIG_TIMER_STROBE
00099 #define TIMER_STROBE_ON do {} while(0)
00100 #define TIMER_STROBE_OFF do {} while(0)
00101 #define TIMER_STROBE_INIT do {} while(0)
00102 #endif
00103
00104
00106 volatile ticks_t _clock;
00107
00108
00109 #ifndef CONFIG_TIMER_DISABLE_EVENTS
00110
00114 REGISTER static List timers_queue;
00115
00116
00124 void timer_add(Timer *timer)
00125 {
00126 Timer *node;
00127 cpuflags_t flags;
00128
00129
00130
00131 ASSERT(timer->magic != TIMER_MAGIC_ACTIVE);
00132 DB(timer->magic = TIMER_MAGIC_ACTIVE;)
00133
00134 IRQ_SAVE_DISABLE(flags);
00135
00136
00137 timer->tick = _clock + timer->_delay;
00138
00139
00140
00141
00142
00143 node = (Timer *)LIST_HEAD(&timers_queue);
00144 while (node->link.succ)
00145 {
00146
00147
00148
00149
00150 if (node->tick - timer->tick > 0)
00151 break;
00152
00153
00154 node = (Timer *)node->link.succ;
00155 }
00156
00157
00158 INSERT_BEFORE(&timer->link, &node->link);
00159
00160 IRQ_RESTORE(flags);
00161 }
00162
00163
00167 Timer *timer_abort(Timer *timer)
00168 {
00169 ATOMIC(REMOVE(&timer->link));
00170 DB(timer->magic = TIMER_MAGIC_INACTIVE;)
00171
00172 return timer;
00173 }
00174
00175 #endif
00176
00177
00181 void timer_delayTicks(ticks_t delay)
00182 {
00183 #if defined(IRQ_ENABLED)
00184
00185 ASSERT(IRQ_ENABLED());
00186 #endif
00187
00188 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
00189 Timer t;
00190
00191 ASSERT(!sig_check(SIG_SINGLE));
00192 timer_set_event_signal(&t, proc_current(), SIG_SINGLE);
00193 timer_setDelay(&t, delay);
00194 timer_add(&t);
00195 sig_wait(SIG_SINGLE);
00196
00197 #else
00198
00199 ticks_t start = timer_clock();
00200
00201
00202 while (timer_clock() - start < delay)
00203 {
00204 #if CONFIG_WATCHDOG
00205 wdt_reset();
00206 #endif
00207 }
00208
00209 #endif
00210 }
00211
00212
00213 #ifndef CONFIG_TIMER_DISABLE_UDELAY
00214
00221 void timer_busyWait(hptime_t delay)
00222 {
00223 hptime_t now, prev = timer_hw_hpread();
00224 hptime_t delta;
00225
00226 for(;;)
00227 {
00228 now = timer_hw_hpread();
00229
00230
00231
00232
00233
00234 delta = (now - prev) % TIMER_HW_CNT;
00235 if (delta >= delay)
00236 break;
00237 delay -= delta;
00238 prev = now;
00239 }
00240 }
00241
00249 void timer_delayHp(hptime_t delay)
00250 {
00251 if (UNLIKELY(delay > us_to_hptime(1000)))
00252 {
00253 timer_delayTicks(delay / (TIMER_HW_HPTICKS_PER_SEC / TIMER_TICKS_PER_SEC));
00254 delay %= (TIMER_HW_HPTICKS_PER_SEC / TIMER_TICKS_PER_SEC);
00255 }
00256
00257 timer_busyWait(delay);
00258 }
00259 #endif
00260
00261
00266 DEFINE_TIMER_ISR
00267 {
00268
00269
00270
00271
00272
00273 #ifdef __MWERKS__
00274 #pragma interrupt saveall
00275 #endif
00276
00277 #ifndef CONFIG_TIMER_DISABLE_EVENTS
00278 Timer *timer;
00279 #endif
00280
00281
00282
00283
00284 if (!timer_hw_triggered())
00285 return;
00286
00287 TIMER_STROBE_ON;
00288
00289
00290 timer_hw_irq();
00291
00292
00293 ++_clock;
00294
00295 #ifndef CONFIG_TIMER_DISABLE_EVENTS
00296
00297
00298
00299
00300
00301
00302
00303 while ((timer = (Timer *)LIST_HEAD(&timers_queue))->link.succ)
00304 {
00305
00306 if (_clock - timer->tick < 0)
00307 break;
00308
00309
00310 REMOVE(&timer->link);
00311 DB(timer->magic = TIMER_MAGIC_INACTIVE;)
00312
00313
00314 event_do(&timer->expire);
00315 }
00316 #endif
00317
00318 TIMER_STROBE_OFF;
00319 }
00320
00321 MOD_DEFINE(timer)
00322
00323
00326 void timer_init(void)
00327 {
00328 TIMER_STROBE_INIT;
00329
00330 #ifndef CONFIG_TIMER_DISABLE_EVENTS
00331 LIST_INIT(&timers_queue);
00332 #endif
00333
00334 _clock = 0;
00335
00336 timer_hw_init();
00337
00338 MOD_INIT(timer);
00339 }