V4 Link Support Tutorial

From EPICSWIKI
Revision as of 15:15, 30 September 2005 by MartyKraimer (talk | contribs)

EPICS: IOC Link Support Tutorial Sept 30 2005


Overview

The V4 link support is a replacement for V3

  1. DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK
  2. device DBD definition and device support
  3. driver DBD definition and driver support

The link support model is:

  • For each link, record support defines a list of interfaces it can use for communicating with link support
  • Link support defines the set of interfaces it implements

Link support has no knowledge of what record types are using it and record support has no knowledge about link support other than the interface it is using.

EPICS base defines a standard set of interfaces for link support. The intention is that the set includes enough functionality such that most link support can be implemented via just these interfaces.

The interfaces support all the functionality needed by Channel/Database access and by the generic EPICS device support supplied by asynDriver. Since asynDriver is intended as a framework for interfacing to most hardware, this means that the interfaces supplied and used by base allows support for most hardware. The support can communicate with the hardware however it wants but must implement some set of the interfaces defined by base.

This document gives a brief overview of the V4 link support model.


Database Definitions For Links

This section first reviews the DBD syntax related to link definitions. It then gives a brief description of link related definitions in dbCommon.dbd

Syntax

A record link has the syntax:

    link(linkDirection,interface(interfaceName,...))

A link itself has the syntax:

    link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))

where

linkDirection
Must be one of none,in,out,process, or inout. Compatible checks are made to match the interface with a field.
interface
This is a list of the interfaces that the record support understands.
choiceName
UTF-8 string that describes the choice
interfaceName
The name of an interface via which record support communicates with device support.
dataStructName
The name of a struct containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.

When a record instance is created the choiceName and interfaceName select the support to attach to a record link. The interfaceName must be one of the interface names the record has listed as a valid type and linkDirection must be compatible with the linkDirection the record type specified.

Standard Definitions For Channel/Database Access

These are the database definitions defined in dbCommon are used by the base supplied support for Channel/Database access.

Data Structures

The complete set of definitions are defined in "V4 DB RecordCommon".

    struct(MonitorLinkData) {
        field(pvname,string) { link}
        field(process,boolean) // process this record when monitor occurs
        field(inheritSeverity,boolean)
    }
    struct(InputLinkData) {
        field(pvname,string) { link}
        field(process,boolean)
        field(wait,boolean)
        field(timeout,float64)
        field(block,boolean)
        field(inheritSeverity,boolean)
    }
    ... also OutputLinkData and ProcessLinkData

A look at the fields shows that these are what is required to implement the V4 semantics for Channel/Database access links.

Link Definitions

Link support is provided for

  • input
    • monitor support
    • input support
  • output
  • process

For input and output The following data types are supported:

  • primitive types
  • string
  • arrays of primitive types and strings

"V4 DB RecordCommon" describes the complete set of link definitions supplied by EPICS base. These are:

    link(process,processLink,ProcessLinkData,interface(ProcessLink))
    link(in,monitorLink,MonitorLinkData interface(
        LinkBoolean,
        LinkInt16,LinkInt32,LinkInt64,
        LinkFloat32,LinkFloat64,
        LinkString
    ))
    link(in,monitorLinkArray,MonitorLinkData interface(
        LinkArrayOctet,LinkArrayBoolean,
        LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,
        LinkArrayFloat32,LinkArrayFloat64,
        LinkArrayString
    ))
    link(in,inputLink,InputLinkData interface(
        LinkBoolean,
        LinkInt16,LinkInt32,LinkInt64,
        LinkFloat32,LinkFloat64,
        LinkString
    ))
    link(in,inputLinkArray,InputLinkData interface(
        LinkArrayOctet,LinkArrayBoolean,
        LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,
        LinkArrayFloat32,LinkArrayFloat64,
        LinkArrayString
    ))
    link(in,outputLink,OutputLinkData interface(
        LinkBoolean,
        LinkInt16,LinkInt32,LinkInt64,
        LinkFloat32,LinkFloat64,
        LinkString
    ))
    link(in,outputLinkArray,OutputLinkData interface(
        LinkArrayOctet,LinkArrayBoolean,
        LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,
        LinkArrayFloat32,LinkArrayFloat64,
        LinkArrayString
    ))

These are the link definitions for the Channel/Database access link support supplied with base. The support registers support for processLink, monitorLinkArrayOctet, ...

asynDriver link support

These are definitions that are used by the standard EPICS device support for asynDriver. Since asynDriver is a generic way of interfacing arbitrary hardware support, this is a generic way of attaching links in records to hardware.

