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
00203 #include <cfg/os.h>
00204 #include <dev/irqreg.h>
00205
00206 #include <sys/types.h>
00207 #include <sys/atom.h>
00208 #include <sys/heap.h>
00209 #include <sys/thread.h>
00210 #include <sys/timer.h>
00211
00212 #ifdef NUTDEBUG
00213 #include <sys/osdebug.h>
00214 #endif
00215
00216 #ifdef NUTTRACER
00217 #include <sys/tracer.h>
00218 #endif
00219
00220 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00221 #include <sys/time.h>
00222
00223 static struct timeval timeStart;
00224 #endif
00225
00226 #include <string.h>
00227
00232
00236 NUTTIMERINFO *nutTimerList;
00237
00238
00239
00240
00241 static uint32_t nut_ticks_resume;
00242
00246 volatile uint32_t nut_ticks;
00247
00248
00249
00250 static uint32_t clock_cache[NUT_HWCLK_MAX + 1];
00251
00255 #if defined(NUT_DELAYLOOPS)
00256 volatile uint32_t nut_delay_loops = NUT_DELAYLOOPS;
00257 #else
00258 volatile uint32_t nut_delay_loops;
00259 #endif
00260
00264
00265
00269 #if !(defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__))
00270 #ifdef USE_TIMER
00271 SIGNAL( SIG_TIMER )
00272 #else
00273 static void NutTimerIntr(void *arg)
00274 #endif
00275 {
00276 nut_ticks++;
00277
00278 }
00279 #endif
00280
00281
00289 void NutTimerInit(void)
00290 {
00291 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00292 gettimeofday( &timeStart, NULL );
00293 #else
00294 NutRegisterTimer(NutTimerIntr);
00295 NutEnableTimerIrq();
00296
00297
00298 #if !defined(NUT_DELAYLOOPS)
00299 #ifndef NUT_TICK_FREQ
00300 #define NUT_TICK_FREQ 1000UL
00301 #endif
00302 {
00303
00304 uint32_t cnt = NutGetTickCount();
00305 while (cnt == NutGetTickCount());
00306
00307 cnt = NutGetTickCount();
00308 while (cnt == NutGetTickCount()) {
00309 nut_delay_loops++;
00310 }
00311
00312
00313
00314
00315
00316 nut_delay_loops *= 103UL;
00317 nut_delay_loops /= 26UL;
00318 }
00319 #endif
00320 #endif
00321 }
00322
00338 void NutMicroDelay(uint32_t us)
00339 {
00340 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00341 usleep(us);
00342 #else
00343 register uint32_t cnt = nut_delay_loops * us / 1000;
00344
00345 while (cnt--) {
00346 _NOP();
00347 }
00348 #endif
00349 }
00350
00362 void NutDelay(uint8_t ms)
00363 {
00364 NutMicroDelay((uint32_t)ms * 1000);
00365 }
00366
00376 void NutTimerInsert(NUTTIMERINFO * tn)
00377 {
00378 NUTTIMERINFO *tnp;
00379
00380 tn->tn_prev = NULL;
00381 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00382 if (tn->tn_ticks_left < tnp->tn_ticks_left) {
00383 tnp->tn_ticks_left -= tn->tn_ticks_left;
00384 break;
00385 }
00386 tn->tn_ticks_left -= tnp->tn_ticks_left;
00387 tn->tn_prev = tnp;
00388 }
00389 tn->tn_next = tnp;
00390 if (tn->tn_next) {
00391 tn->tn_next->tn_prev = tn;
00392 }
00393 if (tn->tn_prev) {
00394 tn->tn_prev->tn_next = tn;
00395 }
00396 else {
00397 nutTimerList = tn;
00398 }
00399 }
00400
00407 void NutTimerProcessElapsed(void)
00408 {
00409 NUTTIMERINFO *tn;
00410 uint32_t ticks;
00411 uint32_t ticks_new;
00412
00413
00414 ticks = NutGetTickCount();
00415 ticks_new = ticks - nut_ticks_resume;
00416 nut_ticks_resume = ticks;
00417
00418
00419 while (nutTimerList && ticks_new){
00420
00421 tn = nutTimerList;
00422
00423
00424 if (ticks_new < tn->tn_ticks_left) {
00425 tn->tn_ticks_left -= ticks_new;
00426 ticks_new = 0;
00427 } else {
00428 ticks_new -= tn->tn_ticks_left;
00429 tn->tn_ticks_left = 0;
00430 }
00431
00432
00433 if (tn->tn_ticks_left == 0){
00434
00435
00436 if (tn->tn_callback) {
00437 (*tn->tn_callback) (tn, (void *) tn->tn_arg);
00438 }
00439
00440 nutTimerList = nutTimerList->tn_next;
00441 if (nutTimerList) {
00442 nutTimerList->tn_prev = NULL;
00443 }
00444 if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
00445 NutHeapFree(tn);
00446 }
00447 else {
00448
00449 NutTimerInsert(tn);
00450 }
00451 }
00452 }
00453 }
00454
00474 NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00475 {
00476 NUTTIMERINFO *tn;
00477
00478 tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
00479 if (tn) {
00480 tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
00481
00482
00483
00484
00485
00486 if (flags & TM_ONESHOT) {
00487 tn->tn_ticks = 0;
00488 } else {
00489 tn->tn_ticks = ticks;
00490 }
00491
00492
00493 tn->tn_callback = callback;
00494 tn->tn_arg = arg;
00495 }
00496 return tn;
00497 }
00498
00525 HANDLE NutTimerStartTicks(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00526 {
00527 NUTTIMERINFO *tn;
00528
00529 tn = NutTimerCreate( ticks, callback, arg, flags);
00530 if (tn) {
00531
00532 NutTimerInsert(tn);
00533 }
00534 return tn;
00535 }
00536
00565 HANDLE NutTimerStart(uint32_t ms, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00566 {
00567 return NutTimerStartTicks(NutTimerMillisToTicks(ms), callback, arg, flags);
00568 }
00569
00591 void NutSleep(uint32_t ms)
00592 {
00593 if (ms) {
00594
00595
00596 NutThreadRemoveQueue(runningThread, &runQueue);
00597 runningThread->td_state = TDS_SLEEP;
00598
00599 if ((runningThread->td_timer = NutTimerStart(ms, NutThreadWake, runningThread, TM_ONESHOT)) != 0) {
00600 #ifdef NUTTRACER
00601 TRACE_ADD_ITEM(TRACE_TAG_THREAD_SLEEP,(int)runningThread);
00602 #endif
00603 NutThreadResume();
00604 } else
00605 {
00606
00607 runningThread->td_queue = &runQueue;
00608 runningThread->td_qnxt = runQueue;
00609 runningThread->td_state = TDS_RUNNING;
00610 runQueue = runningThread;
00611 }
00612 } else
00613 NutThreadYield();
00614 }
00615
00628 void NutTimerStop(HANDLE handle)
00629 {
00630 NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;
00631
00632
00633 tn->tn_ticks = 0;
00634 tn->tn_callback = NULL;
00635
00636 if (tn->tn_ticks_left) {
00637 if (tn->tn_prev) {
00638 tn->tn_prev->tn_next = tn->tn_next;
00639 }
00640 else {
00641 nutTimerList = tn->tn_next;
00642 }
00643 if (tn->tn_next) {
00644 tn->tn_next->tn_prev = tn->tn_prev;
00645 tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
00646 }
00647 tn->tn_ticks_left = 0;
00648 NutTimerInsert(tn);
00649 }
00650 }
00651
00660 uint32_t NutGetTickCount(void)
00661 {
00662 uint32_t rc;
00663
00664 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00665 struct timeval timeNow;
00666
00667 gettimeofday( &timeNow, NULL );
00668 rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000;
00669 rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000;
00670 #else
00671 NutEnterCritical();
00672 rc = nut_ticks;
00673 NutExitCritical();
00674 #endif
00675
00676 return rc;
00677 }
00678
00693 uint32_t NutGetSeconds(void)
00694 {
00695 return NutGetTickCount() / NutGetTickClock();
00696 }
00697
00714 uint32_t NutGetMillis(void)
00715 {
00716
00717 uint32_t ticks = NutGetTickCount();
00718 uint32_t seconds = ticks / NutGetTickClock();
00719 ticks -= seconds * NutGetTickClock();
00720 return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
00721 }
00722
00738 #if NUT_HWCLK_MAX
00739 uint32_t NutClockGet(int idx)
00740 {
00741 if (clock_cache[idx] == 0) {
00742 clock_cache[idx] = NutArchClockGet(idx) | NUT_CACHE_LVALID;
00743 }
00744 return clock_cache[idx] & ~NUT_CACHE_LVALID;
00745 }
00746 #endif
00747
00763 int NutClockSet(int idx, uint32_t freq)
00764 {
00765
00766 memset(clock_cache, 0, sizeof(clock_cache));
00767
00768 return 0;
00769 }
00770
00779 #if !defined(NutGetCpuClock)
00780 uint32_t NutGetCpuClock(void)
00781 {
00782 #ifdef NUT_CPU_FREQ
00783
00784
00785 return NUT_CPU_FREQ;
00786 #else
00787
00788
00789 if (clock_cache[NUT_HWCLK_CPU]) {
00790 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00791 }
00792 #if NUT_HWCLK_MAX
00793 return NutClockGet(NUT_HWCLK_CPU);
00794 #else
00795 clock_cache[NUT_HWCLK_CPU] = NutArchClockGet(NUT_HWCLK_CPU) | NUT_CACHE_LVALID;
00796 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00797 #endif
00798 #endif
00799 }
00800 #endif
00801