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 2021 2022 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 2021 2022 2023 2024 |
<== Date ==> | <== Thread ==> |
---|
Subject: | RE: Force AsynPortDriver to write an output record's value to the device instead of fetching it |
From: | Abdalla Ahmad via Tech-talk <[email protected]> |
To: | Mark Rivers <[email protected]>, "[email protected]" <[email protected]> |
Date: | Sun, 1 Sep 2019 07:04:12 +0000 |
Hi Mark Thank you very much for the info. The IOC already has autosave integrated so we can use it, but out of curiosity how do I check if the read function is called in an IOC init? Best Regards, Abdalla. From: Mark Rivers <[email protected]> Hi Abdalla, Ø
What I noticed is that no matter what, the asyn driver instance does not take the output record’s VAL field on IOC startup, it always take
the last value written (which I don’t know where it is being fetched even if the input record) is not loaded. The behavior you describe is intentional. It is designed to support “bumpless reboots” where output records can be initialized to the current hardware values. This is documented in the asyn driver documentation
https://epics.anl.gov/modules/soft/asyn/R4-36/asynDriver.html#DeviceInitialValues which says this: ********************************** Initial values of output records The device support for output records on register based interfaces (bo, mbbo, ao, longout) does an initial read() of the value from the driver in init_record. If this read()
returns asynSuccess then the record value is set to the value returned from read(). If read() returns anything other than asynSuccess then the record value is not modified. This mechanism supports "bumpless reboots" where the initial value of output records
will match the current value of the hardware when the IOC starts. Drivers should only return asynSuccess from the read() function if the value is known to be valid. Note that this value read from the device will replace the value in the database when iocInit
begins. However, the value read from the device may in turn be replaced by any value from save/restore, because the auto restore happens later in iocInit. Beginning in R4-30 devAsynOctet was changed to also support the initial readback for stringout and waveform output records. The initial readback
is only done if the record in the database contains the following line: ********************************** This tech-talk thread also discussed the issue
https://epics.anl.gov/tech-talk/2016/msg00963.php. It says: ********************************** Where does an output record (ao, longout, mbbo, etc.) get its initial value?
–
If your driver returns asynSuccess on that read then that value is used.
–
Supports bumpless reboots.
–
If using asynPort driver then if your driver has done setIntegerParam, setDoubleParam, or setStringParam before init_record (i.e. typically
in constructor) then the readInt32, etc. functions will return asynSuccess. If setInt32Param has not been done then readInt32 returns asynError, and that value will not be used.
********************************** If you don’t want the output record to use the value read from the hardware then you have 3 choices: -
Change the driver so that readInt32 returns asynError if it is called during iocInit -
Use autosave, which will replace the value read from the hardware with the autosaved value -
Call dbpf at the end of your startup script to write the desired value to the record. Mark From: Abdalla Ahmad <[email protected]>
Following on the issue below. I forgot to provide more information: The device is communicating with UDP. The socket is being initialized and open in the constructor. What I noticed is that no matter what, the asyn driver instance does not take the output record’s VAL field on
IOC startup, it always take the last value written (which I don’t know where it is being fetched even if the input record) is not loaded. I tried using setIntegerParam in the constructor but it did not work, I tried using callParamCallbacks the same way as a previous working asynPortDriver, I played with asyn flags (multi-device and can block),
still on IOC startup the VAL value is not loaded. Communication-wise everything is working, I can read/write with no problem. A workaround to this is to have separate parameters for set and get records and skip each one in the opposite asyn read/write functions. I don’t think this is a good solution in case of large number of parameters.
But what I did notice is that each time the IOC starts, readInt32 gets called then writeInt32 then readInt32 again.
Best Regards, Abdalla. From: Abdalla Ahmad Hi We have output records that uses asynPortDriver-based driver, they all have an initial value on IOC startup through the VAL field and PINI is set to YES. Instead of this value being set to the device on startup, they somehow contain the
last value being set. It seems that it is discarding the record’s VAL field, even if the input record is not loaded. Is there a way to make it write the record’s value at startup instead of the last set value? What am I missing here? Best Regards, Abdalla. |