Data Definitions

    struct(AsynLinkData) {
        field(portName,string)
        field(addr,int32)
        field(timeout,float64)
        field(drvPvt,string)
    }

link definitions

    link(inout,asynInt32,AsynLinkData,interface(LinkInt32))
    link(in,asynInt32Average,AsynLinkData,interface(LinkInt32))
    link(in,asynInt32Monitor,AsynLinkData,interface(LinkInt32))
    link(inout,asynFloat64,AsynLinkData,interface(LinkFloat64))
    link(in,asynFloat64Average,AsynLinkData,interface(LinkFloat64))
    link(in,asynFloat64Monitor,AsynLinkData,interface(LinkFloat64))
    link(in,asynDigitalMonitor,AsynLinkData,interface(AsynDigital))
    link(inout,asynDigital,AsynLinkData,interface(AsynDigital)))
    link(inout,asynInt32Array,AsynLinkData,interface(LinkArrayInt32)))
    link(inout,asynFloat64Array,AsynLinkData,interface(LinkArrayFloat64)))
    link(inout,asynOctet,AsynLinkData,interface(AsynOctet)))

This is the set of definitions for the standard EPICS device support implemented by asynDriver. Although, at least for the first few V4 releases, asynDriver will not be part of base, they are shown here because the LinkInt32,... interface definitions are defined as part of base. Again it is expected that almost all hardware support be created by implementing a combination of these link interface definitions or the interfaces implemented by Channel/Database access link support. ---

Link Support

Overview

An arbitrary number of Link Support implementations can exist. An implementation can be either soft support or support that communicates with hardware.

Other link support can also be supplied. New support should try very hard to implement the standard interfaces supplied by EPICS base. These are the interfaces that the record types supplied with base know how to use.

Soft support should try to implement the same interfaces implemented by the Channel/Database access support supplied with base. The support can, of course, define data structures for it's own use. Implementing these interfaces means that nthe support will work for the same set of record links as the Channel/Database access support.

Hardware support should, if possible, also implement the same interfaces implemented by the Channel/Database access support. Message based support may also have to implement the AsynOctet interface but this interface is only used by a few record links.


This section describes the interfaces implemented by all link support and then the standard interfaces used by the records supplied with base.

Link and MonitorLink

    interface Link {
        void report(int16 level);
        void cancel();
        void destroy();
        void initialize();
        void connect();
        void disconnect();
    }
    interface MonitorLink {
        void addMonitor(Callback callback);
        void removeMonitor();
    }

Link is an interface that must be implemented by every link support. An instance of this is connected to each DbfLink field. The Link methods are:

  • report - report
  • cancel - Cancel any outstanding I/O
  • destroy - This is called if the field is being changed after initialization or if the record is being removed.
  • initialize - Called to initialize a link.
  • connect - Called to connect. Note that this is different than initilization.
  • disconnect - disconnect.

MonitorLink is an interface that is implemented by link support that supports monitors. An example is support for hardware interrupts. The MonitorLink methods are:

  • addMonitor - Add a monitor callback
  • removeMonitor - Remove monitor

Normally record support does not need to call any of the Link or MonitorLink methods since database access does this automatically. For example if a link field is modified via a channel access put, database access will call destroy before modifying the link and initialize and connect after the link is modified.

Neither Link or MonitorLink is listed in the link database definition.

Definitions that apply to Process,Monitor,Input,and Output support

These are the definitions used by the Channel/Database access support supplied with base. It is also used by the standard EPICS support from asyn.

    enum LinkWaitResult {
        linkNoop,           // Nothing was done, e.g. link is null link
        linkDone,           // field was modified. No wait is necessary
        linkWait,           // waiting. can do additional procsssing
        linkWaitBlock,      // waiting. dont do additional processing until
    }
    interface Callback {
        void done();
        void failure();
    }

Process Link Support

    interface ProcessLinkSupport<type> {
        LinkWaitResult process(Callback callback);
    }

Octet Support

There is no support for octet but there is support for an array of octets.


    interface LinkArrayOctet {
        LinkWaitResult getWait(octet[] data,Callback callback);
        LinkWaitResult putWait(octet[] data,Callback callback);
    }

The data source must be an array of octets or the connect request will fail.

GENERIC QUESTION The data is passed as primitive or arrays of primitive types. Should Dbf interfaces be used? Needs thought.


asynOctet Support

