EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  <20022003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  <20022003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: [Q] How to set a timestamp in a device support routine.
From: Carl Lionberger <[email protected]>
To: Marty Kraimer <[email protected]>
Cc: [email protected], "[email protected]" <[email protected]>
Date: Mon, 24 Jun 2002 15:13:09 -0400
OK, I'll go for that.  Thanks.

    Carl

Marty Kraimer wrote:

> Are you asking for something like
>
> #define epicsTimeEventBestTime -1
> #define epicsTimeEventDeviceTime -2
> #define epicsTimeEventLinkPropagate -3

It would be cleaner to have 3 numbers, yes.

>
>
> If it is then I suggest a slight change from what you recommended. The rules
> would be.
>
> 1) Transfering time stamps only works across database links.
> 2) dbScanPassive transfers the time stamp ONLY if the scanned record is passive.

OK, I've convinced myself not to be worried about the fact dbScanPassive also does input
links.  After all, if they don't want their time stamps adjusted they can just not set
tse to epicsTimeEventLinkPropagate.

>
>
>     This replaces your suggestion to modify recGblFwdLink and dbScanFwdLink
> 3) dbPutLinkValue ??? What to do.
>
> Output to asynchronous records are a problem (but always have been!!). The code is
>
>          if(plink->type==DB_LINK) {
>                  struct dbCommon *psource = plink->value.pv_link.precord;
>                  struct pv_link  *ppv_link= &(plink->value.pv_link);
>                  DBADDR          *paddr  = (DBADDR*)(ppv_link->pvt);
>                  dbCommon        *pdest  = paddr->precord;
>
>                  status=dbPut(paddr,dbrType,pbuffer,nRequest);
>                  if(ppv_link->pvlMask&pvlOptMS)
>                          recGblSetSevr(pdest,LINK_ALARM,psource->nsev);
>                  if(status) return(status);
>                  if((paddr->pfield==(void *)&pdest->proc)
>                  || (ppv_link->pvlMask&pvlOptPP && pdest->scan==0)) {
>                          /*if dbPutField caused asyn record to process   */
>                          /* ask for reprocessing*/
>                          if(pdest->putf) pdest->rpro = TRUE;
>                          /* otherwise ask for the record to be processed*/
>                          else status=dbScanLink(psource,pdest);
>                  }
>
> When should the time stamp be transfered? I will say only when
>
>               if((paddr->pfield==(void *)&pdest->proc)
>                  || (ppv_link->pvlMask&pvlOptPP && pdest->scan==0)) {
>
> Is successful. If this is not successfull then the put does not cause the record
> to process. In this case I see no reason to modify the time stamp.

I agree

>
>
> Thus the problem comes down to the statements
>
>                         /*if dbPutField caused asyn record to process   */
>                          /* ask for reprocessing*/
>                          if(pdest->putf) pdest->rpro = TRUE;
>                          /* otherwise ask for the record to be processed*/
>                          else status=dbScanLink(psource,pdest);
>
> In this case the put will cause the record to process but it may be delayed
> because an asyn record has not completed. If the time stamp is transfered before
> the above code then the asyn completion will have the new time stamp not the
> timestamp for the original request. If the timestamp is not transfered at this
> point there is no place to keep it. Also is it worse to replace the time stamp
> than to replace the VAL field? I don't think so. Thus perhaps the above code
> should be
>
>                          if (paddr->precord->tse == epicsTimeEventLinkPropagate)
>                               paddr->precord->time = precord->time;
>                          /*if dbPutField caused asyn record to process   */
>                          /* ask for reprocessing*/
>                          if(pdest->putf) pdest->rpro = TRUE;
>                          /* otherwise ask for the record to be processed*/
>                          else status=dbScanLink(psource,pdest);

I wouldn't want to disagree with you on that!

>
>
> Marty Kraimer
>
> Carl Lionberger wrote:
>
> > The diagnostic people here at SNS (where I'll be for the next couple of years,
> > right down the hall from David Thompson) have been asking for even more-  They want
> > time stamps to be able to propagate over forward links and, I assume for more
> > generality, dbPutLinks.  I start with the assumption of the code Marty gave(in my
> > working code I've been calling it "SPECIAL_TIME_EVENT" and making it -2) and then
> > have had several routines in dbAccess.c and recGbl.c propagate the time if its
> > set.  I've been working on a copy of 3.14.beta0.
> >
> > From recGbl.c I have:
> >
> > void epicsShareAPI recGblFwdLink(void *precord)
> > {
> >     struct dbCommon *pdbc = precord;
> >     static short    fwdLinkValue = 1;
> >
> >     if(pdbc->flnk.type==DB_LINK ) {
> >         struct dbAddr   *paddr = pdbc->flnk.value.pv_link.pvt;
> >         if (paddr->precord->tse == SPECIAL_TIME_EVENT)
> >            paddr->precord->time = pdbc->time;
> >         dbScanPassive(precord,paddr->precord);
> >     } else
> >     if((pdbc->flnk.type==CA_LINK)
> >         ....
> >
> > From dbAccess.c I have:
> >
> > void epicsShareAPI dbScanFwdLink(struct link *plink)
> > {
> >     dbCommon            *precord;
> >     struct pv_link      *pvlink;
> >     short               fwdLinkValue;
> >
> >     if(plink->type!=DB_LINK && plink->type!=CA_LINK) return;
> >     pvlink = &plink->value.pv_link;
> >     precord = pvlink->precord;
> >     if(plink->type==DB_LINK) {
> >         DBADDR *paddr = (DBADDR *)plink->value.pv_link.pvt;
> >         if (paddr->precord->tse == SPECIAL_TIME_EVENT)
> >            paddr->precord->time = precord->time;
> >         dbScanPassive(precord,paddr->precord);
> >         return;
> >     }
> >     if(!(pvlink->pvlMask & pvlOptFWD)) return;
> >     fwdLinkValue = 1;
> >     dbCaPutLink(plink,DBR_SHORT,&fwdLinkValue,1);
> >     return;
> > }
> >
> > and:
> >
> > long epicsShareAPI dbPutLinkValue(struct link *plink,
> >     short dbrType,const void *pbuffer,long nRequest)
> > {
> >         long            status=0;
> >
> >         if(plink->type==DB_LINK) {
> >                 struct dbCommon *psource = plink->value.pv_link.precord;
> >                 struct pv_link  *ppv_link= &(plink->value.pv_link);
> >                 DBADDR          *paddr  = (DBADDR*)(ppv_link->pvt);
> >                 dbCommon        *pdest  = paddr->precord;
> >
> >                 if (pdest->tse == SPECIAL_TIME_EVENT)
> >                     pdest->time = psource->time;
> >                 status=dbPut(paddr,dbrType,pbuffer,nRequest);
> >                 if(ppv_link->pvlMask&pvlOptMS)
> >                         recGblSetSevr(pdest,LINK_ALARM,psource->nsev);
> >
> >        .....
> >
> > Note that I am not thinking to support channel access links or input links (hence I
> > don't put it in dbScanPassive).  There may be situations in which the target record
> > would not process at all or would be processing asynchronously and would just sit
> > there with the wrong time stamp -- this would be an unintended behavior that is not
> > excluded but could happen.  At least it would only happen if the target record had
> > this time event set.  Old databases would be unaffected.
> >
> > So records with this event type set might get their time either from links that
> > caused them to process or from device support.  In general, the diagnostics team
> > wants to see chains of records, the first one of which would get the time stamp
> > from device support and subsequent ones would process it, keeping the same time
> > stamp.
> >
> >     Carl
> >
> >
> > Marty Kraimer wrote:
> >
> >
> >>Someone else asked for this feature. I think the first person to ask was Timo
> >>Korhonen (SLS) who is also the person who is redoing drvTS, which is the support
> >>for hardware generated time stamps.
> >>
> >>The next version of base (both 3.13 and 3.14) will provide this feature. The
> >>exact method is still undecided. Corrently in my working area I have the
> >>following change to recGbl.c
> >>
> >>For 3.13
> >>
> >>void recGblGetTimeStamp(void* prec)
> >>{
> >>    struct dbCommon* pr = (struct dbCommon*)prec;
> >>
> >>    if(pr->tsel.type!=CONSTANT)
> >>        dbGetLink(&(pr->tsel), DBR_SHORT,&(pr->tse),0,0);
> >>    if(pr->tse!=-1)
> >>        TSgetTimeStamp((int)pr->tse,(struct timespec*)&pr->time);
> >>}
> >>
> >>For 3.14 I have
> >>
> >>void epicsShareAPI recGblGetTimeStamp(void* prec)
> >>{
> >>    struct dbCommon* pr = (struct dbCommon*)prec;
> >>    int status = 0;
> >>
> >>    if(pr->tsel.type!=CONSTANT)
> >>        dbGetLink(&(pr->tsel), DBR_SHORT,&(pr->tse),0,0);
> >>    if (pr->tse!=-1)
> >>        status = epicsTimeGetEvent(&pr->time,(unsigned)pr->tse);
> >>    if(status) errlogPrintf("%s recGblGetTimeStamp failed\n",pr->name);
> >>}
> >>
> >>The above change says that if TSE=-1 then dont do anyting to the time stamp.
> >>
> >>This is NOT the final answer however. David Thompson (SNS) pointed out that the
> >>existing drvTS already treats TSE=-1 as a special case. It means that drvTS
> >>should get the most accurate current time stamp. For example with the APS
> >>hardware time stamp support, we keep a 1 millisecond hardware generated clock.
> >>If TSE=-1 then the time stamp will be taken from this clock rather than the
> >>vxWorks 60 HZ clock.
> >>
> >>Thus the above change to recGblGetTimeStamp is not correct. David suggested that
> >>we define.
> >>
> >>#define epicsTimeEventBestTime -1
> >>#define epicsTimeEventDeviceTime -10000
> >>
> >>epicsTimeEventBestTime would be used by drvTS and it's successor.
> >>epicsTimeEventDeviceTime says that device support is supplying the time stamp so
> >>recGblGetTimeStamp should not do anything.
> >>
> >>Questions to be resolved
> >>
> >>1) Where do we define these? For 3.14 the obvious place is epicsTime.h. For 3.13
> >>it is probably tsDefs.h
> >>
> >>2) What value should we use for epicsTimeEventDeviceTime?
> >>
> >>3) Whoever set the value for TSE must know about these values. How do we make
> >>these values known? Just document them in the Application Developer's Guide?
> >>
> >>Noboru Yamamoto wrote:
> >>
> >>
> >>>Hi,
> >>>
> >>>[Question]
> >>>
> >>>Is there any good way to set a timestamp of a record while a
> >>>process() function of a device support routine is called?
> >>>
> >>>[Why I'm asking this question]
> >>>
> >>>We need to import live data from the facility control
> >>>system, which uses a proprietary control system. This system
> >>>update the information on the memory periodically with
> >>>theire own timestamp. We would like to use
> >>>this timestamp as a timestamp of EPICS records rather than
> >>>the timestamp when the record is updated.
> >>>
> >>>Looking at aiRecord.c, for example, recGblGetTimeStamp is
> >>>called AFTER a call to read() function in a device support
> >>>is finished.
> >>>
> >>>Any idea?
> >>>
> >>>Noboru
> >>>
> >>>
> >>>
> >


Replies:
Re: [Q] How to set a timestamp in a device support routine. Marty Kraimer
References:
[Q] How to set a timestamp in a device support routine. Noboru Yamamoto
Re: [Q] How to set a timestamp in a device support routine. Marty Kraimer
Re: [Q] How to set a timestamp in a device support routine. Carl Lionberger
Re: [Q] How to set a timestamp in a device support routine. Marty Kraimer

Navigate by Date:
Prev: Re: [Q] How to set a timestamp in a device support routine. Marty Kraimer
Next: Re: [Report] EPICS R3.13.6 build on RH Linux7.3 Noboru Yamamoto
Index: 1994  1995  1996  1997  1998  1999  2000  2001  <20022003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: [Q] How to set a timestamp in a device support routine. Marty Kraimer
Next: Re: [Q] How to set a timestamp in a device support routine. Marty Kraimer
Index: 1994  1995  1996  1997  1998  1999  2000  2001  <20022003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 10 Aug 2010 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·