EPICS Controls 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  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: asyn bo record staying in INVALID DRIVER UDF
From: Torsten Bögershausen via Tech-talk <tech-talk at aps.anl.gov>
To: Ralph Lange <ralph.lange at gmx.de>, EPICS Tech Talk <tech-talk at aps.anl.gov>, "Rivers, Mark" <rivers at cars.uchicago.edu>
Date: Fri, 28 May 2021 12:54:13 +0200
Hej again,
To start with, I cleanup up the white-spaces that had smuggled
into asyn here:
https://github.com/epics-modules/asyn/pull/134


For the "INVALID DRIVER UDF" I added a PR here,
but that is just for discussion:

https://github.com/epics-modules/asyn/pull/133


BR
/Torsten

On 5/28/21 11:29 AM, Torsten Bögershausen via Tech-talk wrote:
Hej Ralph,
I don't know if I understand the question 100%.

So let me try to explain, what is happening:

In st.cmd, we start a poller thread, talking to the hardware
(=motion controller unit, MCU in ESS speach)
(And the poller is a model 3 motordriver)

When the poller reads the value from the MCU, it calls
              setIntegerParam(axisNo, function,  newValue);
              callBacksNeeded = 1;
and later
    if (callBacksNeeded) {
      callParamCallbacks();
    }

When the IOC is not yet started, the callbacks are blocked somewhere.
But the setIntegerParam() succeeds and the new value is in the
asyn parameter libray.

The bo record does this, once the record need to be initialized:

static long initBo(boRecord *pr)
{
    devPvt *pPvt;
    int status;
    epicsInt32 value;

    status = initCommon((dbCommon *)pr,&pr->out,
       processCallbackOutput,interruptCallbackOutput, interruptCallbackEnumBo,
        2, (char*)&pr->znam, NULL, &pr->zsv);
    if (status != INIT_OK) return status;
    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 INIT_OK;
    }
    return INIT_DO_NOT_CONVERT;
}


So when the record can read a value from the paramlib,
pasynInt32SyncIO() return asynSuccess, the value
is put into the record and everything is fine.


But, there is a race:

When the iocInit() is faster than the poller, the record
is initialized in initBo(), but kept in
"INVALID DRIVER UDF" alarm state.

Later (could be milliseconds, seconds, whatever)
when the poller can talk to the MCU, it will write the value
into the paramlibrary (as before).
(The dev support will resset UDF to 0)

A record processing is triggered and executed.
The new value is in the record, but the alarm status stays,
until the record is processed another time:



static long processBo(boRecord *pr)
{
    devPvt *pPvt = (devPvt *)pr->dpvt;
    int status;

    epicsMutexLock(pPvt->devPvtLock);
    if(pPvt->newOutputCallbackValue && getCallbackValue(pPvt)) {
        /* We got a callback from the driver */
        if (pPvt->result.status == asynSuccess) {
            pr->rval = pPvt->result.value;
            pr->val = (pr->rval) ? 1 : 0;
            pr->udf = 0;
        }

If I change the code like this:

static long processBo(boRecord *pr)
{
    devPvt *pPvt = (devPvt *)pr->dpvt;
    int status;

    epicsMutexLock(pPvt->devPvtLock);
    if(pPvt->newOutputCallbackValue && getCallbackValue(pPvt)) {
        /* We got a callback from the driver */
      fprintf(stdout, "%s/%s:%d %s pPvt->result.status=%d\n",
           __FILE__, __FUNCTION__, __LINE__,
           pr->name, pPvt->result.status);
        if (pPvt->result.status == asynSuccess) {
            pr->rval = pPvt->result.value;
            pr->val = (pr->rval) ? 1 : 0;
            if (pr->udf) {
                pr->udf = 0;
                pr->nsta = 0;
                pr->nsev = 0;
            }
        }


Everything is fine.

Does this explain anything ?

Thanks to everybody
/Torsten


On 5/28/21 11:02 AM, Ralph Lange via Tech-talk wrote:
Might that be related to the initial readback being an asynchronous process(ing)?

The whole idea of doing an initial readback as part of record initialization is based on the assumption that the readback is immediate, i.e. synchronous. If it is asynchronous and the device answer is only accepted after the equivalent of interruptAccept being true, the timing and order of things may be pretty different. In those cases, initial readback has to be done as part of PINI processing, as that runs late enough and works with asynchronous device access. In case that asyn:READBACK is set, the read request can be done as part of the record initialization if the device answer is delayed long enough (or queued) to be processed after interruptAccept. Dropping the device answer would leave the record with UDF cleared (from the silent initial readback) but without processing (as the device answer was lost), which resembles what Torsten is seeing, doesn't it?

Cheers,
~Ralph


References:
asyn bo record staying in INVALID DRIVER UDF Torsten Bögershausen via Tech-talk
RE: asyn bo record staying in INVALID DRIVER UDF Mark Rivers via Tech-talk
RE: asyn bo record staying in INVALID DRIVER UDF Mark Rivers via Tech-talk
RE: asyn bo record staying in INVALID DRIVER UDF Mark Rivers via Tech-talk
RE: asyn bo record staying in INVALID DRIVER UDF Mark Rivers via Tech-talk
Re: asyn bo record staying in INVALID DRIVER UDF Ralph Lange via Tech-talk
Re: asyn bo record staying in INVALID DRIVER UDF Torsten Bögershausen via Tech-talk

Navigate by Date:
Prev: Re: asyn bo record staying in INVALID DRIVER UDF Torsten Bögershausen via Tech-talk
Next: Re: Epics MODbus driver, can this be run as a MODbus Slave? Mark Rivers via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024 
Navigate by Thread:
Prev: Re: asyn bo record staying in INVALID DRIVER UDF Torsten Bögershausen via Tech-talk
Next: RE: asyn bo record staying in INVALID DRIVER UDF Mark Rivers via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024 
ANJ, 28 May 2021 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·