SNS Controls Software Engineering Team

SNS Application Development Environment

“IOC Application HOWTO”

1.0 Prerequisites

The scope of this “HOWTO” is limited to the Red Hat Linux 7.x/8.x Operating system and the bash shell. Any extrapolation to other OSes or Shells is left as an exercise for the reader. Also, there will be no attempt to teach CVS. Please visit the following web site and learn CVS. (

This document is limited to EPICS BASE version 3.13.5 thru 3.13.8. There will be no attempt to describe EPICS Base 3.14.1 at this time.

Recommended reading to understand where the Application Development Environment (ADE) philosophy was derived:

You will also need to read the above document to understand the EPICS make system.

I will not attempt to duplicate EPICS documentation from the APS. READ the manual.

Before starting, your EPICS System manager will need to set a few things up:

1.1 Environment variables and Directory Structure

Let's begin with defining the root location of your ADE:

<ADE_TOP> defines the top-level location of the software components.


For Software components and apps that are shared/common across IOC applications

we define the following area:

The SUPTOP area will contain components such as epics base, extensions, and driver modules. The driver components will be pushed to a lower directory called share so that base and extensions stand-out as software kernel components of the control system.

Epics Drivers and other shared software applications are placed under SHARE_RELEASE

The following environment variables are used to define the location of the IOC software applications. The IOC applications should be organized from a machine oriented view.

All IOCs should begin there boot process from iocCommon. We will used the IOCS environment variable to define this.

When creating new IOC applications the PERL script is used to copy SNS style templates and directory structure under <TOP>. Where <TOP> refers to the directory in which the PERL script is executed. There will be examples on later pages that demonstrate this as well.

The following environment variables are useful for working with VxWorks

The following environment variable defines the target architecture that is being built:

Location of vxWorks headers and config files. Currently this is set at the system level.

We recommend that the following variable be defined in the build system.

For example, $(VX_DIR)/target.

1.2 Directory Structure

Refer to the figures below for the recommended directory structure for the ADE.

The <var> subdirectory is reserved for future use. <epics>/<var> could be useful storing ioc error log files, IOC save/restore files, etc...

The IOCTOP directory structure should be organized from a machine oriented view.

The exceptions to machine oriented view are global systems that are maintained completely in the control systems group. (e.g. CF, PPS, MPS, timing) . Therefore all subsytems should be created under the machine areas. The Vacuum subsytems should be changed to follow the machine oriented model.

Figure 1.2.2 IOCTOP hierarchy

Figure 1.2.3 IOCTOP/<linac> hierarchy

Next we will show a more detailed look at the IOCTOP hierarchy:

The area called SHARE under SUPTOP does not depend on a certain section of the accelerator. So after, the EPICS build version is selected via the system environment variables the components under share will just appear in alphabetical order. This where drivers and software that may be shared across application must be placed. Refer to figure 1.2.4 below to observe our current wealth of drivers.

Figure 1.2.4 SHARE directory structure

2.0 Creating an IOC Application

The SNS software team should use the EPICS Source/Release system to create new applications. The EPICS build environment uses various PERL scripts to provide structure, templates and a makefiles to facilitate IOC software creation. To create our first IOC application follow these steps at your Linux bash shell prompt:

Step 1. Source the appropriate epicsSetup environment script to pick the Release of epics software.

> source <ADE_TOP>/epics/site-setup/epicsSetup-bash-<epics-release>

Step 2: Create a TOP level directory in which to create the new App. This should be done somewhere in your home directory. Below substitute <TOP> with your directory name. This work should not begin in production areas. Play in your “sandbox”. Once your application is created and tested it should be imported into the software version control system. The SNS uses CVS as our versioning control system.

> mkdir <TOP>

Step 3: Our SNS standard for production IOCs is to derive the EPICS name of the IOC from the SNS naming convention. The IOCs EPICS name will also be used at the network name as well as the alias to get to the IOC's debug port.

For example, RFQ_HPRF:IOC1 becomes rfq-hprf-ioc1

> -T $TEMPLATE_TOP -t sns <yourAppName>

> -T $TEMPLATE_TOP -i -t sns <yourIOCName>

Let's take a look at Figure 2.1.1 to see what has happened:

Figure 2.1.1 IOC application directory structure; before a build

Step 4: Go to the config directory and modify the RELEASE and CONFIG files. The RELEASE file contains definitions for the location of external software components that will be used in this IOC application.

For example, to define the ether_ip driver module add the following line to the RELEASE file, where <module-release> refers to the version released from CVS.

---------------------- RELEASE file snippet -------------------------------------------------

ETHER_IP = $(SHARE_RELEASE)/ether_ip/<module-release>

----------------------- RELEASE file snippet ------------------------------------------------

Note: All of make variables in the RELEASE are taken from the EPICS system environment setup script. Of course, the variables can always be over-written by simply redefining them before the build of your IOC application. The EPICS build system also does consistency checks. The build report errors if the IOC application tries to link to an external product built against a different version of EPICS Base.

The CONFIG file can be used to override/select the target architecture built.

Be sure to look at the CROSS_COMPILER_TARGET make system variable. If this variable is commented out IOC application will attempt to build for every architecture that was built by EPICS Base. This may not be what you want. Remember also that the target architecture is meant to be defined in the EPICS system environment setup.

So, edit the CONFIG file and add the following entry; comment out everything else.

-------------------- CONFIG file snippet -----------------------------------------------------


---------------------- CONFIG file snippet ----------------------------------------------------

Step 5: Now descend into <yourAppName>App directory and modify the following files in the src directory:

Step 6: Descend into the Db directory located under <yourAppName>App. Here you will create your database using a suitable tool, such as a texteditor, VDCT, capfast, spread-sheets, etc... Now that you have a database created modify the Makefile.Host file to install your databases as part of the build process.

Step 7: Descend into the other directories beneath <yourAppName>App and follow a similar procedure to install products for edm screens, PLC binaries, alarm handler config, archiver request files, burt request files, and channel access security config.

Step 8: Return to you <TOP> directory and build your IOC Application.

You will notice the following product directories:

Never modify the files in these product directories!! When the IOC boots, it will load the products from the product directories. When EDM screens are launched, they should all reference screens from the <TOP>/opi directory. Remember, once a make clean uninstall is executed the product directories are gone and any changes you may have made!! So, if you need to change anything during the proof-of-principle and test phase modify the file in the source area and rebuild.

Step 9: Finally it is time to set up the <TOP>/iocBoot and the <ADE_TOP>/epics/iocCommon areas. This will be a detailed description; so step 9 will be a little long. Be patient, I know you want to get to CVS checkout, release and versioning procedures.

IOCs should be configured to boot in a consistent way so that maintenance

and upgrades can be performed and rolled back quickly.

Each IOC will have a directory in <ADE_TOP>/epics/iocCommon.

The name of the directory will be the same as the network name of the IOC.

Files in <ADE_TOP>/epics/iocCommon/<yourIOCName>



A description of the vriables defined in the startup.cmd file will be in the following format:



Set BY:




Set by: User

Usage: The network name of the IOC, set by the user. Use whenever the ioc’s network name is needed i.e. when locating startup files or database file in $SHARE. Should also be used for the prefix in vxStats substitutions.


Set by: User

Usage: The primary person on the call list for this IOC.


Set by: User

Usage: The Epics release in use. This is used for the main NFS mount commands and for calculating other variables.

For settings and components common to the boot process of all IOCs we define another file called “common.cmd” located in <ADE_TOP>/epics/iocCommon/All

So we begin describing the variables in the common.cmd file in the following format:



Set BY:




Set by: Epics Administrator

Usage: The server name used in all nfsMount commands.


Set by: Epics Administrator

Usage: The local path to the ${SHARE_RELEASE} directory on the server.


Set by: Epics Administrator

Usage: The local path to the $BASE directory on the server.


Set by: Epics Administrator

Usage: The local path to the $IOCTOP directory on the server.

There are other EPICS related environment variables that may be listed in the common.cmd file. If these are not specified the defaults will be obtained from the EPICS Base build. So the Epics System manager should be aware and ensure that these variables are set properly. In order that all IOCs are seen by the Archive server after a network disconnect CA beacons must be delivered to the Archive server. This is accomplished by setting EPICS_CA_ADDR_LIST = <IP address of Archive Server>.

This holds true for IOC peer communication across subnets. The EPICS_CA_ADDR_LIST is the responsibility of the user! Okay Step 9 is really getting long. So let's just paste in the example of the three files IOC startup files needed for booting.

  1. startup.cmd, (2) common.cmd, (3) st.cmd

--------------------------- startup.cmd -----------------------------------------------------

# startup script for FE_Ctl:IOC1

# This file generated from /ade/epics/iocCommon/config/startup.template


engineer="Fred Jr."


# Execute the common startup stuff

# This performs site nfsmounts and

# defines BASE SHARE and IOCTOP

< ../All/common.cmd

# Execute the startup script


cd "front_end"

cd "iocBoot"

cd iocName

< st.cmd


# End FE_Ctl:IOC1

--------------------------- startup.cmd ---------------------------------

----------------- common.cmd ---------------------------------------------

# Bootup script to be executed by all IOCS

# put hostAdd commands here

# Set the name of the server for all nfsMount commands

# The Epics site manager must set this name

# Front-end building:


netDevHandle=iosDevFind( "ics-accl-srv1:")

# Set the default NFS access user and group

nfsAuthUnixSet(nfsServer, 29147, 870, 0)

# Compute and mount SHARE


sprintf SHARE,"/ade/epics/supTop/share/%s",epicsBase

nfsMount nfsServer,SHARE,SHARE

# Compute and mount BASE


sprintf BASE,"/ade/epics/supTop/base/%s",epicsBase

nfsMount nfsServer,BASE,BASE

# Compute and mount IOCTOP


sprintf IOCTOP,"/ade/epics/iocTop/%s",epicsBase

nfsMount nfsServer,IOCTOP,IOCTOP

# Get rid of the netDev used to boot so that only the correct base

# files are available to the IOC

iosDevDelete netDevHandle

# Enviornment variables meaningful to epics












------------------------ common.cmd --------------------------------------------------

----------------------- st.cmd -------------------------------------------------------------

< cdCommands

#< ../nfsCommands

cd appbin

ld < iocCore

ld < seq

ld < initHooks.o

ld < bumplessLib

ld < snsUtilLib

ld < snsTimingLib

ld < timingClient

v124sConfig 0, 0x9000, 0x3a, 7, 0.0

cd top













dbpf "DHT_Tim:chan_1:name","DHT_Tim:Gate_A1"

dbpf "DHT_Tim:chan_2:name","DHT_Tim:Gate_A3"

dbpf "DHT_Tim:chan_3:name","DHT_Tim:Gate_A2"

dbpf "DHT_Tim:chan_4:name","DHT_Tim:Gate_A8"

dbpf "DHT_Tim:chan_5:name","DHT_Tim:Gate_A4"

dbpf "DHT_Tim:chan_6:name","DHT_Tim:Gate_A5"

dbpf "DHT_Tim:chan_7:name","DHT_Tim:Gate_A6"

dbpf "DHT_Tim:chan_8:name","DHT_Tim:Gate_A7"

------------------------- st.cmd -----------------------------------------------------------------

What is missing from the above discussion on IOCs:

  1. Discussion of IOC Log Server

  2. Discussion of bumpless reboot

  3. Discussion of where IOCs save other forms of data such as from a scan task, etc..

I am now about 70% complete. Next on the agenda will be a discussion of software release, versioning control and operations philosophy.

Stay Tuned.

Note <machine-section> refers to front_end, linac, ring, etc... If the system refers to a global controls area substitute <machine-section> with mpsMaster, timingMaster, etc...

> cd $IOCTOP_RELEASE/<machine-section>