Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019 
<== Date ==> <== Thread ==>

Subject: Re: Initial Value of a BO Record
From: Zenon Szalata <zms@slac.stanford.edu>
To: Mark Rivers <rivers@cars.uchicago.edu>
Cc: tech-talk <tech-talk@aps.anl.gov>
Date: Thu, 11 Jul 2013 14:39:13 -0700
Hi Mark,
Comments interspersed with your text.

On 07/11/13 14:26, Mark Rivers wrote:
Hi Zen,

Your table came through hard to read because it wrapped lines.  I've reformatted it here.

    capture in readInt32   readInt32-returns  setIntegerParams VAL
1  yes                      asynSuccess            yes         1
2  yes                      asynError              yes         0
3  no                       asynError              yes         0
4  no                       asynError               no         0
5  yes                      asynSuccess             no         1
6  yes                      asynError               no         0

Can you explain a few things about these tests:

- What does "capture in readInt32" mean.  Does "yes" mean that the readInt32 method in your class handled that parameter, and "no" mean that you called the base class for that parameter?
yes means that the parameter was handled in my readInt32 and it returned either success or error. No means that the parameter was not handled in readInt32. My readInt32 does not call asynPortDriver base class. Should it?
- Does "setIntegerParams" mean that you called setIntegerParam for that parameter in your constructor, and set the value to 0?
Yes to this.
- To explain test 5 your readInt32 function would need to be returning a non-zero value for the *value argument when it is initially called.  Is this true?  The readInt32 method has the following prototype:
     virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
What value are you returning in *value?
I did not assign any value to *value. This then is the important step that I have not thought to take. I will try to remember this.
Thanks Mark,
Zen

- For test 1 it does not matter that you called setIntegerParam with 0.  What matters is what value your readInt32 routine returns for the *value argument.  The parameter library value is irrelevant.

Mark



-----Original Message-----
From: Zenon Szalata [mailto:zms@slac.stanford.edu]
Sent: Thursday, July 11, 2013 3:36 PM
To: Mark Rivers
Cc: tech-talk
Subject: Re: Initial Value of a BO Record

Thanks Mark,
I redid the tests a bit more carefully and this is what I see:

    capture in readInt32   readInt32-returns  setIntegerParams VAL
1  yes                      asynSuccess            yes         1
2  yes                      asynError              yes         0
3  no                       asynError              yes         0
4  no                       asynError               no         0
5  yes                      asynSuccess             no         1
6  yes                      asynError               no         0

I had a bug which was affecting test 3 and 4 which before the bug was
fixed, resulted in VAL = 1.
I think that these results are in line with what you said in your last
email, perhaps with the exception of test 1, where I would expect to get
VAL = 0 since I was setting the record to value 0 using
setIntegerParam.  It is possible that I don't really understand how this
is supposed to work.
Thanks again,
Zen

On 07/11/13 09:44, Mark Rivers wrote:
Hi Zen,

The concept of the "bumpless reboot" is as follows.

- The init_record function in the asyn device support for the asynInt32 interface attempts to read the value from the driver.  This happens during iocInit.
- If the driver returns asynSuccess then the value returned by the driver is placed into the RVAL field in the bo record, and it tells the record to convert the RVAL value to the VAL field.  This will make the record agree with the hardware after iocInit.
- If the driver does not return asynSuccess then the device support does not change the RVAL field of the bo record, and returns 2 (do not convert).
- If you are using asynPortDriver and you are implementing the readInt32 method then you have control of whether to return asynSuccess or asynError when called during iocInit.  You may need to have a flag indicating whether the value has ever been written by a call to writeInt32, or look at the value of the EPICS global "interruptAccept", etc.
- If you are using asynPortDriver and you are NOT implementing the readInt32 method then the asynPortDriver::readInt32 base class implementation will be used.  It returns asynSuccess if a value has ever been written to the parameter library with setIntegerParam() for that parameter and address.  If setIntegerParam has not yet been called then it returns asynError.

This is the asyn/devEpics/devAsynInt32.c::initBo function, which is the init_record function for bo records in the asynInt32 device support:

