Top Banner
1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited
30

1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

Mar 30, 2015

Download

Documents

Grant Bailiff
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

12009: Device Support

EPICS

Device Support

Andy FosterObservatory Sciences Limited

Page 2: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

22009: Device Support

EPICSOutline

What is device support? The .dbd file entry The Device Support Entry Table

DSET – report DSET – init DSET – init_record DSET – read_write

Hardware device addresses Useful EPICS Facilities Interrupts

EPICS and Interrupts The callback system scanIoInit DSET – get_ioint_info scanIoRequest

Asynchronous I/O The optional driver layer

Page 3: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

32009: Device Support

EPICSWhat is Device Support?

Interface between record and hardware Provides an API for record support to

call Record type determines routines needed

Performs record I/O on request Determines whether a record is to be

synchronous or asynchronous Provides I/O Interrupt support

Determines whether I/O Interrupts are allowed

RECORD SUPPORT

DEVICE SUPPORT

DRIVER SUPPORT

DATABASE ACCESS

CHANNEL ACCESS

Page 4: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

42009: Device Support

EPICSWhy use it

Why not make record types for each hardware interface, with fields to allow full control over the facilities it provides? Users don't have to learn about a new

record type for each I/O board they want to use

Changing the I/O hardware is much easier than writing new records!

Record types provided are sufficient for most hardware interfacing tasks

Device support is simpler than record support

Device support isolates the hardware interface code from changes to the record API

Bug-fixes or enhancements to record support only need to happen in one place

Modularity (good software engineering practice)

Page 5: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

52009: Device Support

EPICSThe .dbd file entry

The IOC discovers what device supports are present from entries in the .dbd filedevice(recType,addrType,dset,"name")

addrType is one ofAB_IO BITBUS_IO BBGPIB_IOCAMAC_IO GPIB_IO INST_IORF_IO VME_IO VXI_IO

dset is the ‘C’ symbol name for the Device Support Entry Table (DSET) By convention the dset name indicates

the record type and hardware interface This is how record support and the

database code call device support routines

