📄 rvtimestamp.c
字号:
}
/* Set up a background process to wait the proper amount of */
/* time then signal the interrupt process to do the work. It */
/* doesn't hurt performance and doesn't have a problem unless */
/* the system always runs at 100% (over a period of weeks). */
OS_PROCESS(RvTimeCheckWait)
{
for(;;) {
delay(RvWrapcheckMs);
signal_fsem(RvWrapCheck);
}
}
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_NUCLEUS)
/* Called by periodic timer */
static VOID RvTimeCheckWrap(UNSIGNED param)
{
UNSIGNED cur_tick;
INT old_level;
/* Timer runs at lowest HISR level so make sure we don't switch */
old_level = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);
cur_tick = NU_Retrieve_Clock();
if(cur_tick < RvLastTick)
RvWrapCount += 1;
RvLastTick = cur_tick;
NU_Local_Control_Interrupts(old_level);
}
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_USER_DEFINED)
/* Called for us by user timestamp driver when wrap occurs */
static void RvTimeCheckWrap(void)
{
RvHiresCount += (RvInt64)RvUserTimestampPeriod();
}
#endif
/* Get a high resolution relative time stamp. This value will never */
/* go backwards. This value returned is in nanoseconds and will never wrap */
/* (at least for about 290 years). */
RVCOREAPI RvInt64 RVCALLCONV RvTimestampGet(void)
{
RvInt64 result;
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_POSIX)
struct timespec tp;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_LINUX)
unsigned long eax,edx;
RvInt64 tickcount;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_WIN32)
LARGE_INTEGER PerformanceCount;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_TIMESTAMP)
RvInt64 tickcount, lastcount_copy1, lastcount_copy2;
ULONG laststamp_copy;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_NORMAL)
long long tickcount;
long wrapcount_copy;
ULONG cur_tick, lasttick_copy1, lasttick_copy2;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_PSOS)
#if (RV_TOOL_TYPE == RV_TOOL_TYPE_CADUL) && (RV_OS_VERSION == RV_OS_PSOS_2_0)
/* we detour the lack of 64 bit (long long) support in psos v2.0, by
using the compiler (CADUL) ability to transfer all his 'long' types to 64 bit. */
long tickcount;
unsigned int tickshi, tickslo;
#else
long long tickcount;
unsigned long tickshi, tickslo;
#endif
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_OSE)
long wrapcount_copy;
long long tickcount;
OSTICK micro, cur_tick, lasttick_copy1, lasttick_copy2;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_NUCLEUS)
long long tickcount;
long wrapcount_copy;
UNSIGNED cur_tick, lasttick_copy1, lasttick_copy2;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_UNIXWARE)
struct timeval tv; /* timeval structure */
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_EMBLINUX)
struct timeval {
long tv_sec; /* timeval structure */ /*h.e ??? */
long tv_usec;
};
struct timeval tv;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_USER_DEFINED)
RvInt64 tickcount, lastcount_copy1, lastcount_copy2, laststamp_copy;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_SOLARIS)
result = (RvInt64)gethrtime();
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_POSIX)
clock_gettime(CLOCK_REALTIME, &tp);
result = ((tp.tv_sec - RvStartingTime) * RV_TIME64_NSECPERSEC) + tp.tv_nsec;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_LINUX)
rdtsc(eax,edx);
tickcount = (RvInt64)edx * (RvInt64)ULONG_MAX + (RvInt64)edx + (RvInt64)eax;
/* convert to nanosecs and maintain resolution, works up to about */
/* a 9 gigaherz clock */
result = (tickcount / RvTickHz) * RV_TIME64_NSECPERSEC;
result += (((tickcount % RvTickHz) * RV_TIME64_NSECPERSEC) / RvTickHz);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_EMBLINUX)
gettimeofday(&tv, NULL);
result = ((RvInt64)tv.tv_sec * RV_TIME64_NSECPERSEC) + ((RvInt64)tv.tv_usec * RV_TIME64_NSECPERUSEC);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_WIN32)
QueryPerformanceCounter(&PerformanceCount);
/* convert to nanosecs and maintain resolution */
result = (PerformanceCount.QuadPart / RvTickHz) * RV_TIME64_NSECPERSEC;
result += (((PerformanceCount.QuadPart % RvTickHz) * RV_TIME64_NSECPERSEC) / RvTickHz);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_TIMESTAMP)
/* Get hires count and timestamp without locking */
do {
lastcount_copy1 = RvHiresCount;
laststamp_copy = sysTimestampLock();
lastcount_copy2= RvHiresCount;
} while(lastcount_copy1 != lastcount_copy2);
tickcount = lastcount_copy1 + (RvInt64)laststamp_copy;
result = (tickcount / RvTickHz) * RV_TIME64_NSECPERSEC;
result += (((tickcount % RvTickHz) * RV_TIME64_NSECPERSEC) / RvTickHz);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_NORMAL)
/* Clock tick is only 32 bits, check for wrap without locking */
do {
lasttick_copy1 = RvLastTick;
wrapcount_copy = RvWrapCount;
lasttick_copy2 = RvLastTick;
} while (lasttick_copy1 != lasttick_copy2); /* max 2 loops */
cur_tick = tickGet();
if(cur_tick < lasttick_copy1)
wrapcount_copy += 1;
tickcount = (RvInt64)cur_tick + (RvInt64)wrapcount_copy * (RvInt64)WRAP_TICKS;
result = (tickcount / RvTickHz) * RV_TIME64_NSECPERSEC;
result += (((tickcount % RvTickHz) * RV_TIME64_NSECPERSEC) / RvTickHz);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_PSOS)
#if (RV_OS_VERSION == RV_OS_PSOS_2_0)
ULONG date;
ULONG time;
ULONG ticks;
ULONG day;
ULONG month;
ULONG cur_time;
static ULONG start_time = 0l;
#define PSOS_CLOCKS_PER_SEC 1000
/* tm_get() resolution:
date Specifies the clock date. date is encoded as follows:
Field Bits
Year, A.D. 31-16
Month (1-12) 15-8
Day (1-31) 7-0
time Specifies the clock time. time is encoded as follows:
Field Bits
Hour (0-23) 31-16
Minute (0-59) 15-8
Second (0-59) 7-0*/
if (!tm_get(&date, &time, &ticks))
return RvTimestampErrorCode(RV_ERROR_UNKNOWN);
month= ((date>>8 )&0x000000FF);
day = ((date )&0x000000FF);
if (!month) month = 1;
if (!day) day = 1;
if (!start_time)
start_time = Rv64Multiply(((time >> 16)&0x0000FFFF),3600) + Rv64Multiply(((time>>8)&0x000000FF),60) + (time&0x000000FF);
cur_time = Rv64Multiply(((time >> 16)&0x0000FFFF),3600) + Rv64Multiply(((time>>8)&0x000000FF),60) + (time&0x000000FF)+Rv64Multiply((day-1),86400) + Rv64Multiply((month-1),2678400);
tickcount = Rv64Multiply(Rv64Divide(ticks, PSOS_CLOCKS_PER_SEC), RV_TIME64_NSECPERSEC) +
Rv64Divide(Rv64Multiply(Rv64Modulu(ticks, PSOS_CLOCKS_PER_SEC), RV_TIME64_NSECPERSEC), PSOS_CLOCKS_PER_SEC);
result = Rv64Multiply((cur_time - start_time), RV_TIME64_NSECPERSEC) + tickcount;
#else
tm_getticks(&tickshi, &tickslo);
tickcount = Rv64Multiply((RvInt64)tickshi, RV_INT64_MAX) + (RvInt64)tickshi + (RvInt64)tickslo;
result = Rv64Multiply(Rv64Divide(tickcount, RvTickHz), RV_TIME64_NSECPERSEC);
result += Rv64Divide(Rv64Multiply(Rv64Modulu(tickcount, RvTickHz), RV_TIME64_NSECPERSEC), RvTickHz);
#endif
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_OSE)
/* Clock tick is only 32 bits, check for wrap without locking */
do {
lasttick_copy1 = RvLastTick;
wrapcount_copy = RvWrapCount;
lasttick_copy2 = RvLastTick;
} while (lasttick_copy1 != lasttick_copy2); /* max 2 loops */
cur_tick = get_systime(µ);
if(cur_tick < lasttick_copy1)
wrapcount_copy += 1;
tickcount = (RvInt64)cur_tick + (RvInt64)wrapcount_copy * (RvInt64)WRAP_TICKS;
result = tickcount * RvTickPeriod + ((RvInt64)micro * RvInt64Const(1000));
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_NUCLEUS)
/* Clock tick is only 32 bits, check for wrap without locking */
do {
lasttick_copy1 = RvLastTick;
wrapcount_copy = RvWrapCount;
lasttick_copy2 = RvLastTick;
} while (lasttick_copy1 != lasttick_copy2); /* max 2 loops */
cur_tick = NU_Retrieve_Clock();
if(cur_tick < lasttick_copy1)
wrapcount_copy += 1;
tickcount = (RvInt64)cur_tick + (RvInt64)wrapcount_copy * (RvInt64)WRAP_TICKS;
result = (tickcount / RvTickHz) * RV_TIME64_NSECPERSEC;
result += (((tickcount % RvTickHz) * RV_TIME64_NSECPERSEC) / RvTickHz);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_UNIXWARE)
/* We don't use a good clock on UnixWare since we can't find it... */
gettimeofday(&tv, NULL);
result = ((RvInt64)tv.tv_sec * RV_TIME64_NSECPERSEC) + ((RvInt64)tv.tv_usec * RV_TIME64_NSECPERUSEC);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_USER_DEFINED)
/* Get hires count and timestamp without using a lock */
do {
lastcount_copy1 = RvHiresCount;
laststamp_copy = (RvInt64)RvUserTimestampGet();
lastcount_copy2= RvHiresCount;
} while(lastcount_copy1 != lastcount_copy2);
tickcount = lastcount_copy1 + laststamp_copy;
result = (tickcount / RvTickHz) * RV_TIME64_NSECPERSEC;
result += (((tickcount % RvTickHz) * RV_TIME64_NSECPERSEC) / RvTickHz);
#endif
return result;
}
/* Returns resolution of high resolution in nanoseconds. */
RvInt64 RvTimestampResolution(void)
{
RvInt64 result;
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_SOLARIS) || (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_POSIX)
RvTime t;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_POSIX)
clock_getres(CLOCK_REALTIME, (struct timespec *)&t);
result = RvTimeConvertTo64(&t);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_SOLARIS)
#if defined(CLOCK_HIGHRES) /* If CLOCK_HIGHRES isn't defined, then it is pre Solaris 8 */
clock_getres(CLOCK_HIGHRES, (struct timespec *)&t);
#else
/* Solaris 2.6 and 7 don't have a way to find the resolution of the
* hires timer. The wall clock resolution will be no worse, so its
* the best we can do. */
clock_getres(CLOCK_REALTIME, (struct timespec *)&t);
#endif
result = RvTimeConvertTo64(&t);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_LINUX) || (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_NORMAL) || \
(RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_TIMESTAMP) || (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_PSOS) || \
(RV_TIMESTAMP_TYPE == RV_TIMESTAMP_NUCLEUS) || (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_WIN32) || \
(RV_TIMESTAMP_TYPE == RV_TIMESTAMP_USER_DEFINED)
if(RvTickHz > RvInt64Const(1))
{
result = Rv64Divide(RV_TIME64_NSECPERSEC, RvTickHz);
}
else
result = RV_TIME64_NSECPERSEC;
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_OSE)
/* OSE never tells us the sub-tick resolution so return ticks */
result = RvTickPeriod;
#endif
return result;
}
#if defined(RV_TEST_CODE)
#include "rv64ascii.h"
#include "rvstdio.h"
void RvTimestampTest(void)
{
RvStatus result;
RvChar buf[RV_64TOASCII_BUFSIZE], inputbuf[81];
RvInt64 res64;
RvInt64 stamp;
RvPrintf("Starting test of rvtimestamp.\n");
/* Initialize needed modules */
Rv64AsciiInit();
result = RvTimestampInit();
if(result == RV_OK) {
RvPrintf("RvTimestampInit successful.\n");
} else RvPrintf("RvTimestampInit failed. Error = %d\n", result);
RvPrintf("Saved information:\n");
#if (RV_TIMESTAMP_TYPE != RV_TIMESTAMP_OSE) && (RV_TIMESTAMP_TYPE != RV_TIMESTAMP_SOLARIS) && \
(RV_TIMESTAMP_TYPE != RV_TIMESTAMP_POSIX) && (RV_TIMESTAMP_TYPE != RV_TIMESTAMP_UNIXWARE) && \
(RV_TIMESTAMP_TYPE != RV_TIMESTAMP_EMBLINUX)
Rv64toA(buf, RvTickHz);
RvPrintf(" RvTickHz = %s\n", buf);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_NORMAL) || (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_OSE) || \
(RV_TIMESTAMP_TYPE == RV_TIMESTAMP_NUCLEUS)
RvPrintf(" RvWrapCount = %d\n", RvWrapCount);
RvPrintf(" RvLastTick = %lu\n", RvLastTick);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_TIMESTAMP)
Rv64UtoA(buf, RvHiresCount);
RvPrintf(" RvHiresCount = %s\n", buf);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_OSE)
Rv64toA(buf, RvTickPeriod);
RvPrintf(" RvTickPeriod = %s\n", buf);
RvPrintf(" RvWrapcheckMs = %d\n", RvWrapcheckMs);
#endif
res64 = RvTimestampResolution();
Rv64toA(buf, res64);
RvPrintf("RvTimestampResolution = %s\n", buf);
stamp = RvTimestampGet();
Rv64toA(buf, stamp);
RvPrintf("RvTimestampGet = %s\n", buf);
/* Let user wait for some time to pass */
RvPrintf("\nWait a few seconds and then press ENTER (optionally change system clock): ");
fflush(stdout);
fflush(stdin);
fgets(inputbuf, sizeof(inputbuf), stdin);
RvPrintf("\n");
stamp = RvTimestampGet();
Rv64toA(buf, stamp);
RvPrintf("RvTimestampGet = %s\n", buf);
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_NORMAL) || (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_OSE) || \
(RV_TIMESTAMP_TYPE == RV_TIMESTAMP_NUCLEUS)
RvPrintf(" RvWrapCount = %d\n", RvWrapCount);
RvPrintf(" RvLastTick = %lu\n", RvLastTick);
#endif
#if (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_VXWORKS_TIMESTAMP) || (RV_TIMESTAMP_TYPE == RV_TIMESTAMP_USER_DEFINED)
Rv64UtoA(buf, RvHiresCount);
RvPrintf(" RvHiresCount = %s\n", buf);
#endif
result = RvTimestampEnd();
if(result == RV_OK) {
RvPrintf("RvTimestampEnd successful.\n");
} else RvPrintf("RvTimestampEnd failed. Error = %d\n", result);
Rv64AsciiEnd();
}
#endif /* RV_TEST_CODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -