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
00196 #include <cfg/os.h>
00197 #include <dev/irqreg.h>
00198
00199 #include <sys/types.h>
00200 #include <sys/atom.h>
00201 #include <sys/heap.h>
00202 #include <sys/thread.h>
00203 #include <sys/timer.h>
00204
00205 #ifdef NUTDEBUG
00206 #include <sys/osdebug.h>
00207 #endif
00208
00209 #ifdef NUTTRACER
00210 #include <sys/tracer.h>
00211 #endif
00212
00213 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00214 #include <sys/time.h>
00215
00216 static struct timeval timeStart;
00217 #endif
00218
00223
00227 NUTTIMERINFO *nutTimerList;
00228
00229
00230
00231
00232 static u_long nut_ticks_resume;
00233
00237 volatile u_long nut_ticks;
00238
00239
00240
00244 #if defined(NUT_DELAYLOOPS)
00245 volatile u_long nut_delay_loops = NUT_DELAYLOOPS;
00246 #else
00247 volatile u_long nut_delay_loops;
00248 #endif
00249
00253
00254
00258 #if !(defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__))
00259 #ifdef USE_TIMER
00260 SIGNAL( SIG_TIMER )
00261 #else
00262 static void NutTimerIntr(void *arg)
00263 #endif
00264 {
00265 nut_ticks++;
00266
00267 }
00268 #endif
00269
00270
00278 void NutTimerInit(void)
00279 {
00280 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00281 gettimeofday( &timeStart, NULL );
00282 #else
00283 NutRegisterTimer(NutTimerIntr);
00284 NutEnableTimerIrq();
00285
00286
00287 #if !defined(NUT_DELAYLOOPS)
00288 #ifndef NUT_TICK_FREQ
00289 #define NUT_TICK_FREQ 1000UL
00290 #endif
00291 {
00292
00293 u_long cnt = NutGetTickCount();
00294 while (cnt == NutGetTickCount());
00295
00296 cnt = NutGetTickCount();
00297 while (cnt == NutGetTickCount()) {
00298 nut_delay_loops++;
00299 }
00300
00301
00302
00303
00304
00305 nut_delay_loops *= 103UL;
00306 nut_delay_loops /= 26UL;
00307 }
00308 #endif
00309 #endif
00310 }
00311
00327 void NutMicroDelay(u_long us)
00328 {
00329 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00330 usleep(us);
00331 #else
00332 register u_long cnt = nut_delay_loops * us / 1000;
00333
00334 while (cnt--) {
00335 _NOP();
00336 }
00337 #endif
00338 }
00339
00351 void NutDelay(u_char ms)
00352 {
00353 NutMicroDelay((u_long)ms * 1000);
00354 }
00355
00365 void NutTimerInsert(NUTTIMERINFO * tn)
00366 {
00367 NUTTIMERINFO *tnp;
00368
00369 tn->tn_prev = NULL;
00370 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00371 if (tn->tn_ticks_left < tnp->tn_ticks_left) {
00372 tnp->tn_ticks_left -= tn->tn_ticks_left;
00373 break;
00374 }
00375 tn->tn_ticks_left -= tnp->tn_ticks_left;
00376 tn->tn_prev = tnp;
00377 }
00378 tn->tn_next = tnp;
00379 if (tn->tn_next) {
00380 tn->tn_next->tn_prev = tn;
00381 }
00382 if (tn->tn_prev) {
00383 tn->tn_prev->tn_next = tn;
00384 }
00385 else {
00386 nutTimerList = tn;
00387 }
00388 }
00389
00396 void NutTimerProcessElapsed(void)
00397 {
00398 NUTTIMERINFO *tn;
00399 u_long ticks;
00400 u_long ticks_new;
00401
00402
00403 ticks = NutGetTickCount();
00404 ticks_new = ticks - nut_ticks_resume;
00405 nut_ticks_resume = ticks;
00406
00407
00408 while (nutTimerList && ticks_new){
00409
00410 tn = nutTimerList;
00411
00412
00413 if (ticks_new < tn->tn_ticks_left) {
00414 tn->tn_ticks_left -= ticks_new;
00415 ticks_new = 0;
00416 } else {
00417 ticks_new -= tn->tn_ticks_left;
00418 tn->tn_ticks_left = 0;
00419 }
00420
00421
00422 if (tn->tn_ticks_left == 0){
00423
00424
00425 if (tn->tn_callback) {
00426 (*tn->tn_callback) (tn, (void *) tn->tn_arg);
00427 }
00428
00429 nutTimerList = nutTimerList->tn_next;
00430 if (nutTimerList) {
00431 nutTimerList->tn_prev = NULL;
00432 }
00433 if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
00434 NutHeapFree(tn);
00435 }
00436 else {
00437
00438 NutTimerInsert(tn);
00439 }
00440 }
00441 }
00442 }
00443
00463 NUTTIMERINFO * NutTimerCreate(u_long ticks, void (*callback) (HANDLE, void *), void *arg, u_char flags)
00464 {
00465 NUTTIMERINFO *tn;
00466
00467 tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
00468 if (tn) {
00469 tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
00470
00471
00472
00473
00474
00475 if (flags & TM_ONESHOT) {
00476 tn->tn_ticks = 0;
00477 } else {
00478 tn->tn_ticks = ticks;
00479 }
00480
00481
00482 tn->tn_callback = callback;
00483 tn->tn_arg = arg;
00484 }
00485 return tn;
00486 }
00487
00514 HANDLE NutTimerStartTicks(u_long ticks, void (*callback) (HANDLE, void *), void *arg, u_char flags)
00515 {
00516 NUTTIMERINFO *tn;
00517
00518 tn = NutTimerCreate( ticks, callback, arg, flags);
00519 if (tn) {
00520
00521 NutTimerInsert(tn);
00522 }
00523 return tn;
00524 }
00525
00554 HANDLE NutTimerStart(u_long ms, void (*callback) (HANDLE, void *), void *arg, u_char flags)
00555 {
00556 return NutTimerStartTicks(NutTimerMillisToTicks(ms), callback, arg, flags);
00557 }
00558
00580 void NutSleep(u_long ms)
00581 {
00582 if (ms) {
00583
00584
00585 NutThreadRemoveQueue(runningThread, &runQueue);
00586 runningThread->td_state = TDS_SLEEP;
00587
00588 if ((runningThread->td_timer = NutTimerStart(ms, NutThreadWake, runningThread, TM_ONESHOT)) != 0) {
00589 #ifdef NUTTRACER
00590 TRACE_ADD_ITEM(TRACE_TAG_THREAD_SLEEP,(int)runningThread);
00591 #endif
00592 NutThreadResume();
00593 } else
00594 {
00595
00596 runningThread->td_queue = &runQueue;
00597 runningThread->td_qnxt = runQueue;
00598 runningThread->td_state = TDS_RUNNING;
00599 runQueue = runningThread;
00600 }
00601 } else
00602 NutThreadYield();
00603 }
00604
00617 void NutTimerStop(HANDLE handle)
00618 {
00619 NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;
00620
00621
00622 tn->tn_ticks = 0;
00623 tn->tn_callback = NULL;
00624
00625 if (tn->tn_ticks_left) {
00626 if (tn->tn_prev) {
00627 tn->tn_prev->tn_next = tn->tn_next;
00628 }
00629 else {
00630 nutTimerList = tn->tn_next;
00631 }
00632 if (tn->tn_next) {
00633 tn->tn_next->tn_prev = tn->tn_prev;
00634 tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
00635 }
00636 tn->tn_ticks_left = 0;
00637 NutTimerInsert(tn);
00638 }
00639 }
00640
00649 u_long NutGetTickCount(void)
00650 {
00651 u_long rc;
00652
00653 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00654 struct timeval timeNow;
00655
00656 gettimeofday( &timeNow, NULL );
00657 rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000;
00658 rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000;
00659 #else
00660 NutEnterCritical();
00661 rc = nut_ticks;
00662 NutExitCritical();
00663 #endif
00664
00665 return rc;
00666 }
00667
00682 u_long NutGetSeconds(void)
00683 {
00684 return NutGetTickCount() / NutGetTickClock();
00685 }
00686
00703 u_long NutGetMillis(void)
00704 {
00705
00706 u_long ticks = NutGetTickCount();
00707 u_long seconds = ticks / NutGetTickClock();
00708 ticks -= seconds * NutGetTickClock();
00709 return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
00710 }
00711