Title: Record/Device/Driver Support
1Record/Device/Driver Support
- Beijing EPICS Seminar
- Monday,8/23 2001
- J.Odagiri
2Before Getting Started
- We will NOT work on any devices
- Lots of things to know even without hardware
- We will work on some example codes instead
- Who can remember all details at once?
- Let me get to focus on essential points
- Please consult EPICS Input / Out put Controller
(IOC) Application Developers Guide for more
detail
3Outline
- Overview of Record, Device and Driver Support
- Implementation of Record / Device Support
- Some hints for Asynchronous Driver Support
4Overview of Record, Device and Driver Support
Run-time Database
Record Support
Device Support
Driver Support
Hardware ( VME )
5Driver Support Is Optional
Run-time Database
Record Support
Device Support
Hardware ( VME )
6Pure Software Record
Run-time Database
Record Support
Calculation record has no hardware to face
7Record Support
Run-time Database
Record Support
Device Support
Driver Support
Hardware ( VME )
8Comments on Record Support
- Record Support consists of a set of routines
- They can be called from several different task
contexts - CA client task
- Scan task
- Callback task
- Sequencer task
- VxWorks shell task
9Comments on Record Support ( Cont. )
- If a type of record does I/O with aid of device
support, the record support must be compliant
with both synchronous and asynchronous processing
10Device Support
Run-time Database
Record Support
Device Support
Driver Support
Hardware ( VME )
11Comments on Device Support
- Can be divided into two basic classes
- Synchronous for register based devices without
delays for I/O ( CAMAC ) - Asynchronous for devices which can be accessed
via I/O requests that may take large amount of
time to complete ( GPIB )
12How Synchronous I/O Works
Run-time Database
Record Support
Device Support
Driver Support
Hardware ( VME )
13What If Synchronous I/O was used for Slow Devices?
Run-time Database
Record Support
Device Support
Driver Support
100 ms of Sleep
14Slow Devices require Asynchronous I/O
- Scan tasks, for instance, should NOT wait for a
transaction to complete if it takes long time - A scan task may have lots of record instances to
process - After the scan task initiate the I/O, it must go
ahead to process the next record - Another task should take care of the callback
when the I/O completes
15How Asynchronous I/O Works
Queue
Scan task
Scan task
I/O task
CA client Scan Seq Shell
Request
Response
16How Asynchronous I/O Works ( Continued )
Run-time Database
Record Support
Scan task
Device Support
I/O task
Driver Support
Sleep
17Driver Support
Run-time Database
Record Support
Device Support
Driver Support
Hardware ( VME )
18Comments on Driver Support
- Why do we need to have two layers, Device and
Driver? - The device support layer was created later by a
historical reason - But still, better to have two layers when
- It is complicated
- There is an existing driver outside EPICS
19Driver Support for GPIB
Device Support
Interface Board
Driver Support
Device
IOC
Request
Response
20Outline
- Overview of Record, Device and Driver Support
- Implementation of Record / Device Support
- Some hints for asynchronous Driver Support
21Implementation of Record / Device Support
- rompinRecord
- A new record type created for this lecture
- ( not standard )
- Derived from standard longinRecord by removing
some miscellaneous fields and routines - Many debug prints to show you how it works
22The Sources Are
- Record Support
- rompinRecord.dbd
- rompinRecord.c
- Device Support
- devRiSoft.c
- devRiAsync.c
- Driver Support
- drvAsync.c
23rompinRecord.dbd
- recordtype(rompin)
- include dbCommon.dbd
- field(VAL,DBF_LONG)
- prompt(Current value)
- asl(ASL0)
- pp(TRUE)
-
- field(INP,DBF_INLINK)
- prompt(Input Specification)
- promptgroup(GUI_INPUTs)
- interest(1)
-
24rompinRecord.dbd
- recordtype(rompin)
- include dbCommon.dbd
- field(VAL,DBF_LONG)
- prompt(Current value)
- asl(ASL0)
- pp(TRUE)
-
- field(INP,DBF_INLINK)
- prompt(Input Specification)
- promptgroup(GUI_INPUTs)
- interest(1)
-
25dbCommon.dbd
- field(NAME,DBF_STRING)
- prompt(Record Name)
- special(SPC_NOMOD)
- size(29)
-
- ...
26rompinRecord.dbd
- recordtype(rompin)
- include dbCommon.dbd
- field(VAL,DBF_LONG)
- prompt(Current value)
- asl(ASL0)
- pp(TRUE)
-
- field(INP,DBF_INLINK)
- prompt(Input Specification)
- promptgroup(GUI_INPUTs)
- interest(1)
-
27rompinRecord.c
- Defines and Implements what the rompinRecord is
- Consists of
- Record Support Entry Table ( RSET )
- Device Support Entry Table ( DSET )
- Implementations of record support routines
defined in the RSET - And their forward declarations
- Internal support routines
28 devRiSoft.c
- Software Device Support to get a value from
another record through - Channel Access link
- Database link
- Constant link
- I/O with a Device requires, say, devRiDevice.c
for each type of device
29Software Device Support
Run-time Database
Record Support
Device Support
A Field of Another Record
30Record Support Entry Table ( RSET )
Run-time Database
RSET
Record Support
Device Support
Driver Support
Hardware ( VME )
31RSET in rompinRecord.c
- struct rset rompinRSET
- long RSETNUMBER,
- RECSUPFUN report,
- RECSUPFUN initialize,
- RECSUPFUN init_record,
- RECSUPFUN process,
- RECSUPFUN special,
- RECSUPFUN get_value,
- RECSUPFUN cvt_dbaddr,
- ...
- RECSUPFUN get_alarm_double
32Declarationsin rompinRecord.c
- / Create RSET Record Support Entry Table /
- define report NULL
- define initialize NULL
- static long init_record()
- static long process()
- define special NULL
- define get_value NULL
- define cvt_addr NULL
- . . .
- define get_alarm_double NULL
33Device Support Entry Table ( DSET )
Run-time Database
Record Support
DSET
Device Support
Driver Support
Hardware ( VME )
34DSET in rompinRecord.c
- struct rompindset
- long number
- DEVSUPFUN dev_report
- DEVSUPFUN init
- DEVSUPFUN init_record
- DEVSUPFUN get_ioint_info
- DEVSUPFUN read_rompin
-
35DSET in devRiSoft.c
- struct
- long number
- DEVSUPFUN report
- ...
- DEVSUPFUN read_rompin
- devRiSoft
- 5,
- NULL,
- ...
- read_rompin
-
36BeijingInclude.dbd
- Include base.dbd
- Include rompindRecord.dbd
- device(rompin,CONSTANT,devRiSoft,Soft Channel)
- device(rompin,CONSTANT,devRiAsync,Soft Async)
- driver(drvAsync)
37rompin.db
- record( rompin,(user)riExample )
- field( DESC, romp input )
- field( ASG, )
- field( SCAN, Passive )
- ...
- field( DTYP,Soft Channel )
- ...
- field( INP, (user)calcExample.VAL )
38BeijingInclude.dbd
- Include base.dbd
- Include rompindRecord.dbd
- device(rompin,CONSTANT,devRiSoft,Soft Channel)
- device(rompin,CONSTANT,devRiAsync,Soft Async)
- driver(drvAsync)
39rompin.db
- record( rompin,(user)riExample )
- field( DESC, romp input )
- field( ASG, )
- field( SCAN, Passive )
- ...
- field( DTYP,Soft Channel )
- ...
- field( INP, (user)calcExample.VAL )
40Link Type
- CONSTANT PV_LINK DB_LINK CA_LINK
- AB_IO BITBUS_IO BBGPIB_IO CAMAC_IO
- GPIB_IO INST_IO RF_IO VME_IO
- VXI_IO
- device( ai, INST_IO, devAiAscii,Ascii SIO)
- device( bo, GPIB_IO, devBoTek2430,Tek2430)
- base/include/lilnk.h
41Getting Back to Record Support
- / Create RSET Record Support Entry Table /
- define report NULL
- define initialize NULL
- static long init_record()
- static long process()
- define special NULL
- define get_value NULL
- define cvt_addr NULL
- . . .
- define get_alarm_double NULL
42init_record() Called Twice on iocInit
- static long init_record( prompin, pass )
-
-
- if ( pass 0 ) return(0)
-
- if(!(pdset (struct rompindset
)(prompin-gtdset))) -
- if( (pdset-gtnumber lt 5)
- (pdset-gtread_rompin NULL) )
-
-
43init_record() Calls init of Dev. Sup.
- static long init_record( prompin, pass )
-
-
- if ( pdset-gtinit_record )
- if ((status(pdset-gtinit_record)(prompin)))
return(status) -
- return(0)
-
44Most Important Routine
- / Create RSET Record Support Entry Table /
- define report NULL
- define initialize NULL
- static long init_record()
- static long process()
- define special NULL
- define get_value NULL
- define cvt_addr NULL
- . . .
- define get_alarm_double NULL
45process() Most Important Routine
- Defines and implements the details of record
processing - Called by dbProcess(), the database access
routine, to process the record - Calls a device support I/O routine, in many cases
46process() Is Responsible for
- Set record active while it is being processed
- Perform I/O ( with aid of device support )
- Check for record specific alarm conditions
- Raise database monitors
- Request processing of forward links
47How process() Performs I/O
- static long process( prompin )
- rompinRecord prompin
-
- ...
- statusreadValue(prompin)
- ...
-
48readValue() in rompinRecord.c
- static long readValue(prompin)
- rompinRecord prompin
-
- ...
- status
- (pdset-gtread_rompin)(prompin)
- ...
-
49read_rompin() in devRiSoft.c
- static long read_rompin(prompin)
- struct rompinRecord prompin
-
- status
- dbGetLink(prompin-gtinp, )
- ...
50Software Device Support
Run-time Database
Record Support
Device Support
A Field of Another Record
51process() Is Responsible for
- Set record active while it is being processed
- Perform I/O (with aid of device support)
- Check for record specific alarm conditions
- Raise database monitors
- Request processing of forward links
52How process() Raises Monitors
- static long process(prompin)
- rompinRecord prompin
-
- ...
- monitor( prompin )
- ...
-
53monitor() in rompinRecord.c
- static void monitor( prompin )
- rompinRecord prompin
-
- unsigned short monitor_mask
- ...
- if ( monitor_mask )
- db_post_events ( prompin, )
-
54db_post_events() in iocCore
- Create a message and put it on a queue to inform
the CA clients of the change - Have the CA event task send the message to the CA
clients - Arguments
- The address of the record/field
- Monitor mask
- DBE_ALARM - change of alarm state
- DBE_LOG - change of archive state
- DBE_VAL - change of value state
55process() Is Responsiblefor
- Set record active while it is being processed
- Perform I/O ( with aid of device support )
- Check for record specific alarm conditions
- Raise database monitors
- Request processing of forward links
56How process() processes Flink
- static long process (void precprd)
-
- rompinRecord prompin
- ...
- recGblFwdLink ( prompin )
- ...
-
57Global Record Support Routines ( src/db/recGbl.c )
- recGblSetSevr()
- recGblGetGraphicDouble()
- recGblGetAlarmDouble()
- recGblGetControlDouble()
- recGblInitConstantLink()
- recGblResetAlarms()
- recGblFwdLink()
- recGblGetTimeStamp()
58PACT 1 Indicatesthe record is active
- static long process( prompin )
-
- ...
- unsigned char pactprompin-gtpact
- ...
- status readValue( prompin )
- if ( !pact prompin-gtpact ) retrun( 0 )
59More on PACT
- Before dbProcess() calls process(), it checks if
PACT is FALSE ( and the record is not disabled ) - Asynchronous completion routines in Device
Support call process() without checking PACT - read_rompin_asynchronous_completion()
60Asynchronous I/Oand PACT
PACT 1
Record Support
Device Support
Driver Support
Sleep
61Outline
- Overview of Record, Device and Driver Support
- Implementation of Record / Device Support
- Some hints for asynchronous Driver Support
62Some hints for Async. Driver Support
- Commonly used facilities to implement
asynchronous Driver Support - Linked List
- Creating I/O tasks
- Semaphores
-
63devRiAsync.c/drvAsync.c
- Do the same as devRiSoft.c does
- Emulates an asynchronous I/O with a slow message
based device, like GPIB - The delay time has been set to 3 seconds to make
it clear
64Driver Support Entry Table
- struct
- long number
- DRVSUPFUN report
- DRVSUPFUN init
- drvAsync
- 2L,
- drvAsyncReport,
- drvAsyncInit
65BeijingInclude.dbd
- Include base.dbd
- Include rompindRecord.dbd
- device(rompin,CONSTANT,devRiSoft,Soft Channel)
- device(rompin,CONSTANT,devRiAsync,Soft Async)
- driver(drvAsync)
66Request Queue
Linked List
Scan task
I/O task
Linked List
67Linked Lists
NULL
NULL
3
1
2
3
68Linked List Library
- lstInit() ellInit()
- lstAdd() ellAdd()
- lstGet() ellGet()
- lstCount() ellCount()
- lstFirst() ellFirst()
- lstNext() ellNext()
- lstInsert() ellInsert()
-
69lstInit()/ellInit()
NULL
0
70lstAdd()/ellAdd()
NULL
3
NULL
2
1
2
71lstGet()/ellGet()
NULL
NULL
2
2
3
1
72Synchronization between Tasks
Scan task
I/O task
semGive()
semTake()
Notification of Event
73Binary Semaphores
- SemBCreate()
- Crate and initialize a binary semaphore
- semTake()
- If empty, the caller goes to sleep
- semGive()
- If another task gives the semaphore, the sleeping
task wakes up
74Mutual Exclusion between Tasks
Scan task
I/O task
75lstGet() on the way
NULL
NULL
3
1
2
3
76Mutex for Linked List
- semTake( mutexSem, )
- lstGet( queue )
- semGive( mutexSem )
77Mutex Semaphores
- semMCreate()
- Crate and initialize a mutex semaphore
- semTake()
- If empty, the caller goes to sleep
- semGive()
- If another task gives the semaphore, the sleeping
task wakes up
78sysBusToLocalAdrs()A VxWorks( BSP ) function
- - convert a bus address to a local address
- STATUS sysBusToLocalAdrs(
- int adrsSpace
- char busAdrs
- char pLocalAdrs
- )
79vxMemProbe()A VxWorks( BSP ) function
- - probe an address for a bus error
- STATUS vxMemProbe(
- char Adrs
- int mode
- int length
- char pVal
- )
80intConnect()A VxWorks( BSP ) function
- - connect a C routine to a hardware interrupt
- STATUS intConnect(
- VOIDFUNCPTR vector
- VOIDFUNCPTR routine
- int paramerter
- )
81sysIntEnable()A VxWorks( BSP ) function
- - enable a bus interrupt level
- STATIS sysIntEnable(
- int intLevel
- )
82Watchdog Timers
- wdCreate()
- Crate a watchdog timer
- wdStart()
- Start a watchdog timer
- wdCancel()
- Cancel a currently counting watchdog
- wdDelete()
- Delete a watchdog timer
83Practices
- Observe the difference between synchronous and
asynchronous record processing ( Check how PACT
works ) - In process() of rompinRecord.c, comment out
monitor() and see what happens - Modify rompinRecord.c so that MEDM can make nice
graphic display - Modify rompinRecord.c so that it can raise alarms
84Other Field Types
- DBF_STRING
- DBF_CHAR DBF_UCHAR
- DBF_SHORT DBF_USHORT
- DBF_LONG DBF_ULONG
- DBF_FLOAT DBF_DOUBLE
- DBF_ENUM
- DBF_MENU
- DBF_DEVICE
- DBF_INLINK DBF_OUTLINK
- DBF_FWDLINK
- DBF_NOACCESS
85dbCommon.dbd
- field(NAME,DBF_STRING)
- prompt(Record Name)
- special(SPC_NOMOD)
- size(29)
-
86Some of Special Values
- SPC_NOMOD
- The field can not be modified at run-time except
by the record/device support modules - SPC_DBADDR
- cvt_dbaddr() should be called when code outside
record/device support want to access the field - SPC_MOD
- special() should be called when the field is
modified by database access
87Relevant Files
- BeijingApp/src/Makfile.Vx
- BeijingInclude.dbd
- rompinRecord.dbd
- rompinRecord.c
- devRiSoft.c
- devRiAsync.c
- drvAsync.c
- /Db/rompin.db
- /display/rompin.adl
- iocBoot/st.cmd2
88Things to do First
- Uncomment out the relevant lines in
src/Makefile.Vx - RECTYPES ../rompinRecord.c
- SRC.c ../rompinRecord.c
- SRC.c ../devRiSoft.c
- SRC.c ../devRiAsync.c
- SRC.c ../drvAsync.c
89Things to do Next
- Uncomment out the relevant lines in
src/BeijingInclude.dbd - device(rompin,CONSTANT,devRiSoft,Soft Channel)
- device(rompin,CONSTANT,devRiSoftAsn,Soft
Async) - driver(drvAsync)
90Making Modules
- Just gmake at src will do it for you
- rompinRecord.h will be created automatically
based on the definitions in rompinRecord.dbd - After gmake, please check what youve got ( the
instructors will help you do it )
91Testing with IOC
- Modify the startup script, st.cmd2, so as to load
the test database ( rompin.db ) - Start MEDM and open the display file for the test
( rompin.adl ) - Boot the IOC with the modified startup script (
st.cmd2 )