Presentation is loading. Please wait.

Presentation is loading. Please wait.

The ASYN Software Module

Similar presentations

Presentation on theme: "The ASYN Software Module"— Presentation transcript:

1 The ASYN Software Module
Andy Foster Observatory Sciences Limited

2 Outline Where is the ASYN layer? What is ASYN? Key concepts of ASYN
ASYN Architecture Vocabulary Asyn Port Asyn Interfaces Asyn Command Asyn User AsynManager Synchronous control flow Asynchronous control flow Writing ASYN device support Writing ASYN driver support Porting existing drivers to ASYN Asyn Trace asynRecord Summary Where to find more information

3 Where is the ASYN layer? Traditionally, the interface between device and driver support Historical name: supports “synchronous” as well as “asynchronous” devices CHANNEL ACCESS DATABASE ACCESS RECORD SUPPORT DEVICE SUPPORT ASYN LAYER DRIVER SUPPORT

4 What is ASYN? The EPICS interface between device support and driver support was only loosely defined. Device support has direct access to the record structure and can manipulate all fields A driver support library could have almost any API. It can even be an externally provided general purpose library ASYN is a software module which provide facilities for interfacing device and driver support read(), write() interface with parameter and address passing Handles some of the generic “housekeeping” tasks in device support

5 What is ASYN? Asyn provides implementation of device support for standard records ai,ao,bi,bo,mbbi,mbbo,waveform and so on Handles the details of the interaction with the record fields Asyn drivers only need to read/write data to/from hardware and the driver support layer No need to write support specifically for every record But not limited to use with EPICS device/driver support Only depends on libCom from EPICS base Other ‘C’ code can talk directly to an Asyn support module (e.g. SNL, genSub) Some support for generic communication protocols Serial interfaces RS232/485 Ethernet TCP/IP, UDP/IP

6 Key concepts of ASYN The ASYN layer has two interfaces:
Upwards to the device support layer. This has been written for all the standard EPICS records. Downwards to a device driver Here a set of standard interfaces have been defined for both message passing (e.g. serial) and register reading/writing (e.g. DAC based devices). Therefore, for a new piece of hardware, we only need to write a driver which implements one or more of the standard interfaces to the ASYN layer.

7 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

8 Vocabulary: ASYN Port Provides access to a device
portName (string) provides the reference to the hardware Drivers register a port, device support connects to it One or many devices can be connected, addresses identify individual devices May be blocking or non-blocking Depends on speed of device Is configured in startup script: drvAsynSerialPortConfigure ("COM2", "/dev/sttyS1“) drvAsynIPPortConfigure ("fooServer", " :40000“) myDeviceDriverConfigure ("portname", parameters)

