00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00187 #include <cfg/os.h>
00188 #include <dev/irqreg.h>
00189
00190 #include <sys/types.h>
00191 #include <sys/atom.h>
00192 #include <sys/heap.h>
00193 #include <sys/thread.h>
00194 #include <sys/timer.h>
00195
00196 #ifdef NUTDEBUG
00197 #include <sys/osdebug.h>
00198 #endif
00199
00200 #ifdef NUTTRACER
00201 #include <sys/tracer.h>
00202 #endif
00203
00204 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00205 #include <sys/time.h>
00206
00207 static struct timeval timeStart;
00208 #endif
00209
00214
00218 NUTTIMERINFO *nutTimerList;
00219
00220
00221
00222
00223 static u_long nut_ticks_resume;
00224
00228 volatile u_long nut_ticks;
00229
00230
00231
00235 #if !(defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__))
00236 #ifdef USE_TIMER
00237 SIGNAL( SIG_TIMER )
00238 #else
00239 static void NutTimerIntr(void *arg)
00240 #endif
00241 {
00242 nut_ticks++;
00243
00244 }
00245 #endif
00246
00247
00255 void NutTimerInit(void)
00256 {
00257 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00258 gettimeofday( &timeStart, NULL );
00259 #else
00260 NutRegisterTimer(NutTimerIntr);
00261 NutEnableTimerIrq();
00262 #endif
00263 }
00264
00265
00275 void NutTimerInsert(NUTTIMERINFO * tn)
00276 {
00277 NUTTIMERINFO *tnp;
00278
00279 tn->tn_prev = NULL;
00280 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00281 if (tn->tn_ticks_left < tnp->tn_ticks_left) {
00282 tnp->tn_ticks_left -= tn->tn_ticks_left;
00283 break;
00284 }
00285 tn->tn_ticks_left -= tnp->tn_ticks_left;
00286 tn->tn_prev = tnp;
00287 }
00288 tn->tn_next = tnp;
00289 if (tn->tn_next) {
00290 tn->tn_next->tn_prev = tn;
00291 }
00292 if (tn->tn_prev) {
00293 tn->tn_prev->tn_next = tn;
00294 }
00295 else {
00296 nutTimerList = tn;
00297 }
00298 }
00299
00306 void NutTimerProcessElapsed(void)
00307 {
00308 NUTTIMERINFO *tn;
00309 u_long ticks;
00310 u_long ticks_new;
00311
00312
00313 ticks = NutGetTickCount();
00314 ticks_new = ticks - nut_ticks_resume;
00315 nut_ticks_resume = ticks;
00316
00317
00318 while (nutTimerList && ticks_new){
00319
00320 tn = nutTimerList;
00321
00322
00323 if (ticks_new < tn->tn_ticks_left) {
00324 tn->tn_ticks_left -= ticks_new;
00325 ticks_new = 0;
00326 } else {
00327 ticks_new -= tn->tn_ticks_left;
00328 tn->tn_ticks_left = 0;
00329 }
00330
00331
00332 if (tn->tn_ticks_left == 0){
00333
00334
00335 if (tn->tn_callback) {
00336 (*tn->tn_callback) (tn, (void *) tn->tn_arg);
00337 }
00338 if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
00339 NutTimerStop(tn);
00340 }
00341 else {
00342
00343 nutTimerList = nutTimerList->tn_next;
00344 if (nutTimerList) {
00345 nutTimerList->tn_prev = 0;
00346 }
00347
00348 NutTimerInsert(tn);
00349 }
00350 }
00351 }
00352 }
00353
00373 NUTTIMERINFO * NutTimerCreate(u_long ticks, void (*callback) (HANDLE, void *), void *arg, u_char flags)
00374 {
00375 NUTTIMERINFO *tn;
00376
00377 tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
00378 if (tn) {
00379 tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
00380
00381
00382
00383
00384
00385 if (flags & TM_ONESHOT) {
00386 tn->tn_ticks = 0;
00387 } else {
00388 tn->tn_ticks = ticks;
00389 }
00390
00391
00392 tn->tn_callback = callback;
00393 tn->tn_arg = arg;
00394 }
00395 return tn;
00396 }
00397
00424 HANDLE NutTimerStartTicks(u_long ticks, void (*callback) (HANDLE, void *), void *arg, u_char flags)
00425 {
00426 NUTTIMERINFO *tn;
00427
00428 tn = NutTimerCreate( ticks, callback, arg, flags);
00429 if (tn) {
00430
00431 NutTimerInsert(tn);
00432 }
00433 return tn;
00434 }
00435
00464 HANDLE NutTimerStart(u_long ms, void (*callback) (HANDLE, void *), void *arg, u_char flags)
00465 {
00466 return NutTimerStartTicks(NutTimerMillisToTicks(ms), callback, arg, flags);
00467 }
00468
00490 void NutSleep(u_long ms)
00491 {
00492 if (ms) {
00493
00494
00495 NutThreadRemoveQueue(runningThread, &runQueue);
00496 runningThread->td_state = TDS_SLEEP;
00497
00498 if ((runningThread->td_timer = NutTimerStart(ms, NutThreadWake, runningThread, TM_ONESHOT)) != 0) {
00499 #ifdef NUTTRACER
00500 TRACE_ADD_ITEM(TRACE_TAG_THREAD_SLEEP,(int)runningThread);
00501 #endif
00502 NutThreadResume();
00503 } else
00504 {
00505
00506 runningThread->td_queue = &runQueue;
00507 runningThread->td_qnxt = runQueue;
00508 runningThread->td_state = TDS_RUNNING;
00509 runQueue = runningThread;
00510 }
00511 } else
00512 NutThreadYield();
00513 }
00514
00527 void NutTimerStop(HANDLE handle)
00528 {
00529 NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;
00530
00531 if (tn->tn_prev) {
00532 tn->tn_prev->tn_next = tn->tn_next;
00533 }
00534 else {
00535 nutTimerList = tn->tn_next;
00536 }
00537 if (tn->tn_next) {
00538 tn->tn_next->tn_prev = tn->tn_prev;
00539 tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
00540 }
00541 NutHeapFree(tn);
00542 }
00543
00552 u_long NutGetTickCount(void)
00553 {
00554 u_long rc;
00555
00556 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00557 struct timeval timeNow;
00558
00559 gettimeofday( &timeNow, NULL );
00560 rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000;
00561 rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000;
00562 #else
00563 NutEnterCritical();
00564 rc = nut_ticks;
00565 NutExitCritical();
00566 #endif
00567
00568 return rc;
00569 }
00570
00585 u_long NutGetSeconds(void)
00586 {
00587 return NutGetTickCount() / NutGetTickClock();
00588 }
00589
00606 u_long NutGetMillis(void)
00607 {
00608
00609 u_long ticks = NutGetTickCount();
00610 u_long seconds = ticks / NutGetTickClock();
00611 ticks -= seconds * NutGetTickClock();
00612 return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
00613 }
00614