This still needs more work. It attempts to reproduce the functionality of V3 asynDriver.

    interface AsynOctet {
        LinkWaitResult write(Callback callback,
          octet[] data, int32 numchars, Int32 nbytesTransfered);
        LinkWaitResult writeRaw(Callback callback,
          octet[] data, int32 numchars, Int32 nbytesTransfered);
        LinkWaitResult read(Callback callback,
          octet[] data, Int32 nbytesTransfered);
        LinkWaitResult readRaw(Callback callback,
          octet[] data, Int32 nbytesTransfered);
        void flush();
        void setInputEos(octet[] eos);
        void getInputEos(octet[] eos);
        void setOutputEos(octet[] eos);
        void getOutputEos(octet[] eos);
    }
    enum interruptReason {
        interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth
    }
    struct asynDigitalInterrupt {
        octet[] mask;
        int32 addr;
        Callback callback
    }
    interface AsynDigital {
         LinkWaitResult write(octet[] value, octet[] mask);
         LinkWaitResult read(octet[] value, octet[] mask);
         void setInterrupt(octet[] mask, interruptReason reason);
         void clearInterrupt(octet[] mask);
         void getInterrupt(octet[] mask, interruptReason reason);
         void registerInterruptUser(interruptCallbackUInt32Digital callback,
             octet[] mask);
         void cancelInterruptUser();
    }

Boolean Support

    interface LinkBoolean {
        LinkWaitResult getWait(Boolean data,Callback callback);
        LinkWaitResult putWait(boolean data,Callback callback);
    }
    interface LinkArrayBoolean {
        LinkWaitResult getWait(boolean[] data,Callback callback);
        LinkWaitResult putWait(boolean[] data,Callback callback);
    }


The data source must be a boolean or a string that contains a valid boolean value.

Integer Support

Support is available. for int16, int32, and int64. This section uses the Java generic syntax, e.g. <type>. In this section <type> must be int16, int32, or int64.

    interface Link<type> {
        LinkWaitResult getWait(<type> data,Callback callback);
        LinkWaitResult putWait(<type> data,Callback callback);
        void getBounds(<type> low, <type> high);
    }
    interface LinkArray<type> {
        LinkWaitResult getWait(<type>[] data,Callback callback);
        LinkWaitResult putWait(<type>[] data,Callback callback);
    }
    enum interruptReason {
        interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth
    } 
        
        

Float Support

Support is available. for float32 and float64. This section uses the Java generic syntax, e.g. <type>. In this section <type> must be float32 or float64.

    interface Link<type> {
        LinkWaitResult getWait(<type> data,Callback callback);
        LinkWaitResult putWait(<type> data,Callback callback);
    }
    interface LinkArray<type> {
        LinkWaitResult getWait(<type>[] data,Callback callback);
        LinkWaitResult putWait(<type>[] data,Callback callback);
    }

String Support

    interface LinkString {
        LinkWaitResult getWait(string data,Callback callback);
        LinkWaitResult putWait(string data,Callback callback);
    }
    interface LinkArrayString {
        LinkWaitResult getWait(string[] data,Callback callback);
        LinkWaitResult putWait(string[] data,Callback callback);
    }


The data source must be a string.


Example - VME ADC support

database definitions

The following struct is defined for configuration information.

    struct VMEADC {
        field(a16 int16)
        field(a32 int32)
        field(channel int16)
    }

The following link definition is defined:

    link(in,myAdcSupport,VMEADCinterface(LinkInt32))

This allows record instance definitions like:

    AiRecord aiExample = {
       ...
       input = myAdcSupport(LinkInt32){a16=0x0010;channel=1}
       ...
    }

link support implementation

The following is presented with Java syntax. It assumes that there is VME support of the form

public class VME {

   static public short getShort(long addr);
   ...

}

The link support would be something like:

    class AdcSupport implements Link LinkInt32 {
    AdcSupport(VMEADCData fromFactory)
    {
        data = fromFactory;
        connected = false;
        //  from the VMEADC initailze vmeaddr and channel
        // details left to your imagination
    }
    // Link methods
    void report(int16_t level)
    {
        printf("AdcSupport a16 %x channel %d\n",a16,channel);
    }
    void cancel() {} // nothing to do
    void destroy() {} //nothing to do
    void initialize()
    {
        // make sure we can access a16
    }
    void connect() {connected = true}
    void disconnect() {connected = false}
    
    // LinkInt32 methods
    LinkWaitResult getWait(Int data,Callback callback)
    {
        data = (Int)VME.getShort(vmeaddr);
        return linkDone;
    }
    LinkWaitResult putWait(Int data,Callback callback)
    {
        throw CantWriteAdc;
    }
    void getBounds(Int low, Int high) 
    {
        // assume 16 bit unipolor adc
        low = 0; high = 0xffff;
    }
    private:
        VMEADCData data;
        int vmeaddr;
        int channel;
        boolean connected;
    }