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
00209 #include <cfg/os.h>
00210 #include <dev/irqreg.h>
00211
00212 #include <sys/types.h>
00213 #include <sys/atom.h>
00214 #include <sys/heap.h>
00215 #include <sys/thread.h>
00216 #include <sys/timer.h>
00217 #include <sys/nutdebug.h>
00218
00219 #ifdef NUTDEBUG
00220 #include <sys/osdebug.h>
00221 #endif
00222
00223 #ifdef NUTTRACER
00224 #include <sys/tracer.h>
00225 #endif
00226
00227 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00228 #include <sys/time.h>
00229
00230 static struct timeval timeStart;
00231 #endif
00232
00233 #include <string.h>
00234
00239
00243 NUTTIMERINFO *nutTimerList;
00244
00245
00246
00247
00248 static uint32_t nut_ticks_resume;
00249
00253 volatile uint32_t nut_ticks;
00254
00255
00256
00257 static uint32_t clock_cache[NUT_HWCLK_MAX + 1];
00258
00262 #if defined(NUT_DELAYLOOPS)
00263 volatile uint32_t nut_delay_loops = NUT_DELAYLOOPS;
00264 #else
00265 volatile uint32_t nut_delay_loops;
00266 #endif
00267
00271
00272
00276 #if !(defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__))
00277 #ifdef USE_TIMER
00278 SIGNAL( SIG_TIMER )
00279 #else
00280 static void NutTimerIntr(void *arg)
00281 #endif
00282 {
00283 nut_ticks++;
00284
00285 #ifdef NUTDEBUG_CHECK_STACKMIN
00286 if((nut_ticks % 1000) == 0) {
00287 NUTTHREADINFO *tdp = NutThreadStackCheck(NUTDEBUG_CHECK_STACKMIN);
00288 if (tdp) {
00289 NUTFATAL(tdp->td_name, __FILE__, __LINE__, "more stack space");
00290 }
00291 }
00292 #endif
00293 }
00294 #endif
00295
00296
00304 void NutTimerInit(void)
00305 {
00306 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00307 gettimeofday( &timeStart, NULL );
00308 #else
00309 NutRegisterTimer(NutTimerIntr);
00310 NutEnableTimerIrq();
00311
00312
00313 #if !defined(NUT_DELAYLOOPS)
00314 #ifndef NUT_TICK_FREQ
00315 #define NUT_TICK_FREQ 1000UL
00316 #endif
00317 {
00318
00319 uint32_t cnt = NutGetTickCount();
00320 while (cnt == NutGetTickCount());
00321
00322 cnt = NutGetTickCount();
00323 while (cnt == NutGetTickCount()) {
00324 nut_delay_loops++;
00325 }
00326
00327
00328
00329
00330
00331 nut_delay_loops *= 103UL;
00332 nut_delay_loops /= 26UL;
00333 }
00334 #endif
00335 #endif
00336 }
00337
00353 void NutMicroDelay(uint32_t us)
00354 {
00355 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00356 usleep(us);
00357 #else
00358 register uint32_t cnt = nut_delay_loops * us / 1000;
00359
00360 while (cnt--) {
00361 _NOP();
00362 }
00363 #endif
00364 }
00365
00377 void NutDelay(uint8_t ms)
00378 {
00379 NutMicroDelay((uint32_t)ms * 1000);
00380 }
00381
00391 void NutTimerInsert(NUTTIMERINFO * tn)
00392 {
00393 NUTTIMERINFO *tnp;
00394
00395 NUTASSERT(tn != NULL);
00396
00397 tn->tn_prev = NULL;
00398 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00399 if (tn->tn_ticks_left < tnp->tn_ticks_left) {
00400 tnp->tn_ticks_left -= tn->tn_ticks_left;
00401 break;
00402 }
00403 tn->tn_ticks_left -= tnp->tn_ticks_left;
00404 tn->tn_prev = tnp;
00405 }
00406 tn->tn_next = tnp;
00407 if (tn->tn_next) {
00408 tn->tn_next->tn_prev = tn;
00409 }
00410 if (tn->tn_prev) {
00411 tn->tn_prev->tn_next = tn;
00412 }
00413 else {
00414 nutTimerList = tn;
00415 }
00416 }
00417
00424 void NutTimerProcessElapsed(void)
00425 {
00426 NUTTIMERINFO *tn;
00427 uint32_t ticks;
00428 uint32_t ticks_new;
00429
00430
00431 ticks = NutGetTickCount();
00432 ticks_new = ticks - nut_ticks_resume;
00433 nut_ticks_resume = ticks;
00434
00435
00436 while (nutTimerList && ticks_new){
00437
00438 tn = nutTimerList;
00439
00440
00441 if (ticks_new < tn->tn_ticks_left) {
00442 tn->tn_ticks_left -= ticks_new;
00443 ticks_new = 0;
00444 } else {
00445 ticks_new -= tn->tn_ticks_left;
00446 tn->tn_ticks_left = 0;
00447 }
00448
00449
00450 if (tn->tn_ticks_left == 0){
00451
00452
00453 if (tn->tn_callback) {
00454 (*tn->tn_callback) (tn, (void *) tn->tn_arg);
00455 }
00456
00457 nutTimerList = nutTimerList->tn_next;
00458 if (nutTimerList) {
00459 nutTimerList->tn_prev = NULL;
00460 }
00461 if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
00462 NutHeapFree(tn);
00463 }
00464 else {
00465
00466 NutTimerInsert(tn);
00467 }
00468 }
00469 }
00470 }
00471
00491 NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00492 {
00493 NUTTIMERINFO *tn;
00494
00495 tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
00496 if (tn) {
00497 tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
00498
00499
00500
00501
00502
00503 if (flags & TM_ONESHOT) {
00504 tn->tn_ticks = 0;
00505 } else {
00506 tn->tn_ticks = ticks;
00507 }
00508
00509
00510 tn->tn_callback = callback;
00511 tn->tn_arg = arg;
00512 }
00513 return tn;
00514 }
00515
00542 HANDLE NutTimerStartTicks(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00543 {
00544 NUTTIMERINFO *tn;
00545
00546 tn = NutTimerCreate( ticks, callback, arg, flags);
00547 if (tn) {
00548
00549 NutTimerInsert(tn);
00550 }
00551 return tn;
00552 }
00553
00582 HANDLE NutTimerStart(uint32_t ms, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00583 {
00584 return NutTimerStartTicks(NutTimerMillisToTicks(ms), callback, arg, flags);
00585 }
00586
00608 void NutSleep(uint32_t ms)
00609 {
00610 if (ms) {
00611
00612
00613 NutThreadRemoveQueue(runningThread, &runQueue);
00614 runningThread->td_state = TDS_SLEEP;
00615
00616 if ((runningThread->td_timer = NutTimerStart(ms, NutThreadWake, runningThread, TM_ONESHOT)) != 0) {
00617 #ifdef NUTTRACER
00618 TRACE_ADD_ITEM(TRACE_TAG_THREAD_SLEEP,(int)runningThread);
00619 #endif
00620 NutThreadResume();
00621 } else
00622 {
00623
00624 runningThread->td_queue = &runQueue;
00625 runningThread->td_qnxt = runQueue;
00626 runningThread->td_state = TDS_RUNNING;
00627 runQueue = runningThread;
00628 }
00629 } else
00630 NutThreadYield();
00631 }
00632
00645 void NutTimerStop(HANDLE handle)
00646 {
00647 NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;
00648
00649 NUTASSERT(tn != NULL);
00650
00651
00652 tn->tn_ticks = 0;
00653 tn->tn_callback = NULL;
00654
00655 if (tn->tn_ticks_left) {
00656 if (tn->tn_prev) {
00657 tn->tn_prev->tn_next = tn->tn_next;
00658 }
00659 else {
00660 nutTimerList = tn->tn_next;
00661 }
00662 if (tn->tn_next) {
00663 tn->tn_next->tn_prev = tn->tn_prev;
00664 tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
00665 }
00666 tn->tn_ticks_left = 0;
00667 NutTimerInsert(tn);
00668 }
00669 }
00670
00679 uint32_t NutGetTickCount(void)
00680 {
00681 uint32_t rc;
00682
00683 #if defined (__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00684 struct timeval timeNow;
00685
00686 gettimeofday( &timeNow, NULL );
00687 rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000;
00688 rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000;
00689 #else
00690 NutEnterCritical();
00691 rc = nut_ticks;
00692 NutExitCritical();
00693 #endif
00694
00695 return rc;
00696 }
00697
00712 uint32_t NutGetSeconds(void)
00713 {
00714 return NutGetTickCount() / NutGetTickClock();
00715 }
00716
00733 uint32_t NutGetMillis(void)
00734 {
00735
00736 uint32_t ticks = NutGetTickCount();
00737 uint32_t seconds = ticks / NutGetTickClock();
00738 ticks -= seconds * NutGetTickClock();
00739 return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
00740 }
00741
00757 #if NUT_HWCLK_MAX
00758 uint32_t NutClockGet(int idx)
00759 {
00760 if (clock_cache[idx] == 0) {
00761 clock_cache[idx] = NutArchClockGet(idx) | NUT_CACHE_LVALID;
00762 }
00763 return clock_cache[idx] & ~NUT_CACHE_LVALID;
00764 }
00765 #endif
00766
00782 int NutClockSet(int idx, uint32_t freq)
00783 {
00784
00785 memset(clock_cache, 0, sizeof(clock_cache));
00786
00787 return 0;
00788 }
00789
00798 #if !defined(NutGetCpuClock)
00799 uint32_t NutGetCpuClock(void)
00800 {
00801 #ifdef NUT_CPU_FREQ
00802
00803
00804 return NUT_CPU_FREQ;
00805 #else
00806
00807
00808 if (clock_cache[NUT_HWCLK_CPU]) {
00809 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00810 }
00811 #if NUT_HWCLK_MAX
00812 return NutClockGet(NUT_HWCLK_CPU);
00813 #else
00814 clock_cache[NUT_HWCLK_CPU] = NutArchClockGet(NUT_HWCLK_CPU) | NUT_CACHE_LVALID;
00815 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00816 #endif
00817 #endif
00818 }
00819 #endif
00820