Download presentation
Presentation is loading. Please wait.
1
Advanced Photon Source
asyn: What’s New Mark Rivers, Eric Norum University of Chicago Advanced Photon Source October 17, 2008
2
What is asyn and why to we need it?
EPICS IOC architecture Motivation Standard EPICS interface between device support and drivers is only loosely defined Needed custom device support for each driver asyn provides standard interface between device support and device drivers And a lot more too! October 17, 2008
3
asyn Architecture Device support (or SNL code, another driver, or non-EPICS software) Interfaces (named; pure virtual functions) asynCommon (connect, report, …) asynOctet (write, read, setInputEos,…) Port (named object) Port driver addr=0 addr=1 device device October 17, 2008
4
Standard Interfaces Common interface, all drivers must implement
asynCommon: report(), connect(), disconnect() I/O Interfaces, most drivers implement one or more All have write(), read(), registerInteruptUser() and cancelInterruptUser() methods asynOctet (CHANGED), writeRaw(), readRaw(), flush(), setInputEos(), setOutputEos(), getInputEos(), getOutputEos() asynInt32: getBounds() asynInt8Array(NEW), asynInt16Array(NEW), asynInt32Array: asynUInt32Digital: asynFloat64: asynFloat32Array(NEW), asynFloat64Array: asynGenericPointer(NEW): Miscellaneous interfaces asynOption: setOption() getOption() asynGpib: addressCommand(), universalCommand(), ifc(), ren(), etc. asynDrvUser: create(), free() October 17, 2008
5
New/Changed Interfaces
asynInt8Array, asynInt16Array, asynFloat32Array Just like asynInt32Array but with new data types Support callbacks Have asyn(XXX)ArraySynchIO interfaces as well asynOctet Removed readRaw(), writeRaw(). Use read and write instead. asynGenericPointer(NEW): typedef struct asynGenericPointer { asynStatus (*write)(void *drvPvt, asynUser *pasynUser, void *pvalue); asynStatus (*read)(void *drvPvt, asynUser *pasynUser, void *pvalue); asynStatus (*registerInterruptUser)(void *drvPvt, asynUser *pasynUser, interruptCallbackGenericPointer callback, void *userPvt,void **registrarPvt); asynStatus (*cancelInterruptUser)(void *drvPvt, asynUser *pasynUser, void *registrarPvt); } asynGenericPointer; October 17, 2008
6
asynStandardInterfaces
Greatly reduces driver code when initializing standard interfaces. Just fill in fields in asynStandardInterfaces structure and call asynStandardInterfacesBase->initialize(). typedef struct asynStandardInterfaces { asynInterface common; asynInterface drvUser; asynInterface octet; int octetProcessEosIn; int octetProcessEosOut; int octetInterruptProcess; int octetCanInterrupt; void *octetInterruptPvt; … asynInterface int32; int int32CanInterrupt; void *int32InterruptPvt; asynInterface float64Array; int float64ArrayCanInterrupt; void *float64ArrayInterruptPvt; } asynStandardInterfaces; typedef struct asynStandardInterfacesBase { asynStatus (*initialize)(const char *portName, asynStandardInterfaces *pInterfaces, asynUser *pasynUser, void *pPvt); } asynStandardInterfacesBase; epicsShareExtern asynStandardInterfacesBase *pasynStandardInterfacesBase; October 17, 2008
7
Driver before asynStandardInterfaces
#include <asynDriver.h> #include <asynInt32.h> #include <asynInt8Array.h> #include <asynInt16Array.h> #include <asynInt32Array.h> #include <asynFloat32Array.h> #include <asynFloat64.h> #include <asynFloat64Array.h> #include <asynOctet.h> #include <asynDrvUser.h> ... typedef struct drvADPvt { /* Asyn interfaces */ asynInterface common; asynInterface int32; void *int32InterruptPvt; asynInterface float64; void *float64InterruptPvt; asynInterface int8Array; void *int8ArrayInterruptPvt; asynInterface int16Array; void *int16ArrayInterruptPvt; asynInterface int32Array; void *int32ArrayInterruptPvt; asynInterface float32Array; void *float32ArrayInterruptPvt; asynInterface float64Array; void *float64ArrayInterruptPvt; asynInterface octet; void *octetInterruptPvt; asynInterface drvUser; } drvADPvt; October 17, 2008
8
Driver before asynStandardInterfaces
int drvADImageConfigure(const char *portName, const char *detectorDriverName, int detector) { ... /* Create asynUser for debugging */ pPvt->pasynUser = pasynManager->createAsynUser(0, 0); /* Link with higher level routines */ pPvt->common.interfaceType = asynCommonType; pPvt->common.pinterface = (void *)&drvADCommon; pPvt->common.drvPvt = pPvt; pPvt->int32.interfaceType = asynInt32Type; pPvt->int32.pinterface = (void *)&drvADInt32; pPvt->int32.drvPvt = pPvt; pPvt->float64.interfaceType = asynFloat64Type; pPvt->float64.pinterface = (void *)&drvADFloat64; pPvt->float64.drvPvt = pPvt; pPvt->int8Array.interfaceType = asynInt8ArrayType; pPvt->int8Array.pinterface = (void *)&drvADInt8Array; pPvt->int8Array.drvPvt = pPvt; pPvt->int16Array.interfaceType = asynInt16ArrayType; pPvt->int16Array.pinterface = (void *)&drvADInt16Array; pPvt->int16Array.drvPvt = pPvt; pPvt->int32Array.interfaceType = asynInt32ArrayType; pPvt->int32Array.pinterface = (void *)&drvADInt32Array; pPvt->int32Array.drvPvt = pPvt; pPvt->float32Array.interfaceType = asynFloat32ArrayType; pPvt->float32Array.pinterface = (void *)&drvADFloat32Array; pPvt->float32Array.drvPvt = pPvt; pPvt->float64Array.interfaceType = asynFloat64ArrayType; pPvt->float64Array.pinterface = (void *)&drvADFloat64Array; pPvt->float64Array.drvPvt = pPvt; pPvt->octet.interfaceType = asynOctetType; pPvt->octet.pinterface = (void *)&drvADOctet; pPvt->octet.drvPvt = pPvt; pPvt->drvUser.interfaceType = asynDrvUserType; pPvt->drvUser.pinterface = (void *)&drvADDrvUser; pPvt->drvUser.drvPvt = pPvt; October 17, 2008
9
Driver before asynStandardInterfaces
status = pasynManager->registerInterface(portName,&pPvt->common); if (status != asynSuccess) { errlogPrintf("drvAsynADConfigure ERROR: Can't register common.\n"); return -1; } status = pasynInt32Base->initialize(pPvt->portName,&pPvt->int32); errlogPrintf("drvAsynADConfigure ERROR: Can't register int32\n"); pasynManager->registerInterruptSource(portName, &pPvt->int32, &pPvt->int32InterruptPvt); status = pasynFloat64Base->initialize(pPvt->portName,&pPvt->float64); errlogPrintf("drvAsynADConfigure ERROR: Can't register float64\n"); pasynManager->registerInterruptSource(portName, &pPvt->float64, &pPvt->float64InterruptPvt); status = pasynInt8ArrayBase->initialize(pPvt->portName,&pPvt->int8Array); errlogPrintf("drvAsynADConfigure ERROR: Can't register int8Array\n"); pasynManager->registerInterruptSource(portName, &pPvt->int8Array, &pPvt->int8ArrayInterruptPvt); status = pasynInt16ArrayBase->initialize(pPvt->portName,&pPvt->int16Array); errlogPrintf("drvAsynADConfigure ERROR: Can't register int16Array\n"); pasynManager->registerInterruptSource(portName, &pPvt->int16Array, &pPvt->int16ArrayInterruptPvt); October 17, 2008
10
Driver before asynStandardInterfaces
status = pasynInt32ArrayBase->initialize(pPvt->portName,&pPvt->int32Array); if (status != asynSuccess) { errlogPrintf("drvAsynADConfigure ERROR: Can't register int32Array\n"); return -1; } pasynManager->registerInterruptSource(portName, &pPvt->int32Array, &pPvt->int32ArrayInterruptPvt); status = pasynFloat32ArrayBase->initialize(pPvt->portName,&pPvt->float32Array); errlogPrintf("drvAsynADConfigure ERROR: Can't register float32Array\n"); pasynManager->registerInterruptSource(portName, &pPvt->float32Array, &pPvt->float32ArrayInterruptPvt); status = pasynFloat64ArrayBase->initialize(pPvt->portName,&pPvt->float64Array); errlogPrintf("drvAsynADConfigure ERROR: Can't register float64Array\n"); pasynManager->registerInterruptSource(portName, &pPvt->float64Array, &pPvt->float64ArrayInterruptPvt); status = pasynOctetBase->initialize(pPvt->portName,&pPvt->octet,0,0,0); errlogPrintf("drvAsynADConfigure ERROR: Can't register octet\n"); pasynManager->registerInterruptSource(portName, &pPvt->octet, &pPvt->octetInterruptPvt); status = pasynManager->registerInterface(pPvt->portName,&pPvt->drvUser); errlogPrintf("drvAsynADConfigure ERROR: Can't register drvUser\n"); October 17, 2008
11
Driver after asynStandardInterfaces
#include <asynStandardInterfaces.h> ... typedef struct drvADPvt { /* Asyn interfaces */ asynStandardInterfaces asynInterfaces; } drvADPvt; int drvADImageConfigure(const char *portName, const char *detectorDriverName, int detector) { asynStandardInterfaces *pInterfaces; /* Create asynUser for debugging and for standardBases */ pPvt->pasynUser = pasynManager->createAsynUser(0, 0); /* Set addresses of asyn interfaces */ pInterfaces = &pPvt->asynInterfaces; pInterfaces->common.pinterface = (void *)&drvADCommon; pInterfaces->drvUser.pinterface = (void *)&drvADDrvUser; pInterfaces->octet.pinterface = (void *)&drvADOctet; pInterfaces->int32.pinterface = (void *)&drvADInt32; pInterfaces->float64.pinterface = (void *)&drvADFloat64; pInterfaces->int8Array.pinterface = (void *)&drvADInt8Array; pInterfaces->int16Array.pinterface = (void *)&drvADInt16Array; pInterfaces->int32Array.pinterface = (void *)&drvADInt32Array; pInterfaces->float32Array.pinterface = (void *)&drvADFloat32Array; pInterfaces->float64Array.pinterface = (void *)&drvADFloat64Array; /* Define which interfaces can generate interrupts */ pInterfaces->octetCanInterrupt = 1; pInterfaces->int32CanInterrupt = 1; pInterfaces->float64CanInterrupt = 1; pInterfaces->int8ArrayCanInterrupt = 1; pInterfaces->int16ArrayCanInterrupt = 1; pInterfaces->int32ArrayCanInterrupt = 1; pInterfaces->float32ArrayCanInterrupt = 1; pInterfaces->float64ArrayCanInterrupt = 1; status = pasynStandardInterfacesBase->initialize(portName, pInterfaces, pPvt->pasynUser, pPvt); if (status != asynSuccess) { errlogPrintf("drvADImageConfigure ERROR: Can't register interfaces: %s.\n", pPvt->pasynUser->errorMessage); return -1; } October 17, 2008
12
Generic Device Support
asyn includes generic device support for many standard EPICS records and standard asyn interfaces Eliminates need to write device support in many cases. New hardware can be supported by writing just a driver. Record fields: field(DTYP, “asynInt32”) field(INP, addr, timeout) drvInfoString) Examples: asynInt32 ao, ai, mbbo, mbbi, longout, longin asynInt32Average ai asynUInt32Digital, asynUInt32DigitalInterrupt bo, bi, mbbo, mbbi asynFloat64 ai, ao asynOctet stringin, stringout, waveform asynXXXArray waveform October 17, 2008
13
Generic Device Support – What’s new
Ring buffer for driver callback values (I/O Intr scanned records) Previously values could be lost if the callbacks came in rapid succession. Before the record could process callback value 1, it was replaced with callback value 2. New FIFO (ring buffer) prevents missing callback values for int32, uint32Digital and float64 callbacks. Space is only allocated when record is put into I/O Intr scanning, so no storage penalty for other records. Default ring buffer size is 10, can be changed per record with dbInfo string "FIFO” Can now handle TTL pulse 10 microseconds wide and record will process on both transitions Added support for bi and bo records to asynInt32 interface. Previously these were only supported for asynUInt32Digital. Simplifies drivers that already support asynInt32, no longer need to also support asynUInt32Digital. Added support for callbacks for asyn(int8,int16,int32,float32,float64)Array interfaces. Waveform records can now be I/O Intr scanned, the same as other records. October 17, 2008
14
Future plan? asynPortDriver C++ base class
Greatly simplifies writing an asyn port driver Hide all details of registering interfaces, registering interrupt sources, doing callbacks, default connection management Parameter library Drivers typically need to support a number of parameters that control their operation and provide status information. Most of these can be treated as 32-bit integers, 64-bit floats, or strings. Sequence on new value: New parameter value arrives, or new data arrives from detector. Change values of one or more parameters. For each parameter whose value changes set a flag noting that it changed. When operation is complete, call the registered callbacks for each changed parameter. asynPortDriver provides methods to simplify the above sequence Each parameter is assigned a number, value in the pasynUser-> reason field asynPortDriver has table of parameter values, w/ data type (integer, double, or string), caches the current value, maintains changed flag Drivers use asynPortDriver methods to read the current value from the table, and to set new values in the table. Method to call all registered callbacks for values that have changed since callbacks were last done. October 17, 2008
15
asynPortDriver C++ base class
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value); virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); virtual asynStatus getBounds(asynUser *pasynUser, epicsInt32 *low, epicsInt32 *high); virtual asynStatus readFloat64(asynUser *pasynUser, epicsFloat64 *value); virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars, size_t *nActual, int *eomReason); virtual asynStatus writeOctet(asynUser *pasynUser, const char *value, size_t maxChars, size_t *nActual); Drivers typically don’t need to implement the readXXX functions, base class takes care of everything, i.e. get cached value from parameter library Need to implement the writeXXX methods if any action is needed, otherwise can use base class implementation which just stores parameter in library October 17, 2008
16
asynPortDriver C++ base class
Constructor: asynPortDriver(const char *portName, int maxAddr, int paramTableSize, int interfaceMask, int interruptMask); Needs additional parameters for asynManger->registerPort to be completely general, i.e. attributes (ASYN_MULTIDEVICE and ASYN_CANBLOCK), autoConnect, priority, stackSize October 17, 2008
17
Thanks for your attention
October 17, 2008
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.