For exampledevice(bi,INST_IO, devBiXy2440,“XYCOM-2440")

device(bo,VME_IO, devBoXy240, “XYCOM-240")

Page 6: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

62009: Device Support

EPICSThe Device Support Entry

Table … is a ‘C’ struct containing function

pointers, the content of which can vary by record type

Each device support layer defines a named DSET with pointers to its own routines

All DSET structure declarations startstruct xxxdset { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_write;};

number gives the number of function pointers in the DSET, usually 5 for standard types

A NULL pointer is given when an optional routine is not implemented

Page 7: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

72009: Device Support

EPICSHow does a record find its

device support?Through .dbd ‘device’ statements:

Page 8: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

82009: Device Support

EPICSDSET: report

long report(int type);

Optional function. Called by dbior shell command

Normally omitted because the driver also has a report function which prints out information about the current state of the hardware.

The value of type defines how much information to print.

Page 9: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

92009: Device Support

EPICSDSET: init

long init(int pass);

Initializes the device support layer Used for one-time startup

operations, e.g. Starting background tasks Creating semaphores

Optional routine, not always needed Routine called twice by iocInit:

pass=0 — Before record initialization At this stage we don’t know what I/O is to

be used by the database, therefore, do not access hardware.

pass=1 — After all record initialization Can be used as a final startup step, all

devices addressed by database are known by this point

Page 10: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

102009: Device Support

EPICSDSET: init_record

long init_record( struct xxxRecord *prec );

Called from xxxRecord’s init_record routine once for each record. This occurs at iocInit.

Important routine, normally required. init_record should:

Parse the hardware address contained in the INP or OUT field

Check if addressed hardware is present Allocate any private storage required

Every record type has a void *dpvt field for device support to use as it wishes

Program device registers Set record-specific fields needed for

conversion to/from engineering units

Page 11: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

112009: Device Support

EPICSDSET: read_write

long read_write( struct xxxRecord *prec );

Important routine. Called from xxxRecord’s process

routine and implements the I/O operation (or calls the driver to do this) which occurs when the record is processed.

Precise action depends on the record type and whether synchronous or asynchronous processing.

Generally, synchronous input support Reads hardware value into prec->rval Returns 0

and synchronous output support Copies value in prec->rval to hardware Returns 0

Page 12: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

122009: Device Support

EPICSHardware Device Addresses

Device support .dbd entry wasdevice(recType,addrType,dset,"name")

addrType tells database software what type to use for the address link

device(bo,VME_IO,devBoXy240,"XYCOM-240”)

implies that: pbo->out.type = VME_IO If we look in base/include/link.h we see that struct vmeio { short card; short signal;

char *parm; }

We can obtain card, signal, parm as follows:pvmeio = (struct vmeio *)&(pbo-

>out.value)

The most flexible link type is INST_IO which provides a string the user can parse.

Page 13: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

132009: Device Support

EPICSA simple example

#include <recGbl.h>#include <devSup.h>#include <devLib.h>#include <biRecord.h>#include <epicsExport.h>

long init_record(biRecord *prec){

char *pbyte, dummy;

prec->pact = 1;if ((prec->inp.type != VME_IO) ||

(prec->inp.value.vmeio.signal < 0) ||(prec->inp.value.vmeio.signal > 7))

{ recGblRecordError(S_dev_badInpType, (void *)prec, "devBiFirst: Bad INP address"); return S_dev_badInpType;}

if( devRegisterAddress("devBiFirst", atVMEA16, prec->inp.value.vmeio.card, 0x1, &pbyte) != 0) {

recGblRecordError(S_dev_badCard, (void *)prec, "devBiFirst: Bad VME address");

return -1;}if( devReadProbe(1, pbyte, &dummy) < 0 )

{ recGblRecordError(S_dev_badCard, (void *)prec,

"devBiFirst: Nothing there!"); return -1;}prec->dpvt = pbyte;prec->pact = 0;return OK;

}

Page 14: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

142009: Device Support

EPICSA simple example

long read_bi(biRecord *prec){

char *pbyte = (char *)prec->dpvt;

prec->rval = *pbyte;return OK;

}

struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_write;} devBiFirst = { 5, NULL, NULL, init_record, NULL, read_bi};epicsExportAddress(dset, devBiFirst);

Page 15: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

152009: Device Support

EPICSA simple example – device

support .dbd fileThe .dbd file for the device support routines shown on the preceding pages might be:

device(bi, VME_IO, devBiFirst, “simpleInput”)

An application .db file using the device support routines shown might contain:

record(bi, "$(P):statusBit") { field(DESC, "Simple example binary input") field(DTYP, "simpleInput") field(INP, "#C$(C) S$(S)")}

Page 16: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

162009: Device Support

EPICSA simple example – application startup

script

An application startup script (st.cmd) using the device support routines shown on the preceding pages might contain:

dbLoadRecords("db/example.db", "P=test,C=0x1E0,S=0")

which would expand the .db file into

record(bi, "test:statusBit"){ field(DESC, "Simple example binary input") field(DTYP, "simpleInput") field(INP, "#C0x1E0 S0")}

Page 17: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

172009: Device Support

EPICSUseful facilities

ANSI C routines (EPICS headers fill in vendor holes) epicsStdio.h – printf, sscanf, epicsSnprintf epicsString.h – strcpy, memcpy, epicsStrDup epicsStdlib.h – getenv, abs,

epicsScanDouble OS-independent hardware access

(devLib.h) Bus address Local address conversion Interrupt control Bus probing

EPICS routines epicsEvent.h – process synchronization

semaphore epicsMutex.h – mutual-exclusion semaphore epicsThread.h – multithreading support recGbl.h – record error and alarm reporting

Page 18: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

182009: Device Support

EPICSInterrupts

vxWorks ISRs can be written in ‘C’ On VME two parameters are needed:

Interrupt Level — prioritized 1-7 Often set with I/O board DIP switches or jumpers Level 7 is non-maskable and can crash vxWorks

Interrupt Number 0-255 has to be unique within this CPU Interrupt numbers < 64 are reserved by

MC680x0 Use EPICS veclist on IOC to see vectors in useHowever, not supported by some PPC BSP’s!

OS initialization takes two callsConnect interrupt handler to vector:devConnectInterruptVME(

unsigned vectorNumber,

void (*pFunction)(void *),

void *parameter);

Enable interrupt from VME level:devEnableInterruptLevelVME (unsigned level);

Page 19: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

192009: Device Support

EPICSEPICS and Interrupts The

callback system How do you make an EPICS record process when an

interrupt occurs?

Use the SCAN setting of “I/O Intr” in the record

Since an ISR cannot call a record’s process routine directly, I/O interrupt scanning is implemented using the EPICS callback system. The callback system uses ring buffers to queue

callback requests made from interrupt level. One of 3 prioritized callback tasks executes the

registered callback function which in turn calls the record’s process routine.

See callback.h for a definition of the EPICS callback structure.

The choice of callback task is determined by the PRIO field in the record (LOW, MEDIUM, HIGH).

From the device/driver layer, we support I/O interrupt scanning by using the following routines: scanIoInit get_ioint_info scanIoRequest

Page 20: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

202009: Device Support

EPICSEPICS and Interrupts scanIoInit

scanIoInit must be called for each possible interrupt “source”. Device support can be written to allow any number of “sources”. Ultimately, the granularity of interrupts depends on the hardware. One “source” per card One “source” per bit

scanIoInit is typically called from the driver initialize routine to initialize a pointervoid scanIoInit(IOSCANPVT *ppvt)

int xy2440Initialise( void ){ struct config2440 *plist = ptrXy2440First;

#ifndef NO_EPICS { int i; for( i=0; i<MAXPORTS*MAXBITS; i++ ) {

scanIoInit( &plist->biScan[i] ); scanIoInit( &plist->mbbiScan[i] ); }

}#endif ...}

Page 21: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

212009: Device Support

EPICSEPICS and Interrupts

scanIoInit – contdstruct config2440

{

...

#ifndef NO_EPICS

IOSCANPVT biScan[MAXPORTS*MAXBITS];

IOSCANPVT mbbiScan[MAXPORTS*MAXBITS];

#endif

}

scanIoInit allocates an array of 3 “scan lists”, one for each callback priority (PRIO field). IOSCANPVT will hold the address of this array.

Page 22: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

222009: Device Support

EPICSEPICS and Interrupts

get_ioint_info The DSET must have a get_ioint_info routine.

This is called at iocInit for all records with “SCAN = I/O Intr”.

Device support copies the IOSCANPVT value for this record (determined by which bit) into *ppvt

typedef struct{ int port; int bit;} xipIo_t;

static long init_bi( struct biRecord *pbi ){ xipIo_t *pxip;

switch(pbi->inp.type) { case(INST_IO): pxip = (xipIo_t *)malloc(sizeof(xipIo_t));

status = xipIoParse(pbi->inp.value.instio.string, pxip); pbi->dpvt = pxip; ret = 0; break;

default: printf("Suitable error message\n");

ret = 1; break;

} return(ret);}

Page 23: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

232009: Device Support

EPICSEPICS and Interrupts

get_ioint_info – contd

static long bi_ioinfo( int cmd, struct biRecord *pbi, IOSCANPVT *ppvt ){ struct config2440 *plist = ptrXy2440First; xipIo_t *pxip;

pxip = (xipIo_t *)pbi->dpvt; /* "channel" is calculated from pxip->port, pxip->bit */ *ppvt = plist->biScan[channel]; return(0);}

Return 0 if OK, else non-zero when scan will be reset to Passive

Can usually ignore the cmd value: At iocInit this routine is called with cmd=0

for all records with SCAN=I/O Intr . If SCAN is later changed by a caPut or

dbPut, this routine will be called again with cmd=1.We do not have to worry about this case.

get_ioint_info adds this record to the appropriate scan list, depending on PRIO.

Page 24: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

242009: Device Support

EPICSEPICS and Interrupts

scanIoRequest

In the ISR, determine which channel on the card caused the interrupt and then call:

scanIoRequest(plist->biScan[channel]);

This causes all records in all 3 scan lists associated with “plist->biScan[channel]” to process!

Page 25: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

252009: Device Support

EPICSAsynchronous I/O

It is never permissible for Device Support to wait for slow I/O

If hardware read/write operations take “a long time,” (>100µsec) use asynchronous record processing If the device does not provide a suitable

completion interrupt, a background task can poll it periodically

An asynchronous read_write routine looks at precord->pact, and if FALSE, it: Starts the I/O operation Sets precord->pact = TRUE and returns

Page 26: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

262009: Device Support

EPICSAsynchronous I/Ocontinued

When the operation completes, Device Support must run the following code at task level, not in the ISR:struct rset *prset = (struct rset *)precord-

>rset;dbScanLock(precord);(*prset->process)(precord);dbScanUnlock(precord);

The record’s process routine will call the Device Support read_write routine again. Now pact is TRUE, the read_write routine will: Complete the I/O by setting the rval field

etc. Return 0

Page 27: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

272009: Device Support

EPICSAsynchronous example

#include <vxWorks.h>

#include <stdlib.h>

#include <stdio.h>

#include <wdLib.h>

#include <recSup.h>

#include <devSup.h>

#include <aiRecord.h>

static long init_record();

static long read_ai();

static void myCallback( CALLBACK * );

typedef struct {long number;DEVSUPFUN report;DEVSUPFUN init;DEVSUPFUN init_record;DEVSUPFUN get_ioint_info;DEVSUPFUN read_ai;DEVSUPFUN special_linconv;

} ANALOGDSET;

ANALOGDSET devAiTestAsyn = { 6, NULL, NULL, init_record, NULL, read_ai, NULL };

/* Device Private Structure */

struct devPrivate {CALLBACK callback; /* EPICS CALLBACK structure */WDOG_ID wdId;

};

Page 28: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

282009: Device Support

EPICSAsynchronous example - continued

static long init_record( struct aiRecord *pai ){ struct devPrivate *pdevp; pai->udf = FALSE; pdevp = (struct devPrivate *)(calloc(1,sizeof(struct

devPrivate))); pai->dpvt = (void *)pdevp;

callbackSetCallback( myCallback, &pdevp->callback ); callbackSetPriority( pai->prio, &pdevp->callback ); callbackSetUser( pai, &pdevp->callback ); pdevp->wdId = wdCreate(); return(0);}

static long read_ai(struct aiRecord *pai){ struct devPrivate *pdevp = (struct devPrivate *)(pai->dpvt); int waitTime;

if( pai->pact == FALSE ) { waitTime = (int)(pai->val * vxTicksPerSecond); printf("(%s) Starting Async. Processing...\n", pai->name);

wdStart( pdevp->wdId, waitTime, (FUNCPTR)callbackRequest, (int)&pdevp->callback );pai->pact = TRUE;return(0);

} else { printf("(%s) Completed Async. Processing...\n", pai->name);

return(2); /* No linear conversion in record */ }}

Page 29: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

292009: Device Support

EPICSAsynchronous example - continued

static void myCallback( CALLBACK *pCallback )

{

struct dbCommon *precord;

struct rset *prset;

callbackGetUser( precord, pCallback );

prset = (struct rset *)precord->rset;

dbScanLock(precord);

(*prset->process)(precord);

dbScanUnlock(precord);

}

Page 30: 1 2009: Device Support EPICS Device Support Andy Foster Observatory Sciences Limited.

302009: Device Support

EPICSThe optional Driver layer

Some reasons to include a driver layer: Share code between similar device

support layers for different record types Most digital I/O interfaces support record

types bi, bo, mbbi, mbbo, mbbiDirect and mbboDirect

Initialize a software module before individual device layers using it are initialized

The order in which device support initialization is called is not guaranteed

Provide a common interface to an I/O bus such as GPIB, Bitbus, Allen-Bradley etc.

I/O devices placed on this bus need their own device support, but share the interface hardware

Provide a wrapper around commercial device drivers or other software libraries