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  2021  <20222023  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  <20222023  2024 
<== Date ==> <== Thread ==>

Subject: Re: EPICS compilation errors
From: Mark Rivers via Tech-talk <tech-talk at aps.anl.gov>
To: Adrian Martinez <adrian.martinez at orolia.com>
Cc: tech-talk <tech-talk at aps.anl.gov>
Date: Fri, 8 Jul 2022 11:53:42 +0000
Hi Adrian,

You are creating your parameters in asynDrvr::setupEWBPeriphCtl(), which is called from asynDrvr::setup().  However, the code you sent does not show where asynDrvr::setup() is called from.

Your driver does not inherit directly from asynPortDriver, but rather from EWBAsynPortDrvr() so I don't know what it's constructor does.

There are things I don't understand.  The definitions of asynPortDriver::createParam() are:
asynPortDriver.h:    virtual asynStatus createParam(          const char *name, asynParamType type, int *index);
asynPortDriver.h:    virtual asynStatus createParam(int list, const char *name, asynParamType type, int *index);

So it takes either 3 or 4 arguments.  You are sometimes calling it with 3 arguments, as it typical:
createParam( "enable_compensation", asynParamInt32, &idxEnableCompensation);

However, here you are calling it with 2 arguments
createParam( "ntp_status", asynParamInt32 );

And here with only 1 argument:
createParam( pAcqst );

The argument is always a pointer, and the next to last is always asynParamType, but here your have not passed asynParamType.

createParam( pIdle, &idxIdle );

All of this suggests to me that you have overridden the createParam() method in ways you have not shown.

The symptoms you have suggest that asynDrvr::setup() has not completed before iocInit.  That could happen if asynDrvr::setup() is being called from some other thread.

You can see whether this is true by adding asynPrint statements in asynDrvr::setupEWBPeriphCtl() with ASYN_TRACE_ERROR and see if those messages are all complete before iocInit is done.  Add a "date" statement to your startup script immediately after iocInit.

Mark


From: Adrian Martinez <adrian.martinez at orolia.com>
Sent: Friday, July 8, 2022 2:36 AM
To: Mark Rivers <rivers at cars.uchicago.edu>
Cc: tech-talk <tech-talk at aps.anl.gov>
Subject: RE: EPICS compilation errors
 
Hello Mark, 

That is the driver code:

asynDrvr::asynDrvr( const char *portName, int index )
:EWBAsynPortDrvr( portName, MAX_NUM_SCOPE_PARAMS )
{
EWBBridge *pBgd;
pBgd = (EWBBridge*)new EWBBgdAXICon( WB2_ROOT_PERIPH_OFFSET, WB2_PERIPH_MAPPING_SIZE,
            WB2_PM_SLW_PERIPH_OFFSET, (uint32_t)WB2_PM_SLW_PERIPH_LAST, WB2_PM_SLW_BLOCKSIZE,
            WB2_PM_RAW_PERIPH_OFFSET, (uint32_t)WB2_PM_RAW_PERIPH_LAST, WB2_PM_RAW_BLOCKSIZE);
//Then define the root of the bus
pRoot = new EWBBus( pBgd, 0x0, NULL );

if(pRoot->isValid()==false){
printf("ERROR while creating pRoot!");
    }

pPrhCtl   = NULL;

#ifdef _DEBUG
EWBTrace::getInstance().setLevel(EWBTrace::DEBUG);
#else
EWBTrace::getInstance().setLevel(EWBTrace::ERROR);
#endif
EWBTrace::getInstance().setLevel(EWBTrace::ERROR);
}

asynDrvr::~asynDrvr()
{
}


 // Setup
 //
 // Setup for all the params needed in the driver. Create all the params included in each periph
 //
asynStatus asynDrvr::setup()
{
AsynStatusObj status = asynSuccess;

setupEWBPeriphCtl();

syncTimeReg();

return status;
}


asynStatus asynDrvr::setupEWBPeriphCtl()
{
  EWBReg *lastreg;
AsynStatusObj status = asynSuccess;

pPrhCtl = new EWBPeriph(this->pRoot,WB2_PRH_ARGS( CTL ));
lastreg = new EWBReg( pPrhCtl, WB2_REG_ARGS( CTL, CTRL ));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, RSTSW )));
pPosMes = new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, POSMESENA ),0);
createParam( pPosMes );
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM ), 1), &idxAlarm , EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV); // TS3
pAcqst = new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ACQST ),0);
createParam( pAcqst );
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, USERBUFDUMP )), &idxDumpBuffer, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);
pChannelCalib = new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, SELFCLBENA ));
createParam(pChannelCalib, &idxChannelCalib, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV | EWB_SYNC_FLG_PRE);
// createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, CABLECLBENA )), &idxCableCalib, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);
pCableCalib = new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, CABLECLBENA ));
createParam( pCableCalib, &idxCableCalib, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, CNF_RDY )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, BPM_RDY )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_X )), &idxAlarmX, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_Y )), &idxAlarmY, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_I )), &idxAlarmI, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_P )), &idxAlarmP, EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_X_ACK )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_Y_ACK )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_I_ACK )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, ALARM_P_ACK )));

