Difference between revisions of "V4 Link Support Tutorial"
MartyKraimer (talk | contribs) m |
MartyKraimer (talk | contribs) |
||
Line 1: | Line 1: | ||
EPICS: IOC Link Support Tutorial Oct | EPICS: IOC Link Support Tutorial Oct 24 2005 | ||
---- | ---- | ||
Line 45: | Line 45: | ||
A link itself has the syntax: | A link itself has the syntax: | ||
link(linkDirection,choiceName,dataStructName,interface(interfaceName,...)) | link(linkDirection,choiceName,dataStructName,interface(interfaceName,...)) | ||
A record instance link definition has the syntax: | |||
field = { blockValue, choice(interfaceName), {structAssignmentList}} | |||
or | |||
field = { block = blockValue; choiceName = choice(interfaceName); | |||
dataStructName {structAssignmentList{} | |||
} | |||
where | where | ||
Line 60: | Line 66: | ||
; <tt>dataStructName</tt> | ; <tt>dataStructName</tt> | ||
: The name of a <tt>struct</tt> containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools | : The name of a <tt>struct</tt> containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools prompt the user to assign values to the structure. | ||
; <tt>blockValue</tt> | |||
: Must be <tt>true</tt> or <tt>false</tt> | |||
; <tt>choice</tt> | |||
: Selects a link with <tt>choiceName</tt> = <tt>choice</tt> | |||
A record instance link definition selects a link as follows: | |||
the | * The linkDirections must be compatible | ||
The interfaceName must be | ** Except for inout the record link and link directions must be the same | ||
** If record link specifies inout the link can specify either in or out | |||
* The interfaceName specified by the record instance must be in the record link interface list and in the link interface list. | |||
* The dataStructName specified in the record instance must match the dataStructName in the link definition. | |||
Assume the following definitions: | |||
record(AiRecord) { | |||
... | |||
field(in,link(in,interface(LinkInt64,LinkFloat64))) | |||
... | |||
} | |||
struct(MonitorLinkData) { | struct(MonitorLinkData) { | ||
field(pvname,string) | field(pvname,string) | ||
field(process,boolean) // process this record when monitor occurs | field(process,boolean) // process this record when monitor occurs | ||
field(inheritSeverity,boolean) | field(inheritSeverity,boolean) | ||
} | } | ||
struct(InputLinkData) { | struct(InputLinkData) { | ||
field(pvname,string) | field(pvname,string) | ||
field(process,boolean) | field(process,boolean) | ||
field(wait,boolean) | field(wait,boolean) | ||
field(timeout,float64) | field(timeout,float64) | ||
field(inheritSeverity,boolean) | field(inheritSeverity,boolean) | ||
} | } | ||
... | ... | ||
link(in,monitorLink,MonitorLinkData interface( | link(in,monitorLink,MonitorLinkData interface( | ||
LinkBoolean, | LinkBoolean, | ||
Line 118: | Line 103: | ||
LinkFloat32,LinkFloat64, | LinkFloat32,LinkFloat64, | ||
LinkString | LinkString | ||
)) | )) | ||
link(in,inputLink,InputLinkData interface( | link(in,inputLink,InputLinkData interface( | ||
Line 131: | Line 110: | ||
LinkString | LinkString | ||
)) | )) | ||
... | |||
struct VME{ | |||
field(a16,int16) | |||
field(a32,int32) | |||
field(channel,int16) | |||
} | |||
link(in, | ... | ||
link(in,someVmeADC,VME, interface(LinkInt32)) | |||
The first example instance definition selects a monitor link. It selects interface LinkInt32, which means the support will provide a "raw" value that the | |||
record support will convert to engineering units. | |||
AiRecord aiMonitorExample = { | |||
... | |||
in = {choiceName = monitorLink(LinkInt32) | |||
MonitorLinkData { | |||
pvname = "someRecord"; | |||
process = true; | |||
inheritSeverity = false | |||
} | |||
} | |||
The next example selects a channel access input link. It selects interface | |||
LinkFloat64, which means the support will provide a value in engineering units. | |||
It asks that the linked record be processed and that the link not complete | |||
until the linked record completes processing. | |||
AiRecord aiInputExample = { | |||
... | |||
in = {choiceName = inputLink(LinkFloat64) | |||
MonitorLinkData { | |||
pvname = "someRecord"; | |||
process = true; | |||
wait = true; | |||
timeout = 1.0; | |||
inheritSeverity = false | |||
} | |||
} | |||
The last example attaches the link to support for a VME Analog to Digital device. | |||
AiRecord aiMonitorExample = { | |||
... | |||
in = {choiceName = someVmeADC(LinkInt32) | |||
VME {a16 = 0xc000; channel = 1} | |||
} | |||
== 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. | |||
This support registers each choiceName in the link definitions. | |||
The complete set of data structure and link definitions are defined | |||
in "V4 DB RecordCommon". | |||
Link support is provided for | |||
* monitor | |||
* input | |||
* output | |||
* process | |||
For monitor, input, and output the following data types are supported: | |||
* primitive types | |||
* string | |||
* arrays of primitive types and strings | |||
== asynDriver link support == | == asynDriver link support == | ||
Line 201: | Line 218: | ||
Other link support can also be supplied. | Other link support can also be supplied. | ||
Whenever possible support should implement the standard interfaces | |||
supplied by EPICS base | supplied by EPICS base, since these are the interfaces that the record types | ||
supplied with base know how to use. | supplied with base know how to use. | ||
Line 208: | Line 225: | ||
the Channel/Database access support supplied with base. The support | the Channel/Database access support supplied with base. The support | ||
can, of course, define data structures for it's own use. | can, of course, define data structures for it's own use. | ||
Implementing these interfaces means that | Implementing these interfaces means that the support will work for | ||
the same set of record links as the Channel/Database access support. | the same set of record links as the Channel/Database access support. | ||
Line 214: | Line 231: | ||
implemented by the Channel/Database access support. | implemented by the Channel/Database access support. | ||
Message based support may also have to implement the AsynOctet interface | Message based support may also have to implement the AsynOctet interface | ||
but this interface is only used by a few record | but this interface is only used by a few record types. | ||
Line 259: | Line 276: | ||
and initialize and connect after the link is modified. | and initialize and connect after the link is modified. | ||
Note that neither Link or MonitorLink is listed in the <tt>link</tt> database | |||
definition. | definition since they are generic. | ||
== Definitions that apply to Process,Monitor,Input,and Output support == | == Definitions that apply to Process,Monitor,Input,and Output support == | ||
Line 270: | Line 287: | ||
linkDone, // field was modified. No wait is necessary | linkDone, // field was modified. No wait is necessary | ||
linkWait, // waiting. can do additional procsssing | linkWait, // waiting. can do additional procsssing | ||
} | } | ||
Line 278: | Line 294: | ||
} | } | ||
== Process Link Support == | == Process Link Support == | ||
interface LinkProcess | interface LinkProcess { | ||
LinkWaitResult process(Callback callback); | LinkWaitResult process(Callback callback); | ||
} | } | ||
== Octet Support == | == Octet Support == | ||
interface LinkOctet { | |||
LinkWaitResult get(Callback callback, Octet data); | |||
LinkWaitResult put(Callback callback, Octet data); | |||
} | |||
interface LinkArrayOctet { | interface LinkArrayOctet { | ||
LinkWaitResult | LinkWaitResult get(Callback callback, octet[] data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback, octet[] data); | ||
} | } | ||
Line 328: | Line 346: | ||
interface AsynDigital { | interface AsynDigital { | ||
LinkWaitResult write(octet[] value, octet[] mask); | LinkWaitResult write(Callback callback,octet[] value, octet[] mask); | ||
LinkWaitResult read(octet[] value, octet[] mask); | LinkWaitResult read(Callback callback,octet[] value, octet[] mask); | ||
void setInterrupt(octet[] mask, interruptReason reason); | void setInterrupt(octet[] mask, interruptReason reason); | ||
void clearInterrupt(octet[] mask); | void clearInterrupt(octet[] mask); | ||
Line 340: | Line 358: | ||
== Boolean Support == | == Boolean Support == | ||
interface LinkBoolean { | interface LinkBoolean { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,Boolean data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,boolean data); | ||
} | } | ||
interface LinkArrayBoolean { | interface LinkArrayBoolean { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,boolean[] data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,boolean[] data); | ||
} | } | ||
Line 359: | Line 377: | ||
interface Link<type> { | interface Link<type> { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,<type> data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,<type> data); | ||
void getBounds(<type> low, <type> high); | void getBounds(<type> low, <type> high); | ||
} | } | ||
interface LinkArray<type> { | interface LinkArray<type> { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,<type>[] data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,<type>[] data); | ||
} | } | ||
Line 380: | Line 398: | ||
interface Link<type> { | interface Link<type> { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,<type> data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,<type> data); | ||
} | } | ||
interface LinkArray<type> { | interface LinkArray<type> { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,<type>[] data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,<type>[] data); | ||
} | } | ||
== String Support == | == String Support == | ||
interface LinkString { | interface LinkString { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,string data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,string data); | ||
} | } | ||
interface LinkArrayString { | interface LinkArrayString { | ||
LinkWaitResult | LinkWaitResult get(Callback callback,string[] data); | ||
LinkWaitResult | LinkWaitResult put(Callback callback,string[] data); | ||
} | } | ||
Line 405: | Line 423: | ||
= Example - VME ADC support = | = Example - VME ADC support = | ||
</center> | </center> | ||
Assume the VME and link definitions given in the examples at the beginning | |||
of this document. | |||
The following is presented with Java syntax. | The following is presented with Java syntax. | ||
It assumes that there is VME support of the form | It assumes that there is VME support of the form | ||
public class | public class vme { | ||
static public short getShort(long addr); | static public short getShort(long addr); | ||
... | ... | ||
Line 434: | Line 437: | ||
class AdcSupport implements Link LinkInt32 { | class AdcSupport implements Link LinkInt32 { | ||
AdcSupport( | AdcSupport(VME fromFactory) | ||
{ | { | ||
addr = fromFactory; | |||
connected = false; | connected = false; | ||
// from the | // from the VME initailze vmeaddr and channel | ||
// details left to your imagination | // details left to your imagination | ||
} | } | ||
Line 457: | Line 460: | ||
// LinkInt32 methods | // LinkInt32 methods | ||
LinkWaitResult | LinkWaitResult get(Callback callback, Int data) | ||
{ | { | ||
data = (Int)VME.getShort(vmeaddr); | data = (Int)VME.getShort(vmeaddr); | ||
return linkDone; | return linkDone; | ||
} | } | ||
LinkWaitResult | LinkWaitResult put(Callback callback, Int data) | ||
{ | { | ||
throw CantWriteAdc; | throw CantWriteAdc; | ||
Line 472: | Line 475: | ||
} | } | ||
private: | private: | ||
VME addr; | |||
int vmeaddr; | int vmeaddr; | ||
int channel; | int channel; | ||
boolean connected; | boolean connected; | ||
} | } |
Revision as of 15:17, 24 October 2005
EPICS: IOC Link Support Tutorial Oct 24 2005
Overview
The V4 link support is a replacement for V3
- DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK
- device DBD definition and device support
- 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,...))
A record instance link definition has the syntax:
field = { blockValue, choice(interfaceName), {structAssignmentList}} or field = { block = blockValue; choiceName = choice(interfaceName); dataStructName {structAssignmentList{} }
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 prompt the user to assign values to the structure.
- blockValue
- Must be true or false
- choice
- Selects a link with choiceName = choice
A record instance link definition selects a link as follows:
- The linkDirections must be compatible
- Except for inout the record link and link directions must be the same
- If record link specifies inout the link can specify either in or out
- The interfaceName specified by the record instance must be in the record link interface list and in the link interface list.
- The dataStructName specified in the record instance must match the dataStructName in the link definition.
Assume the following definitions:
record(AiRecord) { ... field(in,link(in,interface(LinkInt64,LinkFloat64))) ... } struct(MonitorLinkData) { field(pvname,string) field(process,boolean) // process this record when monitor occurs field(inheritSeverity,boolean) } struct(InputLinkData) { field(pvname,string) field(process,boolean) field(wait,boolean) field(timeout,float64) field(inheritSeverity,boolean) } ... link(in,monitorLink,MonitorLinkData interface( LinkBoolean, LinkInt16,LinkInt32,LinkInt64, LinkFloat32,LinkFloat64, LinkString )) link(in,inputLink,InputLinkData interface( LinkBoolean, LinkInt16,LinkInt32,LinkInt64, LinkFloat32,LinkFloat64, LinkString )) ... struct VME{ field(a16,int16) field(a32,int32) field(channel,int16) } ... link(in,someVmeADC,VME, interface(LinkInt32))
The first example instance definition selects a monitor link. It selects interface LinkInt32, which means the support will provide a "raw" value that the record support will convert to engineering units.
AiRecord aiMonitorExample = { ... in = {choiceName = monitorLink(LinkInt32) MonitorLinkData { pvname = "someRecord"; process = true; inheritSeverity = false } }
The next example selects a channel access input link. It selects interface LinkFloat64, which means the support will provide a value in engineering units. It asks that the linked record be processed and that the link not complete until the linked record completes processing.
AiRecord aiInputExample = { ... in = {choiceName = inputLink(LinkFloat64) MonitorLinkData { pvname = "someRecord"; process = true; wait = true; timeout = 1.0; inheritSeverity = false } }
The last example attaches the link to support for a VME Analog to Digital device.
AiRecord aiMonitorExample = { ... in = {choiceName = someVmeADC(LinkInt32) VME {a16 = 0xc000; channel = 1} }
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. This support registers each choiceName in the link definitions. The complete set of data structure and link definitions are defined in "V4 DB RecordCommon".
Link support is provided for
- monitor
- input
- output
- process
For monitor, input, and output the following data types are supported:
- primitive types
- string
- arrays of primitive types and strings
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. Whenever possible support should implement the standard interfaces supplied by EPICS base, since 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 the 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 types.
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.
Note that neither Link or MonitorLink is listed in the link database definition since they are generic.
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 }
interface Callback { void done(); void failure(); }
Process Link Support
interface LinkProcess { LinkWaitResult process(Callback callback); }
Octet Support
interface LinkOctet { LinkWaitResult get(Callback callback, Octet data); LinkWaitResult put(Callback callback, Octet data); } interface LinkArrayOctet { LinkWaitResult get(Callback callback, octet[] data); LinkWaitResult put(Callback callback, octet[] data); }
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(Callback callback,octet[] value, octet[] mask); LinkWaitResult read(Callback callback,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 get(Callback callback,Boolean data); LinkWaitResult put(Callback callback,boolean data); } interface LinkArrayBoolean { LinkWaitResult get(Callback callback,boolean[] data); LinkWaitResult put(Callback callback,boolean[] data); }
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 get(Callback callback,<type> data); LinkWaitResult put(Callback callback,<type> data); void getBounds(<type> low, <type> high); } interface LinkArray<type> { LinkWaitResult get(Callback callback,<type>[] data); LinkWaitResult put(Callback callback,<type>[] data); }
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 get(Callback callback,<type> data); LinkWaitResult put(Callback callback,<type> data); } interface LinkArray<type> { LinkWaitResult get(Callback callback,<type>[] data); LinkWaitResult put(Callback callback,<type>[] data); }
String Support
interface LinkString { LinkWaitResult get(Callback callback,string data); LinkWaitResult put(Callback callback,string data); } interface LinkArrayString { LinkWaitResult get(Callback callback,string[] data); LinkWaitResult put(Callback callback,string[] data); }
The data source must be a string.
Example - VME ADC support
Assume the VME and link definitions given in the examples at the beginning of this document.
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(VME fromFactory) { addr = fromFactory; connected = false; // from the VME 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 get(Callback callback, Int data) { data = (Int)VME.getShort(vmeaddr); return linkDone; } LinkWaitResult put(Callback callback, Int data) { throw CantWriteAdc; } void getBounds(Int low, Int high) { // assume 16 bit unipolor adc low = 0; high = 0xffff; } private: VME addr; int vmeaddr; int channel; boolean connected; }