9 Vocabulary: ASYN Interfaces
Device support (and other ASYN clients) communicate with driver support through defined interfaces Each interface defines a table of driver functions or methods Examples are: asynOctet (read, write, setInputEOS, etc) Used for message based I/O: serial, TCP/IP asynUInt32Digital (read, write, Used for bit field registers: status word, switches, etc asynInt32, asynInt32Array (read, write, getBounds, …) Integer registers: ADC, DAC, encoder, … Integer arrays: spectrum analyzer, oscilloscope asynFloat64, asynFloat64Array (read, write,…) Floating point registers and arrays

10 Vocabulary: ASYN Interfaces
asynCommon (report, connect, disconnect) report: Generates a report about the hardware device connect/disconnect: connect/disconnect to the hardware device Every driver must implement these! Every port has one or many interfaces

11 Vocabulary: ASYN Command
An ASYN driver defines a set of commands it supports e.g. enum FINS_COMMANDS { FINS_MODEL, …, … } (Factory Intelligent Network Service - PLC) In an EPICS database the ASYN command is the argument at the end of the INP or OUT field. The DTYP field is set to the type of ASYN interface being used e.g. record(waveform, "$(device):MODEL:CPU") { field(DTYP, "asynOctetRead") field(INP, addr, timeout) FINS_MODEL") }

12 Vocabulary: ASYN Command
ASYN commands are supported through a special interface. asynDrvUser ( create, getType, destroy) create: maps the ENUM command to the string used in INP/OUT in the database getType: Looks up ENUM command based on the database string. Destroys the resources created by “create”. asynStatus drvUserCreate(void *pvt, asynUser *pasynUser, const char *drvInfo, const char **pptypeName, size_t *psize) { if (drvInfo) if (strcmp("FINS_MODEL", drvInfo) == 0) pasynUser->reason = FINS_MODEL; } else { }

13 Vocabulary: asynUser Identifies the client e.g. EPICS record.
Each client needs one asynUser An “asynUser” must not be shared between parts of code that can simultaneously access a driver. For example, device support for EPICS records should create a separate “asynUser” for each record instance. By creation of an “asynUser” we obtain a handle for accessing ports and for calling interfaces implemented by drivers. In writing ASYN device support, before doing anything you must obtain a pointer to an asynUser pasynUser=pasynManager->createAsynUser( processCallback, timeoutCallback); Provide 2 callbacks: processCallback is called when you are scheduled to access the port timeoutCallback is called if port times out

14 Vocabulary: asynManager
Core of ASYN. Creates threads for blocking ports. Registers and finds ports and interfaces. Schedules access to ports. Device support and driver support do not need to implement queues or semaphores, this is handled by asynManager. There is exactly one global instance: pasynManager Clients ask asynManager for services pasynManager->connectDevice(pasynUser , "portname", address) pasynManager->findInterface(pasynUser, interfaceType, ...) pasynManager->queueRequest(pasynUser, priority, timeout)

15 Control flow for non-blocking port
Record processing calls device support. Device support calls queueRequest. Since the port is synchronous, queueRequest calls “lockPort” and then “processCallback”. “processCallback” calls the driver. The driver returns the results of the I/O operation to “processCallback”. “processCallback” returns to “queueRequest”, which calls “unlockPort” and returns to device support, which returns to record support to complete processing. Used for devices that provide fast responses, typically VME or register based devices

16 Control flow for blocking port
Record processing calls device support with PACT=0. Device support calls queueRequest. queueRequest places the request on the driver queue (the application thread can now continue). The portThread removes the request from the queue. The portThread calls the users “processCallback” located in device support. “processCallback” calls the driver. The driver blocks until the operation is complete and returns the results of the I/O operation to “processCallback”. “processCallback” calls the EPICS routine “callbackRequestProcessCallback” to make the record process again. Record support calls device support again, with PACT=1. Device support updates fields in the record and returns to record support to complete the processing. Used for ‘slow’ devices like serial or ethernet

17 Writing ASYN Device Support Step 1: Connect to the port
Before doing anything you must obtain a pointer to an asynUser pasynUser=pasynManager->createAsynUser( processCallback, timeoutCallback); Connect to the device (port, address) status=pasynManager->connectDevice(pasynUser, port, addr); Find the interface (e.g. asynOctet) pasynInterface=pasynManager->findInterface (pasynUser, asynOctetType, 1); We can now find the address of the asynOctet interface and of the private driver structure: pasynOctet =(asynOctet *)pasynInterface->pinterface; drvPvt = pasynInterface->pdrvPvt; The following call is made from processCallback when we have access to the port (next slide): pasynOctet->read ( drvPvt, pasynUser,...

18 Step 2: Request access to the port
Ask asynManager to put your request to the queue status=pasynManager->queueRequest(pasynUser, priority, timeout); Priorities: asynQueuePriority{Low|Medium|High} queueRequest never blocks. Blocking port: AsynManager will call your processCallback when port is free. The callback runs in port thread. Non blocking port: queueRequest calls processCallback. If port is not free for timeout seconds, asynManager calls timeoutCallback. In processCallback, you have exclusive access to the port.

19 Step 3: processCallback (asynOctet methods)
Flush (discard old input) status=pasynOctet->flush(drvPvt, pasynUser); Write: Status = pasynOctet->write( drvPvt,pasynUser,data,size,&bytesWritten); Actual number of written bytes is returned in bytesWritten. Read: status=pasynOctet->read(drvPvt, pasynUser,buffer,maxsize,&bytesReceived,&eomReason); Actual number of written bytes is returned in bytesReceived. End of message reason is returned in eomReason.

20 Step 3: processCallback (asynInt32 methods)
Get bounds status=pasynInt32->getBounds( drvPvt, pasynUser, &low, &high); Limits for valid register values are returned in low and high. Write status=pasynInt32->write( drvPvt, pasynUser, value); Read status=pasynInt32->read( drvPvt, pasynUser, &value); Current register value is returned in value.

21 Rules for using driver methods
Never use I/O methods outside processCallback. Only talk to the port that has called you back. You can do as many I/O as you like. You must always use the interface method table pasyn{Octet|Int32|…} to access the driver. You always need pasynUser as an argument. All other clients of the same port (even with other addresses) have to wait until you are finished. So, remember, it’s not nice of you if your device blocks for a long time!

22 Writing ASYN Driver Support
Since the interface to the device support layer has been written for most common EPICS records, we are more likely to need to write an ASYN driver. Starting design of a new ASYN based driver Decide whether your device is synchronous or asynchronous (timing) Choose a number of commands which your driver will implement Identify which standard interfaces are appropriate for communicating with the device A driver must maintain a data structure for all its internal storage Common practice for most drivers – not just asyn A pointer to this structure will be passed around as an argument to the various callbacks to the driver code

23 Writing ASYN Driver Support
asynCommon and asynDrvUser must be registered with asynManager For each “data” interface, you must supply a number of methods read, write are the main ones Each “data” interface must be initialised

24 Example ASYN driver: foo
#include <asynDriver.h> #include <asynDrvUser.h> #include <asynInt32.h> ... Define functions here... static struct asynCommon foo_Common = { fooReport, fooConnect, fooDisconnect }; static asynDrvUser foo_DrvUser = { fooCreate, fooGetType, fooDestroy}; static asynInt32 foo_Int32 = { fooInt32Read, fooInt32Write, NULL, NULL, NULL}; typedef struct drvPvt { ... char *portName; asynInterface common; asynInterface drvUser; asynInterface int32; } drvPvt; /* Add asynInterface lines to a non-asyn driver */

25 ASYN driver initialisation routine
fooInit( char *portName, char *address ) /* startup script */ { drvPvt *pFoo; pFoo = callocMustSucceed(1, sizeof(drvPvt), FUNCNAME); pdrvPvt->portName = epicsStrDup(portName); pFoo->common.interfaceType = asynCommonType; pFoo->common.pinterface = (void *)&foo_Common; pFoo->common.drvPvt = pFoo; pFoo->drvUser.interfaceType = asynDrvUserType; pFoo->drvUser.pinterface = (void *)&foo_DrvUser; pFoo->drvUser.drvPvt = pFoo; pFoo->int32.interfaceType = asynInt32Type; pFoo->int32.pinterface = (void *)&foo_Int32; pFoo->int32.drvPvt = pFoo; pasynManager->registerPort( pFoo->portName, ASYN_MULTIDEVICE | ASYN_CANBLOCK, /* ASYN_MULTIDEVICE set: port supports > 1 device */ /* ASYN_CANBLOCK set: separate thread for the port */ 1, /* autoconnect: asynmanager connects automatically */ 0, /* medium priority for thread */ 0 ) /* default stack size for thread */ pasynManager->registerInterface (pFoo->portName, &pFoo->common); (pFoo->portName, &pFoo->drvUser); pasynInt32Base->initialize (pFoo->portName, &pFoo->int32); }

26 Implementation of driver “read” function
static asynStatus fooInt32Read( void *drvPvt, asynUser *pasynUser, epicsInt32 *value) { drvPvt *pdrvPvt = (drvPvt *)drvPvt; epicsInt32 addr; /* Find out which address on the device we are reading */ pasynManager->getAddr(pasynUser,&addr); /* pasynUser->reason is set in the asynDrvUser create method – see earlier */ switch ( pasynUser->reason ) case AMP_GAIN: *value = readAmpGainFromDevice(); break; case AMP_CLOCK_READ: *value = readAmpClock(); } return asynSuccess;

27 Porting existing drivers to ASYN
Depends on the existing design Does it have both device and driver support? Device support is supplied by asyn so remove or untangle existing device support Identify and name specific commands to communicate with the device Implement an enum type with the commands and a lookup table for string representations Implement driver read + write functions Typically with big switch/case structure to handle different ‘reasons’ or ‘commands’ Implement driver structure A driver structure should already exist (common in way of keeping track of a device) Add the asyn interface pointers to the structure Initialisation routine must register and initialize the relevant interfaces

28 Vocabulary: asynTrace
Diagnostic facility Provides routines to call for diagnostic messages: asynPrint(), asynPrintIO() Several masks or levels can be selected for debugging purposes Provides consistent debugging mechanism for drivers

29 asynRecord Special record type that can use all asyn interfaces.
Can connect to different ports at run-time. Is a good debug tool. Access to options, including tracing. Comes with set of medm screens for different interfaces. Can handle simple devices: e.g. asynOctet: write one string, read one string If a new instrument arrives that has a serial, GPIB or ethernet port, then it is often possible to communicate with it just by attaching an asynRecord i.e. a database containing one record!

30 asynRecord medm screens

31 Summary Advantages of ASYN
Drivers implement standard interfaces that can be accessed from: Multiple record types SNL programs Other drivers Generic device support eliminates the need for separate device support in 90% of cases Consistent trace/debugging at (port, addr) level asynRecord can be used for testing, debugging, and actual I/O applications Easy to add ASYN interfaces to existing drivers: Register port, implement interface write(), read() and change debugging output Preserve 90% of driver code

32 More information AsynDriver StreamDevice linuxGpib
StreamDevice linuxGpib Drivers/device supports using asynDriver Talks about asynDriver

Download ppt "The ASYN Software Module"

Similar presentations

Ads by Google