Hi Mark,
Thanks for your tips. Sorry for the long email...
> When I look up those parameters in your template file I see that those are mbbo/mbbi records. You said that other parameters are called correctly for both addr=0 and addr=1. Can you see if the mbbo/mbbi records all fail to be called with addr=1 and all other record types are called OK with addr=1?
So, I commented most of my st.cmd file and it look like this now:
< envPaths
# Override default TOP variable
epicsEnvSet("TOP","../..")
epicsEnvSet("EPICS_DB_INCLUDE_PATH", "$(ADCORE)/db")
epicsEnvSet("BPM_TYPE","FMC250M_4CH")
< BPM.config
## Register all support components
dbLoadDatabase("${TOP}/dbd/BPM.dbd")
BPM_registerRecordDeviceDriver (pdbbase)
drvBPMConfigure("$(BPM_NAME)", "$(BPM_ENDPOINT)", "$(BPM_NUMBER)", "$(BPM_TYPE)", "$(BPM_VERBOSE)", "$(BPM_TIMEOUT)", "$(WAVEFORM_MAX_POINTS)", "$(MAXBUFFERS)", "$(MAXMEMORY)")
## Load record instances
dbLoadRecords("${TOP}/db/BPMAcq.template", "P=${P}, R=${R}, ACQ_NAME=ACQ, PORT=$(PORT), ADDR=0, TIMEOUT=1")
dbLoadRecords("${TOP}/db/BPMAcq.template", "P=${P}, R=${R}, ACQ_NAME=ACQ_PM, PORT=$(PORT), ADDR=1, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMSwitching.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMActiveClk.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMAdcCommon.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/MonitDspCtl.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMInfo.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMSP.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
dbLoadRecords("$(ASYN)/db/asynRecord.db","P=${P}, R=${R}asyn,PORT=$(PORT),ADDR=0,OMAX=80,IMAX=80")
dbLoadRecords("${TOP}/db/BPMTrigger.template", "P=${P}, R=${R}, PORT=$(PORT), TRIGGER_NAME=TRIGGER, TRIGGER_CHAN=0, ADDR=0, TIMEOUT=1")
dbLoadRecords("${TOP}/db/BPMTrigger.template", "P=${P}, R=${R}, PORT=$(PORT), TRIGGER_NAME=TRIGGER, TRIGGER_CHAN=1, ADDR=1, TIMEOUT=1")
#< triggerBPM.cmd
#< fmc250m_4ch.cmd
#< waveformPlugins.cmd
#< waveformFilePlugins.cmd
#< waveformFFTRecords.cmd
#< statsPlugins.cmd
#< save_restore.cmd
# Turn on asynTraceFlow and asynTraceError for global trace, i.e. no connected asynUser.
asynSetTraceIOMask("$(BPM_NAME)",0,0x2)
#asynSetTraceMask("", 0, 17)
#asynSetTraceMask("$(BPM_NAME)",0,0xff)
iocInit()
#< initBPMCommands
# save things every thirty seconds
#create_monitor_set("auto_settings.req", 30,"P=${P}, R=${R}")
#set_savefile_name("auto_settings.req", "auto_settings_${P}${R}.sav")
Only the BPMAcq.template and the BPMTrigger.template files are loaded. Plus, I added right at the end of my readUInt32Digital (), readInt32 () and readFloat64 () functions the following snippet (example showing for int32):
asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
"%s:%s: readInt32 parameter addr = %d, value = %u, functionId = %d, paramName = %s\n",
driverName, functionName, addr, *value, function, paramName);
So, it should print the print everytime a read is executed.
The IOC log is as follows:
@@@ Welcome to procServ (procServ Process Server 2.7.0)
@@@ Use ^X to kill the child, auto restart is ON, use ^T to toggle auto restart
@@@ procServ server PID: 24581
@@@ Server startup directory: /opt/epics/startup/ioc/bpm-epics-ioc/iocBoot/iocBPM
@@@ Child startup directory: /opt/epics/startup/ioc/bpm-epics-ioc/iocBoot/iocBPM
@@@ Child "halcs-be-ioc21" started as: ./runBPM.sh
@@@ Child "halcs-be-ioc21" is SHUT DOWN
@@@ procServ server started at: Wed Jun 12 21:11:09 2019
@@@ 0 user(s) and 0 logger(s) connected (plus you)
@@@ ^R or ^X restarts the child, ^Q quits the server
@@@ Restarting child "halcs-be-ioc21"
@@@ (as ./runBPM.sh)
@@@ The PID of new child "halcs-be-ioc21" is: 24608
@@@ @@@ @@@ @@@ @@@
/var/log/halcs/halcsd11_be0_info.log found. Parsing it to find which FMC board we have.
Synthesis name: bpm-gw-bo-siriu+
FMC 0 name: LNLS_FMC250M_REGS
FMC 1 name: LNLS_FMC250M_REGS
Using st.cmd file: stBPM250M.cmd
< envPaths
epicsEnvSet("IOC","iocBPM")
epicsEnvSet("TOP","/root/postinstall/apps/bpm-app/bpm-epics-ioc")
epicsEnvSet("SUPPORT","/opt/epics/synApps-lnls-R1-2-1/support")
epicsEnvSet("EPICS_BASE","/opt/epics/base")
epicsEnvSet("ASYN","/opt/epics/synApps-lnls-R1-2-1/support/asyn-R4-35")
epicsEnvSet("SSCAN","/opt/epics/synApps-lnls-R1-2-1/support/sscan-R2-11-2")
epicsEnvSet("CALC","/opt/epics/synApps-lnls-R1-2-1/support/calc-R3-7-2")
epicsEnvSet("AUTOSAVE","/opt/epics/synApps-lnls-R1-2-1/support/autosave-R5-9")
epicsEnvSet("BUSY","/opt/epics/synApps-lnls-R1-2-1/support/busy-R1-7-1")
epicsEnvSet("AREA_DETECTOR","/opt/epics/synApps-lnls-R1-2-1/support/areaDetector-R3-6")
epicsEnvSet("ADCORE","/opt/epics/synApps-lnls-R1-2-1/support/areaDetector-R3-6/ADCore")
epicsEnvSet("AREA_DETECTOR_COMPAT","/opt/epics/synApps-lnls-R1-2-1/support/areaDetector-R3-6/ADCore")
# Override default TOP variable
epicsEnvSet("TOP","../..")
epicsEnvSet("EPICS_DB_INCLUDE_PATH", "/opt/epics/synApps-lnls-R1-2-1/support/areaDetector-R3-6/ADCore/db")
epicsEnvSet("BPM_TYPE","FMC250M_4CH")
< BPM.config
# Set externally
#epicsEnvSet("BPM_ENDPOINT","tcp://10.2.117.47:9999")
#epicsEnvSet("BPM_NUMBER","17")
epicsEnvSet("BPM_VERBOSE","0")
epicsEnvSet("BPM_TIMEOUT","2000")
epicsEnvSet("WAVEFORM_MAX_POINTS", "100000")
epicsEnvSet("QSIZE", "20")
# Must be greater than asyn MAX_ADDR when using NDStats plugin
epicsEnvSet("MAX_SIGNALS", "30")
epicsEnvSet("NCHANS", "10")
epicsEnvSet("RING_SIZE", "10000")
epicsEnvSet("MAXBUFFERS", "0")
# 50MB limit for NDArrays
epicsEnvSet("MAXMEMORY", "50000000")
epicsEnvSet("COEFF_ARRAY_SIZE", "20")
# PV prefixes
epicsEnvSet("P", "BO-28U:")
epicsEnvSet("R", "DI-BPM:")
epicsEnvSet("PORT", "BPM")
epicsEnvSet("BPM_NAME","BPM")
## Register all support components
dbLoadDatabase("../../dbd/BPM.dbd")
BPM_registerRecordDeviceDriver (pdbbase)
Warning: IOC is booting with TOP = "../.."
but was built with TOP = "/root/postinstall/apps/bpm-app/bpm-epics-ioc"
drvBPMConfigure("BPM", "ipc:///tmp/malamute", "21", "FMC250M_4CH", "0", "2000", "100000", "0", "50000000")
## Load record instances
dbLoadRecords("../../db/BPMAcq.template", "P=BO-28U:, R=DI-BPM:, ACQ_NAME=ACQ, PORT=BPM, ADDR=0, TIMEOUT=1")
dbLoadRecords("../../db/BPMAcq.template", "P=BO-28U:, R=DI-BPM:, ACQ_NAME=ACQ_PM, PORT=BPM, ADDR=1, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMSwitching.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMActiveClk.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMAdcCommon.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/MonitDspCtl.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMInfo.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
#dbLoadRecords("${TOP}/db/BPMSP.template", "P=${P}, R=${R}, PORT=$(PORT), ADDR=0, TIMEOUT=1")
dbLoadRecords("/opt/epics/synApps-lnls-R1-2-1/support/asyn-R4-35/db/asynRecord.db","P=BO-28U:, R=DI-BPM:asyn,PORT=BPM,ADDR=0,OMAX=80,IMAX=80")
dbLoadRecords("../../db/BPMTrigger.template", "P=BO-28U:, R=DI-BPM:, PORT=BPM, TRIGGER_NAME=TRIGGER, TRIGGER_CHAN=0, ADDR=0, TIMEOUT=1")
dbLoadRecords("../../db/BPMTrigger.template", "P=BO-28U:, R=DI-BPM:, PORT=BPM, TRIGGER_NAME=TRIGGER, TRIGGER_CHAN=1, ADDR=1, TIMEOUT=1")
#< triggerBPM.cmd
#< fmc250m_4ch.cmd
#< waveformPlugins.cmd
#< waveformFilePlugins.cmd
#< waveformFFTRecords.cmd
#< statsPlugins.cmd
#< save_restore.cmd
# Turn on asynTraceFlow and asynTraceError for global trace, i.e. no connected asynUser.
asynSetTraceIOMask("BPM",0,0x2)
#asynSetTraceMask("", 0, 17)
#asynSetTraceMask("$(BPM_NAME)",0,0xff)
iocInit()
Starting iocInit
############################################################################
## EPICS R3.15.6
## EPICS Base built Jun 7 2019
############################################################################
2019/06/12 21:11:10.995 drvBPM:readInt32: readInt32 parameter addr = 0, value = 0, functionId = 52, paramName = BPM_MODE
2019/06/12 21:11:10.996 drvBPM:readInt32: readInt32 parameter addr = 0, value = 0, functionId = 123, paramName = ACQ_CHANNEL
2019/06/12 21:11:10.996 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 125, paramName = ACQ_TRIGGER
2019/06/12 21:11:10.996 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 1, functionId = 126, paramName = ACQ_TRIGGER_EVENT
2019/06/12 21:11:10.997 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 127, paramName = ACQ_TRIGGER_REP
2019/06/12 21:11:10.998 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 129, paramName = ACQ_TRIGGER_POL
2019/06/12 21:11:10.999 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 133, paramName = ACQ_DATA_TRIG_CHAN
2019/06/12 21:11:11.001 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 1, functionId = 158, paramName = TRIGGER_DIR
2019/06/12 21:11:11.002 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 1, functionId = 159, paramName = TRIGGER_DIR_POL
2019/06/12 21:11:11.003 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 166, paramName = TRIGGER_RCV_SRC
2019/06/12 21:11:11.004 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 167, paramName = TRIGGER_TRN_SRC
2019/06/12 21:11:11.005 drvBPM:readFloat64: readFloat64 parameter addr = 0, value = 1.000000, functionId = 124, paramName = ACQ_UPDATE_TIME
2019/06/12 21:11:11.006 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 1000, functionId = 120, paramName = ACQ_SAMPLES_PRE
2019/06/12 21:11:11.006 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 121, paramName = ACQ_SAMPLES_POST
2019/06/12 21:11:11.006 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 1, functionId = 122, paramName = ACQ_NUM_SHOTS
2019/06/12 21:11:11.007 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 128, paramName = ACQ_TRIGGER_THRES
2019/06/12 21:11:11.008 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 130, paramName = ACQ_TRIGGER_SEL
2019/06/12 21:11:11.009 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 131, paramName = ACQ_TRIGGER_FILT
2019/06/12 21:11:11.010 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 132, paramName = ACQ_TRIGGER_HWDLY
2019/06/12 21:11:11.010 drvBPM:readInt32: readInt32 parameter addr = 0, value = 0, functionId = 157, paramName = TRIGGER_CHAN
2019/06/12 21:11:11.011 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 160, paramName = TRIGGER_RCV_CNT_RST
2019/06/12 21:11:11.013 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 161, paramName = TRIGGER_TRN_CNT_RST
2019/06/12 21:11:11.014 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 1, functionId = 162, paramName = TRIGGER_RCV_LEN
2019/06/12 21:11:11.015 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 1, functionId = 163, paramName = TRIGGER_TRN_LEN
2019/06/12 21:11:11.016 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 168, paramName = TRIGGER_RCV_IN_SEL
2019/06/12 21:11:11.017 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 169, paramName = TRIGGER_TRN_OUT_SEL
cas warning: Configured TCP port was unavailable.
cas warning: Using dynamically assigned TCP port 44921,
cas warning: but now two or more servers share the same UDP port.
cas warning: Depending on your IP kernel this server may not be
cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)
2019/06/12 21:11:11.529 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 7, functionId = 164, paramName = TRIGGER_CNT_RCV
2019/06/12 21:11:11.529 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 0, value = 0, functionId = 165, paramName = TRIGGER_CNT_TRN
2019/06/12 21:11:11.530 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 1, value = 0, functionId = 164, paramName = TRIGGER_CNT_RCV
2019/06/12 21:11:11.530 drvBPM:readUInt32Digital: readUInt32Read parameter addr = 1, value = 0, functionId = 165, paramName = TRIGGER_CNT_TRN
iocRun: All initialization complete
#< initBPMCommands
# save things every thirty seconds
#create_monitor_set("auto_settings.req", 30,"P=${P}, R=${R}")
#set_savefile_name("auto_settings.req", "auto_settings_${P}${R}.sav")
epics>
So, loading the BPMAcq.template (which has longout/longin, mbbo/mbbi, ao/ai records) with addr = 0 and addr = 1 showed that only read functions for addr = 0. The longin records were also called (last 4 readUInt32Read messages) (BPMTrigger.template has 2 records that are longin), but I guess that's because PINI = "yes" for those *in records. Does that make sense?
> I also notice that some of your mbbo records use asynInt32, e.g. BPM_MODE, and some use asynUInt32Digital, e.g. ACQ_TRIGGER. Does one of the interfaces fail and one work for mbbo records? Why are you using different interfaces for different records?
It seems that they all fail for addr = 1 (different from what I had previously said), except the case for longin records (but I think this is another this, because for longin values are not read on devce init, right?). I was using differente interfaces because BPM_MODE is just an IOC parameter to select between two operation modes and ACQ_TRIGGER is a hardware value that are mapped to a register inside an FPGA. I guess I could have used the same interface for both, but I though it made sense to distinguish those two.
> That code is called for every mbbo record unless init_common returns an error. If init_common returns an error it always prints an error message. Did you check carefully that there are no error messages right after iocInit?
> If you still think your driver is not being called for addr=1 with those parameters you could add a debugging printf just before the above call that prints pPvt->portName, pPvt->addr, and pPvt->userParam. That will show you if it is calling the port for addr=1 and that parameter string.
So, I added the following to devAsynUInt32Digital.c:
printf("initLo: portName = %s, addr = %d, userParam = %s\n",
pPvt->portName, pPvt->addr, pPvt->userParam);
/* Read the current value from the device */
status = pasynUInt32DigitalSyncIO->read(pPvt->pasynUserSync,
&value, pPvt->mask,pPvt->pasynUser->timeout);
...
printf("initMbbo: portName = %s, addr = %d, userParam = %s\n",
pPvt->portName, pPvt->addr, pPvt->userParam);
/* Read the current value from the device */
status = pasynUInt32DigitalSyncIO->read(pPvt->pasynUserSync,
&value, pPvt->mask, pPvt->pasynUser->timeout);