pIdle = new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, GET_IDLE ));
createParam( pIdle, &idxIdle );

createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, CTRL, BPMSTATE )), &idxBpmState, EWB_SYNC_FLG_PRE | EWB_SYNC_FLG_POST | EWB_SYNC_FLG_DEV);

// Code to set the machine in Startup mode in each driver reboot
setIdle();

lastreg = new EWBReg( pPrhCtl, WB2_REG_ARGS( CTL, OVERAGE ));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, OVERAGE, ADC_TOP )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, OVERAGE, ADC_BOTTOM )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, OVERAGE, ADC_RIGHT )));
createParam( new EWBField( lastreg, WB2_FIELD_ARGS( CTL, OVERAGE, ADC_LEFT )));
createParam( "calibration_msg", asynParamOctet, &idxCalibrationMsg );
setStringParam( idxCalibrationMsg, "Please, select calibration to calibrate the system" );
createParam( "reset_calibration", asynParamInt32, &idxResetCalibration);
setIntegerParam( idxResetCalibration, 1 );
createParam( "Cavity_present", asynParamInt32, &idxCavityPresent);
setIntegerParam( idxCavityPresent, 0 );
createParam( "disable_calibration", asynParamInt32, &idxDisableCalibration);
setIntegerParam( idxDisableCalibration, 1);
createParam( "nfs_status", asynParamInt32);
// This PV allow to enable-disable the coupling compensation, using caput command
createParam( "enable_compensation", asynParamInt32, &idxEnableCompensation);
setIntegerParam( idxEnableCompensation, 0 );
createParam( "ntp_status", asynParamInt32 );

return status;
}


In addition to this, the driver code contains other functions such as postWriteFromPv(), preReadToPv(), postReadToPv()... used to execute diferrent conditions depending on the PVs flags.

Do you need any other part of the code?



Thanks, Adrián.


De: Mark Rivers <rivers at cars.uchicago.edu>
Enviado: jueves, 7 de julio de 2022 16:05
Para: Adrian Martinez <adrian.martinez at orolia.com>
Cc: tech-talk <tech-talk at aps.anl.gov>
Asunto: RE: EPICS compilation errors
 

CAUTION: This email originated from outside of the organization.
Do not click links or open attachments unless you recognize the sender and know the content is safe.

Hi Adrian,

 

2022/07/06 10:46:59.429 asynPortDriver:drvUserCreate: addr=0, cannot find parameter Ctrl_RstSw

SL-SCL-CM3:DIA-BPM-3:ResetSoftStat devAsynInt32::initCommon drvUserCreate

 

This error is not shown for all the PVs and not always for the same PVs. For example, the first compilation shows error for PV1, PV2 and PV3, and the second compilation (immediately) shows error for PV2, PV4 and PV5.

 

Summing up, it is almost impossible to compile with 0 errors.

 

First, let me clarify.  Those are not compile errors, they are errors at run time, almost certainly during iocInit when the record is being initialized.

 

This sounds like a race condition where not all parameters have been created before iocInit is called.

 

Your driver should be creating all of the parameters in the constructor, which will run in the main thread of the startup script.  It is OK if createParam() is called in another function that is called from the constructor, but if it is done in another thread then the constructor must wait for that thread to complete.

 

It would probably be helpful if you shared your driver code so we could look for the problem.

 

Mark

 

 

From: Tech-talk <tech-talk-bounces at aps.anl.gov> On Behalf Of Adrian Martinez via Tech-talk
Sent: Thursday, July 7, 2022 2:39 AM
To: tech-talk at aps.anl.gov
Subject: EPICS compilation errors

 

Hello,

 

I am developing an epics driver using epics-3.15.5 and asyn-4-33. The driver works correctly but, sometimes (aprox 90% of the time), returns an error when the procces variables (PV) are initialized:

 

2022/07/06 10:46:59.429 asynPortDriver:drvUserCreate: addr=0, cannot find parameter Ctrl_RstSw

