added soft clock support
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
/* iocClock.c */
|
||||
|
||||
/* Author: Marty Kraimer Date: 16JUN2000 */
|
||||
|
||||
/********************COPYRIGHT NOTIFICATION**********************************
|
||||
This software was developed under a United States Government license
|
||||
described on the COPYRIGHT_UniversityOfChicago file included as part
|
||||
of this distribution.
|
||||
****************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <vxWorks.h>
|
||||
#include <bootLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <sntpcLib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "epicsTypes.h"
|
||||
#include "cantProceed.h"
|
||||
#include "errlog.h"
|
||||
#include "osiThread.h"
|
||||
#include "osiSem.h"
|
||||
#include "tsStamp.h"
|
||||
#include "iocClock.h"
|
||||
|
||||
#define BILLION 1000000000
|
||||
#define iocClockSyncRate 10.0
|
||||
|
||||
static int iocClockGetCurrent(TS_STAMP *pDest);
|
||||
static int iocClockGetEvent(TS_STAMP *pDest, unsigned eventNumber);
|
||||
|
||||
typedef struct iocClockPvt {
|
||||
semMutexId lock;
|
||||
TS_STAMP clock;
|
||||
unsigned long lastTick;
|
||||
epicsUInt32 nanosecondsPerTick;
|
||||
int tickRate;
|
||||
int ticksToSkip;
|
||||
ptsStampGetCurrent getCurrent;
|
||||
ptsStampGetEvent getEvent;
|
||||
char *pserverAddr;
|
||||
}iocClockPvt;
|
||||
static iocClockPvt *piocClockPvt = 0;
|
||||
|
||||
extern char* sysBootLine;
|
||||
|
||||
static void syncNTP(void)
|
||||
{
|
||||
struct timespec Currtime;
|
||||
TS_STAMP epicsTime;
|
||||
STATUS status;
|
||||
int nConsecutiveBad = 0;
|
||||
|
||||
while(1) {
|
||||
status = sntpcTimeGet(piocClockPvt->pserverAddr,
|
||||
piocClockPvt->tickRate,&Currtime);
|
||||
if(status) {
|
||||
if(++nConsecutiveBad>6) {
|
||||
errlogPrintf("iocClockSyncWithNTPserver: sntpcTimeGet %s\n",
|
||||
strerror(status));
|
||||
nConsecutiveBad = 0;
|
||||
}
|
||||
threadSleep(iocClockSyncRate);
|
||||
continue;
|
||||
}
|
||||
nConsecutiveBad = 0;
|
||||
semMutexMustTake(piocClockPvt->lock);
|
||||
clock_settime(CLOCK_REALTIME,&Currtime);
|
||||
tsStampFromTimespec(&piocClockPvt->clock,&Currtime);
|
||||
piocClockPvt->lastTick = tickGet();
|
||||
semMutexGive(piocClockPvt->lock);
|
||||
}
|
||||
while(1) {
|
||||
double diffTime;
|
||||
threadSleep(iocClockSyncRate);
|
||||
status = sntpcTimeGet(piocClockPvt->pserverAddr,
|
||||
piocClockPvt->tickRate,&Currtime);
|
||||
if(status) {
|
||||
errlogPrintf("iocClockSyncWithNTPserver: sntpcTimeGet %s\n",
|
||||
strerror(status));
|
||||
continue;
|
||||
}
|
||||
tsStampFromTimespec(&epicsTime,&Currtime);
|
||||
semMutexMustTake(piocClockPvt->lock);
|
||||
diffTime = tsStampDiffInSeconds(&epicsTime,&piocClockPvt->clock);
|
||||
if(diffTime>=0.0) {
|
||||
piocClockPvt->clock = epicsTime;
|
||||
} else {/*dont go back in time*/
|
||||
piocClockPvt->ticksToSkip = (int) (diffTime*piocClockPvt->tickRate);
|
||||
}
|
||||
piocClockPvt->lastTick = tickGet();
|
||||
semMutexGive(piocClockPvt->lock);
|
||||
}
|
||||
}
|
||||
|
||||
void iocClockInit()
|
||||
{
|
||||
if(piocClockPvt) return;
|
||||
piocClockPvt = callocMustSucceed(1,sizeof(iocClockPvt),"iocClockInit");
|
||||
piocClockPvt->lock = semMutexMustCreate();
|
||||
piocClockPvt->nanosecondsPerTick = BILLION/sysClkRateGet();
|
||||
piocClockPvt->tickRate = sysClkRateGet();
|
||||
piocClockPvt->getCurrent = iocClockGetCurrent;
|
||||
piocClockPvt->getEvent = iocClockGetEvent;
|
||||
/* look first for environment variable */
|
||||
piocClockPvt->pserverAddr = getenv("EPICS_TS_NTP_INET");
|
||||
if(!piocClockPvt->pserverAddr) { /* next look for boot server*/
|
||||
BOOT_PARAMS bootParms;
|
||||
static char host_addr[BOOT_ADDR_LEN];
|
||||
bootStringToStruct(sysBootLine,&bootParms);
|
||||
/* bootParms.had = host IP address */
|
||||
strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN);
|
||||
piocClockPvt->pserverAddr = host_addr;
|
||||
}
|
||||
if(!piocClockPvt->pserverAddr) {
|
||||
errlogPrintf("No NTP server is defined. Clock does not work\n");
|
||||
return;
|
||||
}
|
||||
threadCreate("syncNTP",
|
||||
threadPriorityHigh,threadGetStackSize(threadStackSmall),
|
||||
(THREADFUNC)syncNTP,0);
|
||||
return;
|
||||
}
|
||||
|
||||
void iocClockRegister(ptsStampGetCurrent getCurrent,
|
||||
ptsStampGetEvent getEvent)
|
||||
{
|
||||
if(piocClockPvt) {
|
||||
printf("iocClockRegister: iocClock already initialized\n");
|
||||
return;
|
||||
}
|
||||
piocClockPvt = callocMustSucceed(1,sizeof(iocClockPvt),"iocClockRegister");
|
||||
piocClockPvt->getCurrent = getCurrent;
|
||||
piocClockPvt->getEvent = getEvent;
|
||||
}
|
||||
|
||||
int iocClockGetCurrent(TS_STAMP *pDest)
|
||||
{
|
||||
unsigned long currentTick,nticks,nsecs;
|
||||
|
||||
semMutexMustTake(piocClockPvt->lock);
|
||||
currentTick = tickGet();
|
||||
while(currentTick!=piocClockPvt->lastTick) {
|
||||
nticks = (currentTick>piocClockPvt->lastTick)
|
||||
? (currentTick - piocClockPvt->lastTick)
|
||||
: (currentTick + (ULONG_MAX - piocClockPvt->lastTick));
|
||||
if(piocClockPvt->ticksToSkip>0) {/*dont go back in time*/
|
||||
if(nticks<piocClockPvt->ticksToSkip) {
|
||||
piocClockPvt->ticksToSkip -= nticks;
|
||||
break;
|
||||
}
|
||||
nticks -= piocClockPvt->ticksToSkip;
|
||||
}
|
||||
piocClockPvt->lastTick = currentTick;
|
||||
nsecs = nticks/piocClockPvt->tickRate;
|
||||
nticks = nticks - nsecs*piocClockPvt->tickRate;
|
||||
piocClockPvt->clock.nsec += nticks * piocClockPvt->nanosecondsPerTick;
|
||||
if(piocClockPvt->clock.nsec>=BILLION) {
|
||||
++nsecs;
|
||||
piocClockPvt->clock.nsec -= BILLION;
|
||||
}
|
||||
piocClockPvt->clock.secPastEpoch += nsecs;
|
||||
}
|
||||
*pDest = piocClockPvt->clock;
|
||||
semMutexGive(piocClockPvt->lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int iocClockGetEvent(TS_STAMP *pDest, unsigned eventNumber)
|
||||
{
|
||||
if (eventNumber==tsStampEventCurrentTime) {
|
||||
*pDest = piocClockPvt->clock;
|
||||
return(0);
|
||||
}
|
||||
return(tsStampERROR);
|
||||
}
|
||||
|
||||
int tsStampGetCurrent (TS_STAMP *pDest)
|
||||
{
|
||||
if(piocClockPvt->getCurrent) return((*piocClockPvt->getCurrent)(pDest));
|
||||
return(tsStampERROR);
|
||||
}
|
||||
|
||||
int tsStampGetEvent (TS_STAMP *pDest, unsigned eventNumber)
|
||||
{
|
||||
if(piocClockPvt->getEvent)
|
||||
return((*piocClockPvt->getEvent)(pDest,eventNumber));
|
||||
return(tsStampERROR);
|
||||
}
|
||||
|
||||
void date()
|
||||
{
|
||||
TS_STAMP now;
|
||||
char nowText[40];
|
||||
size_t rtn;
|
||||
|
||||
rtn = tsStampGetCurrent(&now);
|
||||
if(rtn) {
|
||||
printf("tsStampGetCurrent failed\n");
|
||||
return;
|
||||
}
|
||||
nowText[0] = 0;
|
||||
rtn = tsStampToStrftime(nowText,sizeof(nowText),
|
||||
"%Y/%m/%d %H:%M:%S.%06f",&now);
|
||||
printf("%s\n",nowText);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* iocClock.h */
|
||||
|
||||
/* Author: Marty Kraimer Date: 16JUN2000 */
|
||||
|
||||
/********************COPYRIGHT NOTIFICATION**********************************
|
||||
This software was developed under a United States Government license
|
||||
described on the COPYRIGHT_UniversityOfChicago file included as part
|
||||
of this distribution.
|
||||
****************************************************************************/
|
||||
|
||||
#include "tsStamp.h"
|
||||
|
||||
typedef int (*ptsStampGetCurrent)(TS_STAMP *pDest);
|
||||
typedef int (*ptsStampGetEvent)(TS_STAMP *pDest,unsigned eventNumber);
|
||||
|
||||
void iocClockInit(void);
|
||||
void iocClockRegister(ptsStampGetCurrent getCurrent,ptsStampGetEvent getEvent);
|
||||
@@ -98,9 +98,9 @@ void threadInit(void)
|
||||
threadOnceMutex = semMCreate(
|
||||
SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
|
||||
assert(threadOnceMutex);
|
||||
TSinit();
|
||||
}
|
||||
lock = 0;
|
||||
iocClockInit();
|
||||
}
|
||||
|
||||
void threadOnceOsd(threadOnceId *id, void (*func)(void *), void *arg)
|
||||
|
||||
@@ -1,26 +1,2 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#include "osiTime.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern long TSgetTimeStamp(int event_number,TS_STAMP* ts);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// osiTime::osdGetCurrent ()
|
||||
//
|
||||
extern "C" epicsShareFunc int tsStampGetCurrent (TS_STAMP *pDest)
|
||||
{
|
||||
return(TSgetTimeStamp(0,pDest));
|
||||
}
|
||||
|
||||
//
|
||||
// tsStampGetEvent ()
|
||||
//
|
||||
extern "C" epicsShareFunc int epicsShareAPI tsStampGetEvent (TS_STAMP *pDest, unsigned eventNumber)
|
||||
{
|
||||
return(TSgetTimeStamp((int)eventNumber,pDest));
|
||||
}
|
||||
// this is not needed
|
||||
// tsStampGetCurrent and tsStampGetEvent are implemented in iocClock.c
|
||||
|
||||
Reference in New Issue
Block a user