Go to the documentation of this file.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
00212 #include <cfg/os.h>
00213 #include <dev/irqreg.h>
00214
00215 #include <sys/types.h>
00216 #include <sys/atom.h>
00217 #include <sys/heap.h>
00218 #include <sys/thread.h>
00219 #include <sys/timer.h>
00220 #include <sys/nutdebug.h>
00221
00222 #ifdef NUTDEBUG
00223 #include <sys/osdebug.h>
00224 #endif
00225
00226 #ifdef NUTTRACER
00227 #include <sys/tracer.h>
00228 #endif
00229
00230 #ifdef __NUT_EMULATION__
00231 #include <sys/time.h>
00232 static struct timeval timeStart;
00233 #endif
00234
00235 #include <string.h>
00236
00241
00245 NUTTIMERINFO *nutTimerList;
00246
00247
00248
00249
00250 static uint32_t nut_ticks_resume;
00251
00255 volatile uint32_t nut_ticks;
00256
00257
00258
00259 static uint32_t clock_cache[NUT_HWCLK_MAX + 1];
00260
00264 #if defined(NUT_DELAYLOOPS)
00265 uint32_t nut_delay_loops = NUT_DELAYLOOPS;
00266 #else
00267 uint32_t nut_delay_loops;
00268 #endif
00269
00273
00274
00278 #ifndef __NUT_EMULATION__
00279 #ifdef USE_TIMER
00280 SIGNAL( SIG_TIMER )
00281 #else
00282 static void NutTimerIntr(void *arg)
00283 #endif
00284 {
00285 nut_ticks++;
00286
00287 #ifdef NUTDEBUG_CHECK_STACKMIN
00288 if((nut_ticks % 1000) == 0) {
00289 NUTTHREADINFO *tdp = NutThreadStackCheck(NUTDEBUG_CHECK_STACKMIN);
00290 if (tdp) {
00291 NUTFATAL(tdp->td_name, __FILE__, __LINE__, "more stack space");
00292 }
00293 }
00294 #endif
00295 }
00296 #endif
00297
00298
00306 void NutTimerInit(void)
00307 {
00308 #ifdef __NUT_EMULATION__
00309 gettimeofday( &timeStart, NULL );
00310 #else
00311 NutRegisterTimer(NutTimerIntr);
00312 NutEnableTimerIrq();
00313
00314
00315 #if !defined(NUT_DELAYLOOPS)
00316 #ifndef NUT_TICK_FREQ
00317 #define NUT_TICK_FREQ 1000UL
00318 #endif
00319 {
00320
00321 uint32_t cnt = NutGetTickCount();
00322 while (cnt == NutGetTickCount());
00323
00324 cnt = NutGetTickCount();
00325 while (cnt == NutGetTickCount()) {
00326 nut_delay_loops++;
00327 }
00328
00329
00330
00331
00332
00333 #if defined(__AVR__)
00334 nut_delay_loops *= 103UL;
00335 nut_delay_loops /= 26UL;
00336 #else
00337 nut_delay_loops *= 137UL;
00338 nut_delay_loops /= 25UL;
00339 #endif
00340 }
00341 #endif
00342 #endif
00343 }
00344
00373 void NutMicroDelay(uint32_t us)
00374 {
00375 #ifdef __NUT_EMULATION__
00376 usleep(us);
00377 #else
00378 register uint32_t cnt = nut_delay_loops * us / 1000;
00379
00380 while (cnt--) {
00381 _NOP();
00382 }
00383 #endif
00384 }
00385
00397 void NutDelay(uint8_t ms)
00398 {
00399 NutMicroDelay((uint32_t)ms * 1000);
00400 }
00401
00411 void NutTimerInsert(NUTTIMERINFO * tn)
00412 {
00413 NUTTIMERINFO *tnp;
00414
00415 NUTASSERT(tn != NULL);
00416
00417 tn->tn_prev = NULL;
00418 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00419 if (tn->tn_ticks_left < tnp->tn_ticks_left) {
00420 tnp->tn_ticks_left -= tn->tn_ticks_left;
00421 break;
00422 }
00423 tn->tn_ticks_left -= tnp->tn_ticks_left;
00424 tn->tn_prev = tnp;
00425 }
00426 tn->tn_next = tnp;
00427 if (tn->tn_next) {
00428 tn->tn_next->tn_prev = tn;
00429 }
00430 if (tn->tn_prev) {
00431 tn->tn_prev->tn_next = tn;
00432 }
00433 else {
00434 nutTimerList = tn;
00435 }
00436 }
00437
00444 void NutTimerProcessElapsed(void)
00445 {
00446 NUTTIMERINFO *tn;
00447 uint32_t ticks;
00448 uint32_t ticks_new;
00449
00450
00451 ticks = NutGetTickCount();
00452 ticks_new = ticks - nut_ticks_resume;
00453 nut_ticks_resume = ticks;
00454
00455
00456 while (nutTimerList && ticks_new){
00457
00458 tn = nutTimerList;
00459
00460
00461 if (ticks_new < tn->tn_ticks_left) {
00462 tn->tn_ticks_left -= ticks_new;
00463 ticks_new = 0;
00464 } else {
00465 ticks_new -= tn->tn_ticks_left;
00466 tn->tn_ticks_left = 0;
00467 }
00468
00469
00470 if (tn->tn_ticks_left == 0){
00471
00472
00473 if (tn->tn_callback) {
00474 (*tn->tn_callback) (tn, (void *) tn->tn_arg);
00475 }
00476
00477 nutTimerList = nutTimerList->tn_next;
00478 if (nutTimerList) {
00479 nutTimerList->tn_prev = NULL;
00480 }
00481 if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
00482 NutHeapFree(tn);
00483 }
00484 else {
00485
00486 NutTimerInsert(tn);
00487 }
00488 }
00489 }
00490 }
00491
00511 NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00512 {
00513 NUTTIMERINFO *tn;
00514
00515 tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
00516 if (tn) {
00517 tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
00518
00519
00520
00521
00522
00523 if (flags & TM_ONESHOT) {
00524 tn->tn_ticks = 0;
00525 } else {
00526 tn->tn_ticks = ticks;
00527 }
00528
00529
00530 tn->tn_callback = callback;
00531 tn->tn_arg = arg;
00532 }
00533 return tn;
00534 }
00535
00562 HANDLE NutTimerStartTicks(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00563 {
00564 NUTTIMERINFO *tn;
00565
00566 tn = NutTimerCreate( ticks, callback, arg, flags);
00567 if (tn) {
00568
00569 NutTimerInsert(tn);
00570 }
00571 return tn;
00572 }
00573
00602 HANDLE NutTimerStart(uint32_t ms, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00603 {
00604 return NutTimerStartTicks(NutTimerMillisToTicks(ms), callback, arg, flags);
00605 }
00606
00628 void NutSleep(uint32_t ms)
00629 {
00630 if (ms) {
00631
00632
00633 NutThreadRemoveQueue(runningThread, &runQueue);
00634 runningThread->td_state = TDS_SLEEP;
00635
00636 if ((runningThread->td_timer = NutTimerStart(ms, NutThreadWake, runningThread, TM_ONESHOT)) != 0) {
00637 #ifdef NUTTRACER
00638 TRACE_ADD_ITEM(TRACE_TAG_THREAD_SLEEP,(int)runningThread);
00639 #endif
00640 NutThreadResume();
00641 } else
00642 {
00643
00644 runningThread->td_queue = &runQueue;
00645 runningThread->td_qnxt = runQueue;
00646 runningThread->td_state = TDS_RUNNING;
00647 runQueue = runningThread;
00648 }
00649 } else
00650 NutThreadYield();
00651 }
00652
00665 void NutTimerStop(HANDLE handle)
00666 {
00667 NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;
00668
00669 NUTASSERT(tn != NULL);
00670
00671
00672 tn->tn_ticks = 0;
00673 tn->tn_callback = NULL;
00674
00675 if (tn->tn_ticks_left) {
00676 if (tn->tn_prev) {
00677 tn->tn_prev->tn_next = tn->tn_next;
00678 }
00679 else {
00680 nutTimerList = tn->tn_next;
00681 }
00682 if (tn->tn_next) {
00683 tn->tn_next->tn_prev = tn->tn_prev;
00684 tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
00685 }
00686 tn->tn_ticks_left = 0;
00687 NutTimerInsert(tn);
00688 }
00689 }
00690
00699 uint32_t NutGetTickCount(void)
00700 {
00701 uint32_t rc;
00702
00703 #ifdef __NUT_EMULATION__
00704 struct timeval timeNow;
00705 gettimeofday( &timeNow, NULL );
00706 rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000;
00707 rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000;
00708 #else
00709 NutEnterCritical();
00710 rc = nut_ticks;
00711 NutExitCritical();
00712 #endif
00713
00714 return rc;
00715 }
00716
00731 uint32_t NutGetSeconds(void)
00732 {
00733 return NutGetTickCount() / NutGetTickClock();
00734 }
00735
00752 uint32_t NutGetMillis(void)
00753 {
00754
00755 uint32_t ticks = NutGetTickCount();
00756 uint32_t seconds = ticks / NutGetTickClock();
00757 ticks -= seconds * NutGetTickClock();
00758 return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
00759 }
00760
00776 #if NUT_HWCLK_MAX
00777 uint32_t NutClockGet(int idx)
00778 {
00779 if (clock_cache[idx] == 0) {
00780 clock_cache[idx] = NutArchClockGet(idx) | NUT_CACHE_LVALID;
00781 }
00782 return clock_cache[idx] & ~NUT_CACHE_LVALID;
00783 }
00784 #endif
00785
00801 int NutClockSet(int idx, uint32_t freq)
00802 {
00803
00804 memset(clock_cache, 0, sizeof(clock_cache));
00805
00806 return 0;
00807 }
00808
00817 #if !defined(NutGetCpuClock)
00818 uint32_t NutGetCpuClock(void)
00819 {
00820 #ifdef NUT_CPU_FREQ
00821
00822
00823 return NUT_CPU_FREQ;
00824 #else
00825
00826
00827 if (clock_cache[NUT_HWCLK_CPU]) {
00828 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00829 }
00830 #if NUT_HWCLK_MAX
00831 return NutClockGet(NUT_HWCLK_CPU);
00832 #else
00833 clock_cache[NUT_HWCLK_CPU] = NutArchClockGet(NUT_HWCLK_CPU) | NUT_CACHE_LVALID;
00834 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00835 #endif
00836 #endif
00837 }
00838 #endif
00839