SL-SCL-CM3:DIA-BPM-3:ResetSoftStat devAsynInt32::initCommon drvUserCreate

 

This error is not shown for all the PVs and not always for the same PVs. For example, the first compilation shows error for PV1, PV2 and PV3, and the second compilation (immediately) shows error for PV2, PV4 and PV5. Summing up, it is almost impossible to compile with 0 errors.

 

These errors just affect to PV readbacks, which never change its values, although the value can be read correctly in the memory register corresponding to the modified PV.

 

 

The error could be related with the asynPortDriver class so, createParam function from asynPortDriver.cpp it is working correctly, creating the param list with all PVs (it has been checked using a for loop after each createParam invocation):

 

Last createParam invocation to add mrf_time PV

 

PUSH = mrf_time

VALS[0] = Ctrl_RstSw

VALS[1] = Ctrl_PosMesEna

VALS[2] = Ctrl_Alarm

VALS[3] = Ctrl_Acqst

VALS[4] = Ctrl_UserBufDump

VALS[5] = Ctrl_SelfClbEna

VALS[6] = Ctrl_CableClbEna

VALS[7] = Ctrl_cnf_rdy

VALS[8] = Ctrl_bpm_rdy

VALS[9] = Ctrl_alarm_x

VALS[10] = Ctrl_alarm_y

VALS[11] = Ctrl_alarm_i

VALS[12] = Ctrl_alarm_p

VALS[13] = Ctrl_alarm_x_ack

VALS[14] = Ctrl_alarm_y_ack

VALS[15] = Ctrl_alarm_i_ack

VALS[16] = Ctrl_alarm_p_ack

VALS[17] = Ctrl_get_idle

VALS[18] = Ctrl_BpmState

VALS[19] = overage_adc_top

VALS[20] = overage_adc_bottom

VALS[21] = overage_adc_right

VALS[22] = overage_adc_left

VALS[23] = calibration_msg

VALS[24] = reset_calibration

VALS[25] = Cavity_present

VALS[26] = disable_calibration

VALS[27] = nfs_status

VALS[28] = enable_compensation

VALS[29] = ntp_status

VALS[30] = ctl_pps_utc_sw

VALS[31] = syncTimeMode

VALS[32] = mrf_time

VALS.SIZE() = 33

 

The problem comes when drvUserCreate() function is invocated and check all the PVs included in the param list.

 

/** Called by asynManager to pass a pasynUser structure and drvInfo string to the driver;

* Assigns pasynUser->reason based on the value of the drvInfo string.

* This base class implementation looks up the drvInfo string in the parameter list.

* \param[in] pasynUser pasynUser structure that driver will modify

* \param[in] drvInfo String containing information about what driver function is being referenced

* \param[out] pptypeName Location in which driver can write information.

* \param[out] psize Location where driver can write information about size of pptypeName */

asynStatus asynPortDriver::drvUserCreate(asynUser *pasynUser,

const char *drvInfo,

const char **pptypeName, size_t *psize)

{

static const char *functionName = "drvUserCreate";

asynStatus status;

int index;

int addr;

status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);

 

status = this->findParam(addr, drvInfo, &index); // ¡¡¡ERROR!!!

 

if (status) {

asynPrint(pasynUser, ASYN_TRACE_ERROR,

"%s:%s: addr=%d, cannot find parameter %s\n",

driverName, functionName, addr, drvInfo);

return(status);

}

pasynUser->reason = index;

asynPrint(pasynUser, ASYN_TRACE_FLOW,

"%s:%s: drvInfo=%s, index=%d\n",

driverName, functionName, drvInfo, index);

return(asynSuccess);

}

 

 

findParam() is not able to find all the PVs and the if statement is executed. I have print each index after the findParam() execution and the param list has not all the PVs, missing just the ones not found.

 

 

Thanks in advance, Adrián.


Replies:
RE: EPICS compilation errors Adrian Martinez via Tech-talk
References:
EPICS compilation errors Adrian Martinez via Tech-talk
RE: EPICS compilation errors Mark Rivers via Tech-talk
RE: EPICS compilation errors Adrian Martinez via Tech-talk

Navigate by Date:
Prev: RE: EPICS compilation errors Adrian Martinez via Tech-talk
Next: Unexpected behavior when setting waveform PVs Érico Nogueira Rolim 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  2021  <20222023  2024 
Navigate by Thread:
Prev: RE: EPICS compilation errors Adrian Martinez via Tech-talk
Next: RE: EPICS compilation errors Adrian Martinez 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  2021  <20222023  2024 
ANJ, 14 Sep 2022 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·