/****************************************************************************** * * usrTimeSync - synchronize the system clock with an RTC * * This function should be called upon system initialization, after * sysClkEnable(), or any time after that repeatedly. * * NOTE: * If accurate time keeping is needed, every so often the clock resolution * can be subtly changed to reflect possible inaccuracy of the System * Clock interrupt generator, and keep the wall clock in sync with the RTC. * */ STATUS usrTimeSync (void) { struct timespec tv ; struct tm tm ; sysRtcGet( &tm ) ; tv.tv_sec = mktime( &tm ); tv.tv_nsec = 0; clock_settime( CLOCK_REALTIME, &tv ); tv.tv_sec = 0; tv.tv_nsec = 1000000000 / sysClkRateGet() ; clock_setres( CLOCK_REALTIME, &tv ); return OK ; }
CStopWatch::CStopWatch() : CMessage("CStopWatch", g_iDebugLevel, g_bDebug, g_bDebugFile), m_bStartFlag(false), m_bStopFlag(false), m_iTimeType(util_REAL_TIME) { m_iFirst = 0; m_iLast = 0; m_fOverflowTime = 0.0; #if defined(_WIN32) QueryPerformanceFrequency(&m_TempTime); // pointer to current frequency frequencyE = m_TempTime.LowPart; m_FirstTime.HighPart = 0; m_FirstTime.LowPart = 0; m_LastTime.HighPart = 0; m_LastTime.LowPart = 0; m_TempTime.HighPart = 0; m_TempTime.LowPart = 0; m_ActualTime.HighPart = 0; m_ActualTime.LowPart = 0; #elif defined(__QNX__) m_FirstTime.tv_sec = 0; m_FirstTime.tv_nsec = 0; m_LastTime.tv_sec = 0; m_LastTime.tv_nsec = 0; m_TempTime.tv_sec = 0; m_TempTime.tv_nsec = 500000; clock_setres(CLOCK_REALTIME, &m_TempTime); m_ActualTime.tv_sec = 0; m_ActualTime.tv_nsec = 0; #else m_FirstTime.tv_sec = 0; m_FirstTime.tv_usec = 0; m_LastTime.tv_sec = 0; m_LastTime.tv_usec = 0; m_TempTime.tv_sec = 0; m_TempTime.tv_usec = 0; m_ActualTime.tv_sec = 0; m_ActualTime.tv_usec = 0; #endif }
/****************************************************************************** * * usrTimeAdj - routinely adjust system time with the Real-Time Clock * */ STATUS usrTimeAdj( int interval ) { static time_t lastFreq, lastTime, lastPeriod ; FAST time_t freq, t, t1; long dif; struct tm tm ; struct timespec tv ; if( interval == 0) interval = 120 ; freq = sysClkRateGet(); FOREVER { /* sleep until the next iteration */ taskDelay( interval * freq ); taskLock() ; sysRtcGet( &tm ); freq = sysClkRateGet(); t = time (NULL); taskUnlock(); if( t == ERROR ) { char buf[48]; int i=sizeof(buf); asctime_r( &tm, buf, &i ); logMsg("mktime error %s", (int) buf, 0,0,0,0,0); } t1 = mktime( &tm ); dif = t1 - t; /* how many seconds skew */ /* logMsg("t=%d t1=%d dif=%d\n", t, t1, dif, 0,0,0); */ /* if there is a serious difference, do a step adjustment */ if ((abs(dif) > 1) || (freq != lastFreq) ) { if(usrTimeDebug) { char buf[48]; int i=sizeof(buf); asctime_r( &tm, buf, &i ); logMsg("syncing clock %s", (int) buf, 0,0,0,0,0); } usrTimeSync(); /* update statics for next iteration */ lastFreq = freq ; lastPeriod = tv.tv_nsec = 1000000000 / freq ; lastTime = time(NULL) ; } #ifdef __XXX__ else if( dif != 0) { FAST time_t tmp ; /* otherwise, gradually adjust clock to RTC speed */ tv.tv_sec = 0; /* this expression must be carefully ordered, not to * get involved with 64-bit arithmetic which is * incomplete in the current version's library. */ tmp = lastPeriod / ((t - lastTime)*freq); tv.tv_nsec += tmp * dif ; clock_setres( CLOCK_REALTIME, &tv ); if(usrTimeDebug) logMsg("dif %d old period %d ns, new period %d ns, interval %d\n", dif, lastPeriod, tv.tv_nsec, t - lastTime, 0, 0 ); /* update statics for next iteration */ lastFreq = freq ; lastPeriod = tv.tv_nsec ; lastTime = t ; } #endif /*__XXX__*/ } /* FOREVER */ }