softGlue Installation and Deployment
Table of contents
- Overview
- How to get the software
- Building softGlue
- Deploying softGlue to an IOC
- Configuring hardware
- Configuring softGlue
- User callable functions
Overview
softGlue is a synApps module, so if you’ve used any other synApps module, you probably already know how to install and deploy it. The important thing is that softGlue is pure support: you are not expected to run an IOC directly with it, but instead to draw from the module into your own IOC application.
Unlike most other synApps modules, softGlue publishes the text files needed to boot an IOC in its
dbdirectory (as an EPICS module really should), rather than in thesoftGlueApp/Dbdirectory.
How to get the software
softGlue is available as part of synApps 5.5 and higher, or from the softGlue GitHub repository.
Building softGlue
-
Edit
softGlue/configure/RELEASEto specify the paths toEPICS_BASE,ASYN, andIPAC. -
If you’re using a version of ipac older than 2.11, edit
softGlueApp/src/drvIP_EP201.cto change the definition of the macroDO_IPMODULE_CHECK:#define DO_IPMODULE_CHECK 0 -
Run
makein the top-level directory, using the samemakeexecutable used to build EPICS base.
The build will issue a warning that it can’t expand all macros in substitution files. This is not an error; unexpanded macros are intended to be defined at boot time. Note that version 1-4 of
msireturns an error, which causes the softGlue build to fail, after writing a database file that contains unexpanded macros.
Deploying softGlue to an IOC
To configure an EPICS IOC application to use softGlue, you must make modifications in the following directories, and then rebuild the application.
configure/RELEASE – Edit the RELEASE file to define the following names:
SOFTGLUE=<path to the softGlue module>
ASYN=<path to the asyn module>
IPAC=<path to the ipac module>
BUSY=<path to the busy module>
BUSY is an optional add-on for use with softGlue. If the busy module is available, you can arrange for EPICS database processing to wait for a signal from softGlue hardware before declaring itself to be finished. The softGlue_convenience.db database loads busy records for this purpose, and the softGlueConvenience.adl display file contains menu items to display the records. Nothing else in softGlue depends on the busy module.
xxxApp/src – Edit Makefile or a *Include.dbd file so that softGlueSupport.dbd is included in the .dbd file the IOC loads at boot time. You’ll also need files from asyn, ipac, and busy, if you’re not already including them.
For a Makefile:
iocxxx_DBD_vxWorks += softGlueSupport.dbd drvIpac.dbd asyn.dbd busySupport.dbd
For the .dbd file that will be loaded into a vxWorks IOC:
include "softGlueSupport.dbd"
include "drvIpac.dbd"
include "asyn.dbd"
include "busySupport.dbd"
Edit Makefile so that the IOC executable is linked with the softGlue library. You’ll also need libraries from the asyn, ipac, and busy modules. The order in which libraries are named is sometimes important. Example:
xxx_LIBS_vxWorks += asyn Ipac softGlue busy
iocBoot/iocxxx – Copy softGlue/iocBoot/iocSoftGlue/softGlue.cmd to your IOC directory (iocBoot/iocxxx), and edit the dbLoadRecords() commands in your copy of softGlue.cmd to define the macro P, so that it’s unique to your IOC.
If you’ll have more than one IP_EP20x module in an IOC, you’ll also need to maintain separate definitions for the macro
H, for asyn port names associated with the modules, and for the macroREADEVENT. Port names are supplied as arguments to the functionsinitIP_EP200(),initIP_EP201(), andinitIP_EP201SingleRegisterPort(), and they are supplied as the macro definitionsPORT,PORT1,PORT2, andPORT3indbLoadRecords()commands.
If you specify the same value of
READEVENTfor N instances of softGlue in a single IOC, the software will still work, but it will use N times the CPU cycles, as each instance will post read events that will cause all other instances to read from the hardware.
Add the following line to st.cmd, before the call to iocInit():
< softGlue.cmd
If you use autosave, add the following line to save_restore.cmd:
set_requestfile_path(softglue, "softGlueApp/Db")
The first argument
softgluemust be all lowercase, because this is how the path variable is defined incdCommands.
Add the following line to auto_settings.req (or whatever you’ve named the file used to save/restore PVs of arbitrary type):
file softGlue_settings.req P=$(P) H=softGlue:
where the macros P and H agree with those in softGlue.cmd.
xxxApp/op/adl – If you use MEDM, add a related-display button to call up the softGlueMenu.adl display with the macros P and H, as defined in iocBoot/iocxxx/softGlue.cmd. The file softGlueApp/op/adl/softGlueTop.adl contains an example button.
If you figure out how to use softGlue with some other display manager, please tell us about it, so we can include your work in the next version of softGlue. The MEDM-display files included in softGlue make heavy use of MEDM’s
composite file, and other display managers may not have a comparable feature. softGlue’s use ofcomposite fileis purely a display-development convenience.
If you use MEDM, give it access to the softGlue module’s .adl files. In csh, you could do this with the following command:
setenv EPICS_DISPLAY_PATH $EPICS_DISPLAY_PATH':'$SOFTGLUE/softGlueApp/op/adl
Don’t forget to rebuild your application:
cd <applicationTop>
make rebuild
Configuring hardware
The IP-EP20x board must be configured to permit programming the FPGA via the IndustryPack bus, by moving the DIP jumper to “IP BUS”. This is the factory default setting.
Configuring softGlue
softGlue is configured by editing softGlue.cmd. This file contains calls to the user callable functions described below, and dbLoadRecords() commands that load the databases matching the FPGA content.
User callable functions
The following functions are called from softGlue.cmd (or from st.cmd) to initialize the IP-EP20x module and softGlue support.
initIP_EP200_FPGA
initIP_EP200_FPGA(ushort carrier, ushort slot, char *filename)
carrier: IP-carrier number (numbering begins at 0)
slot: IP-slot number (numbering begins at 0)
filename: Name of the FPGA-content hex file to load into
the FPGA.
Example:
initIP_EP200_FPGA(0, 2, "$(SOFTGLUE)/softGlueApp/Db/SoftGlue_2_2.hex")
Write content to the FPGA. This command will fail if the FPGA already has content loaded, as it will after a soft reboot. When the command fails for this reason, the already loaded FPGA content will be left as it was, with no ill effect. To load new FPGA content, you must power cycle the IOC.
initIP_EP200
initIP_EP200(ushort carrier, ushort slot, char *portName1,
char *portName2, char *portName3, int sopcBase)
carrier: IP-carrier number (numbering begins at 0)
slot: IP-slot number (numbering begins at 0)
portName1: Name of asyn port for component at sopcBase
portName2: Name of asyn port for component at sopcBase+0x10
portName3: Name of asyn port for component at sopcBase+0x20
sopcBase: must agree with FPGA content (0x800000)
Example:
initIP_EP200(0, 2, "SGIO_1", "SGIO_2", "SGIO_3", 0x800000)
Initialize basic field I/O.
initIP_EP200_Int
initIP_EP200_Int(ushort carrier, ushort slot, int intVectorBase,
int risingMaskMS, int risingMaskLS,
int fallingMaskMS, int fallingMaskLS)
carrier: IP-carrier number (numbering begins at 0)
slot: IP-slot number (numbering begins at 0)
intVectorBase: must agree with the FPGA content loaded
(0x90 for softGlue 2.1 and higher;
0x80 for softGlue 2.0 and lower).
softGlue uses three vectors, for example,
0x90, 0x91, 0x92.
risingMaskMS: interrupt on 0->1 for I/O pins 33-48
risingMaskLS: interrupt on 0->1 for I/O pins 1-32
fallingMaskMS: interrupt on 1->0 for I/O pins 33-48
fallingMaskLS: interrupt on 1->0 for I/O pins 1-32
Example:
initIP_EP200_Int(0, 2, 0x90, 0x0, 0x0, 0x0, 0x0)
Initialize field-I/O interrupt support.
Interrupt vectors are hardwired in the supplied FPGA content. Each IP-EP20x module uses three vectors (0x90, 0x91, 0x92), one for each set of 16 I/O bits. Depending on the interrupt-service mechanism supported by the operating system, multiple IP-EP20x boards may or may not all be able to generate interrupts. For PowerPC processors, interrupt-service routines (ISRs) are chained, so multiple IP-EP20x modules can all generate interrupts. But if the operating system doesn’t permit multiple ISRs attached to a single interrupt vector, then only one IP-EP20x board will be able to generate interrupts. See “Field I/O Interrupt support” in the User Guide for a description of the
softGlueFieldIO_Intxx.adldisplay.
initIP_EP200_IO
initIP_EP200_IO(ushort carrier, ushort slot,
ushort moduleType, ushort dataDir)
carrier: IP-carrier number (numbering begins at 0)
slot: IP-slot number (numbering begins at 0)
moduleType: one of [201, 202, 203, 204]
dataDir: Bit mask, in which only the first 9 bits are
significant. If a bit is set, the corresponding
field I/O pins are outputs. Note that for the
202 and 204 modules, all I/O is differential,
and I/O pin N is paired with pin N+1. For the
203 module, pins 25/26 through 47/48 are
differential pairs.
Correspondence between dataDir bits (0-8) and I/O pins (1-48):
| dataDir bit | 201 | 202 or 204 | 203 |
|---|---|---|---|
| bit 0 | pins 1-8 | pins 1, 3,25,27 | pins 25,27 |
| bit 1 | pins 9-16 | pins 5, 7,29,31 | pins 29,31 |
| bit 2 | pins 17-24 | pins 9,11,33,35 | pins 33,35 |
| bit 3 | pins 25-32 | pins 13,15,37,39 | pins 37,39 |
| bit 4 | pins 33-40 | pins 17,19,41,43 | pins 41,43 |
| bit 5 | pins 41-48 | pins 21,23,45,47 | pins 45,47 |
| bit 6 | x | x | pins 1-8 |
| bit 7 | x | x | pins 9-16 |
| bit 8 | x | x | pins 17-24 |
Examples:
- For the IP-EP201,
moduleTypeis 201, anddataDir == 0x3cwould mean that I/O bits 17-48 are outputs. - For the IP-EP202 or IP-EP204,
moduleTypeis 202 or 204, anddataDir == 0x13would mean that I/O bits 1,3,25,27, 5,7,29,31, 17,19,41,43 are outputs. - For the IP-EP203,
moduleTypeis 203, anddataDir == 0x???would mean that I/O bits 1-8, 25,27, 29,31, 33,35, 45,47 are outputs.
Set field-I/O data direction:
initIP_EP200_IO(0, 2, 201, 0x3c)
initIP_EP201
For backward compatibility with softGlue 2.1 and earlier, the following command can be used to initialize an IP_EP201 module, instead of the above calls to initIP_EP200(), initIP_EP200_Int(), and initIP_EP200_IO(). This won’t work for any other IP_EP200-series module.
initIP_EP201(char *portName, ushort carrier, ushort slot,
int msecPoll, int dataDir, int sopcOffset,
int interruptVector, int risingMask, int fallingMask)
portName: Name of asyn port for component at
sopcOffset
carrier: IP-carrier number (numbering begins at 0)
slot: IP-slot number (numbering begins at 0)
msecPoll: Time interval between driver polls of
field I/O bits
dataDir: Data direction for I/O bits, explained
below.
sopcOffset: SOPC offset (must be as in example below).
interruptVector: Must agree with the FPGA content loaded
(0x90, 0x91, 0x92 for softGlue 2.1 and
higher; 0x80, 0x81, 0x82 for softGlue 2.0
and lower).
risingMask: 16-bit mask: if a bit is 1, the
corresponding I/O bit will generate an
interrupt when its value goes from 0 to 1.
Bit 0 corresponds to field I/O pin 1,
bit 1 to pin 2, etc.
fallingMask: Similar to risingMask, but for 1-to-0
transitions.
Note that the user can overwrite risingMask
and fallingMask at run time, with menu
selections, and probably has those
selections autosaved.
dataDir is a bit mask in which only bits 0 and 8 are significant:
- For
sopcOffset0x800000:- If bit 0 of
dataDiris set, I/O bits 1-8 are outputs. - If bit 8 of
dataDiris set, I/O bits 9-16 are outputs.
- If bit 0 of
- For
sopcOffset0x800010:- If bit 0 of
dataDiris set, I/O bits 17-24 are outputs. - If bit 8 of
dataDiris set, I/O bits 25-32 are outputs.
- If bit 0 of
- For
sopcOffset0x800020:- If bit 0 of
dataDiris set, I/O bits 33-40 are outputs. - If bit 8 of
dataDiris set, I/O bits 41-48 are outputs.
- If bit 0 of
Example:
initIP_EP201("SGIO_1",0,2,1000000,0x101,0x800000,0x90,0x00,0x00)
initIP_EP201("SGIO_2",0,2,1000000,0x101,0x800010,0x91,0x00,0x00)
initIP_EP201("SGIO_3",0,2,1000000,0x101,0x800020,0x92,0x00,0x00)
Interrupt vectors are currently hardwired in the supplied FPGA content. Thus, if you want to use two or more IP_EP20x modules, only one may be permitted to generate interrupts. Interrupt generation is entirely an end-user choice, and it occurs only for the purpose of causing some EPICS record to process on the change of state of a softGlue field I/O signal. See “Field I/O Interrupt support” in the User Guide for a description of the
softGlueFieldIO_Intxx.adldisplay.
initIP_EP201SingleRegisterPort
initIP_EP201SingleRegisterPort(char *portName,
ushort carrier, ushort slot)
Initialize softGlue signal-name support.
Example:
initIP_EP201SingleRegisterPort("SOFTGLUE", 0, 2)