Hi Torsten,
I realize the tests I reported in my previous message were on an ao record, and you were having problems with a bo record.
So I repeated the tests, but this time I modified the “Run” record in the database and driver.
--- a/iocBoot/ioctestAsynPortDriver/st.cmd
+++ b/iocBoot/ioctestAsynPortDriver/st.cmd
@@ -11,3 +11,6 @@ dbLoadRecords("../../db/asynRecord.db","P=testAPD:,R=asyn1,PORT=testAPD,ADDR=0,O
#asynSetTraceMask("testAPD",0,0xff)
asynSetTraceIOMask("testAPD",0,0x2)
iocInit()
+
+epicsThreadSleep(1)
+dbpr testAPD:scope1:Run
--- a/testAsynPortDriverApp/Db/testAsynPortDriver.db
+++ b/testAsynPortDriverApp/Db/testAsynPortDriver.db
@@ -3,11 +3,12 @@
###################################################################
record(bo, "$(P)$(R)Run")
{
- field(PINI, "1")
+# field(PINI, "1")
field(DTYP, "asynInt32")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))SCOPE_RUN")
field(ZNAM, "Stop")
field(ONAM, "Run")
+ info(asyn:READBACK, "1")
}
--- a/testAsynPortDriverApp/src/testAsynPortDriver.cpp
+++ b/testAsynPortDriverApp/src/testAsynPortDriver.cpp
@@ -99,7 +99,7 @@ testAsynPortDriver::testAsynPortDriver(const char *portName, int maxPoints)
/* Set the initial values of some parameters */
setIntegerParam(P_MaxPoints, maxPoints);
- setIntegerParam(P_Run, 0);
+// setIntegerParam(P_Run, 0);
setIntegerParam(P_VertGainSelect, 10);
setVertGain();
setDoubleParam (P_VoltsPerDiv, 1.0);
I found exactly the same results as with the ai record. I see STAT=UDF and SEVR=INVALID if I remove PINI and comment out the line in the constructor that sets the value
of P_Run.
Mark
From: Mark Rivers
Sent: Thursday, May 27, 2021 4:31 PM
To: 'Torsten Bögershausen' <torsten.bogershausen at ess.eu>; 'Johnson, Andrew N.' <anj at anl.gov>
Cc: 'tech-talk at aps.anl.gov' <tech-talk at aps.anl.gov>
Subject: RE: asyn bo record staying in INVALID DRIVER UDF
Hi Torsten,
I am done some tests to understand what you are seeing, and what should happen. My conclusion is that asyn is working correctly, and there appears to be something wrong
with your driver.
I tested using the testAsynPortDriver application which is part of asyn. I tested by modifying the NoiseAmplitude record and the handling of the corresponding parameter
in the driver.
I modified asyn/iocBoot/ioctestAsynPortDriver/st.cmd to sleep 1 second after iocInit, and then to run dbpr on the NoiseAmplitude record:
#asynSetTraceMask("testAPD",0,0xff)
asynSetTraceIOMask("testAPD",0,0x2)
iocInit()
+
+epicsThreadSleep(1)
+dbpr testAPD:scope1:NoiseAmplitude
In the distributed version of testAsynPortDriver.db the NoiseAmplitude record is defined as follows:
record(ao, "$(P)$(R)NoiseAmplitude")
{
field(PINI, "1")
field(DTYP, "asynFloat64")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))SCOPE_NOISE_AMPLITUDE")
field(PREC, "3")
}
Note that it has PINI=1, so it processes at iocInit.
With the distributed version of the database and the driver I see the following after iocInit:
dbpr testAPD:scope1:NoiseAmplitude
ASG : DESC: DISA: 0 DISP: 0
DISV: 1 NAME: testAPD:scope1:NoiseAmplitude OMOD: 0
OVAL: 0.1 RBV : 0 RVAL: 0 SEVR: NO_ALARM
STAT: NO_ALARM TPRO: 0 VAL : 0.1
Note that the record STAT and SEVR are NO_ALARM.
I then commented out PINI=1 from the .db file.
record(ao, "$(P)$(R)NoiseAmplitude")
{
- field(PINI, "1")
+# field(PINI, "1")
Now the record has SEVR:INVALID and STAT=UDF because the record has not processed.
dbpr testAPD:scope1:NoiseAmplitude
ASG : DESC: DISA: 0 DISP: 0
DISV: 1 NAME: testAPD:scope1:NoiseAmplitude OMOD: 0
OVAL: 0.1 RBV : 0 RVAL: 0 SEVR: INVALID
STAT: UDF TPRO: 0 VAL : 0.1
I then added asyn:READBACK info tag to the NoiseAmplitude record:
record(ao, "$(P)$(R)NoiseAmplitude")
{
- field(PINI, "1")
+# field(PINI, "1")
field(DTYP, "asynFloat64")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))SCOPE_NOISE_AMPLITUDE")
+ info(asyn:READBACK, "1")
field(PREC, "3")
}
Now the record is back to NO_ALARM.
dbpr testAPD:scope1:NoiseAmplitude
ASG : DESC: DISA: 0 DISP: 0
DISV: 1 NAME: testAPD:scope1:NoiseAmplitude OMOD: 0
OVAL: 0.1 RBV : 0 RVAL: 0 SEVR: NO_ALARM
STAT: NO_ALARM TPRO: 0 VAL : 0.1
That is because the constructor of the driver contains this line:
setDoubleParam(P_NoiseAmplitude, 0.1);
Because that parameter has been set in the constructor (before iocInit), then asynPortDriver will do a callback to device support once the global EPICS variable interruptAccept
is true. That causes the record to process (because asyn:READBACK=1), which clears the UDF and INVALID status.
If I comment out that above line in the constructor then the record is back to UDF and INVALID.
dbpr testAPD:scope1:NoiseAmplitude
ASG : DESC: DISA: 0 DISP: 0
DISV: 1 NAME: testAPD:scope1:NoiseAmplitude OMOD: 0
OVAL: 0 RBV : 0 RVAL: 0 SEVR: INVALID
STAT: UDF TPRO: 0 VAL : 0
So my conclusion is that asynPortDriver is behaving as it should.
Since you appear to be seeing a different result for your driver, then perhaps you are not setting the value of that parameter in your constructor (or elsewhere)?
Mark
-----Original Message-----
From: Mark Rivers
Sent: Thursday, May 27, 2021 2:56 PM
To: 'Torsten Bögershausen' <torsten.bogershausen at ess.eu>
Cc: 'tech-talk at aps.anl.gov' <tech-talk at aps.anl.gov>
Subject: RE: asyn bo record staying in INVALID DRIVER UDF
I see that you did send the output of dbpr in a subsequent message.
dbpr shows that the record has been processed at TIME: 2021-05-27 15:51:06.243005887. UDF is 0, but STAT=UDF and SEVR=INVALID.
This does not seem right, assuming UDF was actually 0 when the record processed.
Mark
-----Original Message-----
From: Mark Rivers
Sent: Thursday, May 27, 2021 2:50 PM
To: 'Torsten Bögershausen' <torsten.bogershausen at ess.eu>
Cc: tech-talk at aps.anl.gov
Subject: RE: asyn bo record staying in INVALID DRIVER UDF
Hi Torsten,
asynInt32 device support for bo records always attempts an initial readback from the device to support "bumpless reboots". If your driver returns asynSuccess on that read operation then it will set the value and set udf=0. However,
that initial read does not cause the record to process, so it will not reset STAT and SEVR.
You have also set the info tag asynREADBACK=1. That will cause the record to process if your driver does a callback to device support. You did not say if your driver is doing that. Is your driver based on asynPortDriver?
If you boot the IOC, wait a few seconds, and then type the following at the iocsh what do you see?
dbpr $(PREFIX)$(MOTOR_NAME)-OpenClutch 2
Mark
-----Original Message-----
From: Tech-talk <tech-talk-bounces at aps.anl.gov> On Behalf Of Torsten Bögershausen via Tech-talk
Sent: Thursday, May 27, 2021 5:50 AM
To: tech-talk at aps.anl.gov
Subject: asyn bo record staying in INVALID DRIVER UDF
Asyn-Experts,
I am chasing an interesting problem.
For a motor, we have a clutch that can be opened under very special conditions, say service mode.
We define it like this:
record(bo, "$(PREFIX)$(MOTOR_NAME)-OpenClutch")
{
field(DTYP, "asynInt32")
field(DESC, "$(DESC=Clutch)")
field(OUT, "@asyn($(MOTOR_PORT),$(AXIS_NO))OpenClutch")
field(ZNAM, "Closed")
field(ONAM, "Open")
info(asyn:READBACK,"1")
}
When the IOC starts, it talks to the motion controller, and reads back the value of the clutch.
This does work, but the PV stays in an "INVALID DRIVER UDF"
alarm.
I can see that the value is read back, and pr->udf is reset from 1 to 0.
However, there is no post here.
Re-starting the pvmonitor shows that udf goes to 0.
.STAT stay at UDF,
.SEVR stay at INVALID
(base) [xx@yy test]$ pvmonitor IOC:m6-OpenClutch IOC:m6-OpenClutch.UDF
IOC:m6-OpenClutch.STAT IOC:m6-OpenClutch.SEVR
IOC:m6-OpenClutch <undefined> INVALID DRIVER UDF (0)
Closed
IOC:m6-OpenClutch.UDF <undefined> 1 INVALID DRIVER UDF
IOC:m6-OpenClutch.STAT <undefined> INVALID DRIVER UDF (17) UDF
IOC:m6-OpenClutch.SEVR <undefined> INVALID DRIVER UDF (3)
INVALID
^C(base) [xx@yy test]$ pvmonitor IOC:m6-OpenClutch IOC:m6-OpenClutch.UDF
IOC:m6-OpenClutch.STAT IOC:m6-OpenClutch.SEVR
IOC:m6-OpenClutch 2021-05-27 12:44:11.032 INVALID DRIVER UDF (0)
Closed
IOC:m6-OpenClutch.UDF 2021-05-27 12:44:11.032 0 INVALID DRIVER UDF
IOC:m6-OpenClutch.STAT 2021-05-27 12:44:11.032 INVALID DRIVER UDF (17) UDF
IOC:m6-OpenClutch.SEVR 2021-05-27 12:44:11.032 INVALID DRIVER UDF (3) INVALID
(Sorry for this slightly garbled log file)
The alarm seem to go away, if the record is processed one more time.
(by disconnecting the IOC from the controller and re-establishing the connection).
Is this a know phenomena ?
Anything that can be done ?
Thanks
/Torsten