static long initBo(boRecord *pr)
{
      devInt32Pvt *pPvt;
      asynStatus status;
      epicsInt32 value;

      status = initCommon((dbCommon *)pr,&pr->out,
          processCallbackOutput,interruptCallbackOutput, interruptCallbackEnumBo,
          2, (char*)&pr->znam, NULL, &pr->zsv);
      if (status != asynSuccess) return 0;
      pPvt = pr->dpvt;
      /* Read the current value from the device */
      status = pasynInt32SyncIO->read(pPvt->pasynUserSync,
                        &value, pPvt->pasynUser->timeout);
      if (status == asynSuccess) {
          pr->rval = value;
          return 0;
      }
      return 2;
}

So it called pasynInt32SyncIO-read to read the value from the driver.  If the read is successful it set rval and returns 0.  If the read fails it returns 2, and does not modify rval.

This is the pasynInt32SyncIO->read function:

static asynStatus readOp(asynUser *pasynUser, epicsInt32 *pvalue, double timeout)
{
      ioPvt      *pioPvt = (ioPvt *)pasynUser->userPvt;
      asynStatus status, unlockStatus;

      pasynUser->timeout = timeout;
      status = pasynManager->queueLockPort(pasynUser);
      if(status!=asynSuccess) {
          return status;
      }
      status = pioPvt->pasynInt32->read(pioPvt->int32Pvt, pasynUser, pvalue);
      if (status==asynSuccess) {
          asynPrint(pasynUser, ASYN_TRACEIO_DEVICE,
                    "asynInt32SyncIO read: %d\n", *pvalue);
      }
      unlockStatus = pasynManager->queueUnlockPort(pasynUser);
      if (unlockStatus != asynSuccess) {
          return unlockStatus;
      }
      return(status);
}

So it returns asynSuccess if and only if your driver's pasynInt32->read function returns asynSuccess.

If your readInt32 routine is returning asynError then the bo record should not be being set to 1.

Are you using autosave?  Is it possible that autosave is restoring 1 from an autosave file?

I cannot explain what you are observing, and I cannot reproduce it.

I just tested with an areaDetector driver.  I deleted all of the autosave files.  I rebooted the IOC and all bo records had the values defined in the database file.  Some were 1, some were 0.  I did not find any discrepancies between the database file and the run time value.  None of these parameters were having their values set with setIntegerParam() in the constructors.

Mark


-----Original Message-----
From: Zenon Szalata [mailto:zms@slac.stanford.edu]
Sent: Thursday, July 11, 2013 11:08 AM
To: Mark Rivers; tech-talk
Subject: Initial Value of a BO Record

Hi Mark,
I have a handful of bo records, which are intended to initiate some
action in a device driver sub-classed from asynPortDriver.  I want these
records to have VAL 0 when the IOC starts.  A typical record looks like
this:

record( bo,"$(P):BO:$(MOD):CH$(N):STOP"){
     field( DESC, "Stop:")
     field( DTYP, "asynInt32")
     field( OUT,  "@asyn($(PORT) $(ADDR) 1)BO_STOP")
     field( HIGH, "0.1")
     field( ZNAM, "Not")
     field( ONAM, "Yes")
     field( VAL,  "0")
}

When the IOC starts, these records have VAL=1, which is undesirable.
For testing I have created a soft channel bo record and it comes up with
the state consistent with what is in the VAL field.  I suspect the
observed behavior has something to do with the "bumpless reboot" that
you mentioned in your last email to me.  I must confess that I don't
understand the concept and more importantly how to avoid it, assuming
that is what is getting me.
I tried a few things in the device driver.  I have captured the call in
readInt32 routine and set the return status to either asynSuccess or
asynError, which did not change the behavior.  I have also added in the
constructor setIntegerParam( xxxx,0) for these records.  This also did
not help.  Could you put me on the right track with this?
Thanks in advance,
Zen



Replies:
RE: Initial Value of a BO Record Mark Rivers
References:
Initial Value of a BO Record Zenon Szalata
RE: Initial Value of a BO Record Mark Rivers
Re: Initial Value of a BO Record Zenon Szalata
RE: Initial Value of a BO Record Mark Rivers

Navigate by Date:
Prev: RE: Initial Value of a BO Record Mark Rivers
Next: RE: Initial Value of a BO Record Mark Rivers
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019 
Navigate by Thread:
Prev: RE: Initial Value of a BO Record Mark Rivers
Next: RE: Initial Value of a BO Record Mark Rivers
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019 
ANJ, 20 Apr 2015 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·