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