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 volatile uint32_t nut_delay_loops = NUT_DELAYLOOPS;
00266 #else
00267 volatile 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 nut_delay_loops *= 103UL;
00334 nut_delay_loops /= 26UL;
00335 }
00336 #endif
00337 #endif
00338 }
00339
00355 void NutMicroDelay(uint32_t us)
00356 {
00357 #ifdef __NUT_EMULATION__
00358 usleep(us);
00359 #else
00360 register uint32_t cnt = nut_delay_loops * us / 1000;
00361
00362 while (cnt--) {
00363 _NOP();
00364 }
00365 #endif
00366 }
00367
00379 void NutDelay(uint8_t ms)
00380 {
00381 NutMicroDelay((uint32_t)ms * 1000);
00382 }
00383
00393 void NutTimerInsert(NUTTIMERINFO * tn)
00394 {
00395 NUTTIMERINFO *tnp;
00396
00397 NUTASSERT(tn != NULL);
00398
00399 tn->tn_prev = NULL;
00400 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00401 if (tn->tn_ticks_left < tnp->tn_ticks_left) {
00402 tnp->tn_ticks_left -= tn->tn_ticks_left;
00403 break;
00404 }
00405 tn->tn_ticks_left -= tnp->tn_ticks_left;
00406 tn->tn_prev = tnp;
00407 }
00408 tn->tn_next = tnp;
00409 if (tn->tn_next) {
00410 tn->tn_next->tn_prev = tn;
00411 }
00412 if (tn->tn_prev) {
00413 tn->tn_prev->tn_next = tn;
00414 }
00415 else {
00416 nutTimerList = tn;
00417 }
00418 }
00419
00426 void NutTimerProcessElapsed(void)
00427 {
00428 NUTTIMERINFO *tn;
00429 uint32_t ticks;
00430 uint32_t ticks_new;
00431
00432
00433 ticks = NutGetTickCount();
00434 ticks_new = ticks - nut_ticks_resume;
00435 nut_ticks_resume = ticks;
00436
00437
00438 while (nutTimerList && ticks_new){
00439
00440 tn = nutTimerList;
00441
00442
00443 if (ticks_new < tn->tn_ticks_left) {
00444 tn->tn_ticks_left -= ticks_new;
00445 ticks_new = 0;
00446 } else {
00447 ticks_new -= tn->tn_ticks_left;
00448 tn->tn_ticks_left = 0;
00449 }
00450
00451
00452 if (tn->tn_ticks_left == 0){
00453
00454
00455 if (tn->tn_callback) {
00456 (*tn->tn_callback) (tn, (void *) tn->tn_arg);
00457 }
00458
00459 nutTimerList = nutTimerList->tn_next;
00460 if (nutTimerList) {
00461 nutTimerList->tn_prev = NULL;
00462 }
00463 if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
00464 NutHeapFree(tn);
00465 }
00466 else {
00467
00468 NutTimerInsert(tn);
00469 }
00470 }
00471 }
00472 }
00473
00493 NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00494 {
00495 NUTTIMERINFO *tn;
00496
00497 tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
00498 if (tn) {
00499 tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
00500
00501
00502
00503
00504
00505 if (flags & TM_ONESHOT) {
00506 tn->tn_ticks = 0;
00507 } else {
00508 tn->tn_ticks = ticks;
00509 }
00510
00511
00512 tn->tn_callback = callback;
00513 tn->tn_arg = arg;
00514 }
00515 return tn;
00516 }
00517
00544 HANDLE NutTimerStartTicks(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00545 {
00546 NUTTIMERINFO *tn;
00547
00548 tn = NutTimerCreate( ticks, callback, arg, flags);
00549 if (tn) {
00550
00551 NutTimerInsert(tn);
00552 }
00553 return tn;
00554 }
00555
00584 HANDLE NutTimerStart(uint32_t ms, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
00585 {
00586 return NutTimerStartTicks(NutTimerMillisToTicks(ms), callback, arg, flags);
00587 }
00588
00610 void NutSleep(uint32_t ms)
00611 {
00612 if (ms) {
00613
00614
00615 NutThreadRemoveQueue(runningThread, &runQueue);
00616 runningThread->td_state = TDS_SLEEP;
00617
00618 if ((runningThread->td_timer = NutTimerStart(ms, NutThreadWake, runningThread, TM_ONESHOT)) != 0) {
00619 #ifdef NUTTRACER
00620 TRACE_ADD_ITEM(TRACE_TAG_THREAD_SLEEP,(int)runningThread);
00621 #endif
00622 NutThreadResume();
00623 } else
00624 {
00625
00626 runningThread->td_queue = &runQueue;
00627 runningThread->td_qnxt = runQueue;
00628 runningThread->td_state = TDS_RUNNING;
00629 runQueue = runningThread;
00630 }
00631 } else
00632 NutThreadYield();
00633 }
00634
00647 void NutTimerStop(HANDLE handle)
00648 {
00649 NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;
00650
00651 NUTASSERT(tn != NULL);
00652
00653
00654 tn->tn_ticks = 0;
00655 tn->tn_callback = NULL;
00656
00657 if (tn->tn_ticks_left) {
00658 if (tn->tn_prev) {
00659 tn->tn_prev->tn_next = tn->tn_next;
00660 }
00661 else {
00662 nutTimerList = tn->tn_next;
00663 }
00664 if (tn->tn_next) {
00665 tn->tn_next->tn_prev = tn->tn_prev;
00666 tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
00667 }
00668 tn->tn_ticks_left = 0;
00669 NutTimerInsert(tn);
00670 }
00671 }
00672
00681 uint32_t NutGetTickCount(void)
00682 {
00683 uint32_t rc;
00684
00685 #ifdef __NUT_EMULATION__
00686 struct timeval timeNow;
00687 gettimeofday( &timeNow, NULL );
00688 rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000;
00689 rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000;
00690 #else
00691 NutEnterCritical();
00692 rc = nut_ticks;
00693 NutExitCritical();
00694 #endif
00695
00696 return rc;
00697 }
00698
00713 uint32_t NutGetSeconds(void)
00714 {
00715 return NutGetTickCount() / NutGetTickClock();
00716 }
00717
00734 uint32_t NutGetMillis(void)
00735 {
00736
00737 uint32_t ticks = NutGetTickCount();
00738 uint32_t seconds = ticks / NutGetTickClock();
00739 ticks -= seconds * NutGetTickClock();
00740 return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
00741 }
00742
00758 #if NUT_HWCLK_MAX
00759 uint32_t NutClockGet(int idx)
00760 {
00761 if (clock_cache[idx] == 0) {
00762 clock_cache[idx] = NutArchClockGet(idx) | NUT_CACHE_LVALID;
00763 }
00764 return clock_cache[idx] & ~NUT_CACHE_LVALID;
00765 }
00766 #endif
00767
00783 int NutClockSet(int idx, uint32_t freq)
00784 {
00785
00786 memset(clock_cache, 0, sizeof(clock_cache));
00787
00788 return 0;
00789 }
00790
00799 #if !defined(NutGetCpuClock)
00800 uint32_t NutGetCpuClock(void)
00801 {
00802 #ifdef NUT_CPU_FREQ
00803
00804
00805 return NUT_CPU_FREQ;
00806 #else
00807
00808
00809 if (clock_cache[NUT_HWCLK_CPU]) {
00810 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00811 }
00812 #if NUT_HWCLK_MAX
00813 return NutClockGet(NUT_HWCLK_CPU);
00814 #else
00815 clock_cache[NUT_HWCLK_CPU] = NutArchClockGet(NUT_HWCLK_CPU) | NUT_CACHE_LVALID;
00816 return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
00817 #endif
00818 #endif
00819 }
00820 #endif
00821