The main reference for this module is this slide deck: (pdf)

In the previous step, we created and built our first EPICS application.  You spent some time looking through the directories before and after the build process.  You should have found that the directory structure looks something like this:

  • <TOP>
    • <TOP>App
      • Db
      • src
    • configure
    • iocBoot
      • <ioc>
    • bin
    • db
    • dbd
    • lib

The <TOP>App, configure, and iocBoot directories are the pre-build locations where files are edited and code is written.  The bin, db, dbd, and lib directories are outputs of the build process and contain the built files.

The core of a basic EPICS application are the EPICS databases.  These are located in the <TOP>App/Db directory, and are built per the Makefile located within that directory.  Let's take a look inside this directory to see what is there.  Right now, there is nothing!  Let's create our first EPICS database.

  1.  Within the <TOP>App/Db directory, create a new file.  Call it whatever you like, but in the example it will be called example.db
Create Db file
jmock@rhel6-64k  $ pwd
/u/ld/jmock/JeremyTest/JeremyTestApp/Db
jmock@rhel6-64k  $ touch example.db
jmock@rhel6-64k  $ ls
Makefile  example.db

Great, now you have a database file you can edit.  Open it in your favorite text editor.  Some examples are emacs and vi.  We will start by creating an analog output record to hold some data.  An analog output record is explained here.  It is a useful record type that we will use now as a data container.  Put the below text into the example.db file

example.db
record(ao,  "EXAMPLE:TEST:RECORD:1") {
  field(DESC, "Test record to learn about EPICS")
  field(DTYP, "Soft Channel")
  field(VAL,  "1.5")
}

Within the record definition, first we give it a type (ao) and then we give it a name ("EXAMPLE:TEST:RECORD:1")  Note that EPICS records must be unique, so choose a number different than 1 in your record name.  We have also given the record a description (DESC).  When you create records in IOC application, you should give them a description that is meaningful.  We have defined the record as DTYP (device type) Soft Channel.  This means it is software - it does not connect to a real device.  This is the default DTYP, but it helps to explicitly state it.  If the record were to connect to a real device to move data out from EPICS into the device (analog out), the DTYP would connect this record to the correct device support (driver).  Lastly, we have given the record an initial value of 1.5  Choose whatever initial value you like.

Next, let's build this database into our application.  Open the <TOP>App/Db/Makefile.  You should see a line that is commented out that looks something like this: "#DB += xxx.db"  Un-comment that line (remove the "#"), and change xxx.db to example.db:

Makefile
TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE

#----------------------------------------------------
# Create and install (or just install) into <top>/db
# databases, templates, substitutions like this
DB += example.db

#----------------------------------------------------
# If <anyname>.db template is not named <anyname>*.template add
# <anyname>_template = <templatename>

include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE

Now navigate to <TOP> and type make.  After the build process, you should see a db directory was created, and example.db was moved into that location.  You now have an EPICS database that can be loaded.  Let's load it.

Navigate to <TOP>/iocBoot/<ioc>.  The IOC is the one you created in the earlier stage of the project.  This directory has a file called st.cmd.  This is the startup file for your EPICS IOC.  Open it up and take a look.  At the top you should see a line that looks like this:

st.cmd
#!../../bin/rhel6-x86_64/JeremyTest

This line instructs the IOC to boot up with the binary called JeremyTest, located in <TOP>/bin/rhel6-x86-64.  You can find it there - that is the compiled output of the build process.

Coming back to the st.cmd, you can see that the startup process loads the dbd file (read about database definitions (dbd) in chapter 6 of the reference manual).  Then it has a commented out line that loads a db file.  Let's change that line to load the database we created:

st.cmd
#!../../bin/rhel6-x86_64/JeremyTest

#- You may have to change JeremyTest to something else
#- everywhere it appears in this file

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/JeremyTest.dbd"
JeremyTest_registerRecordDeviceDriver pdbbase

## Load record instances
dbLoadRecords("db/example.db")

cd "${TOP}/iocBoot/${IOC}"
iocInit

Great, now we are ready to run the IOC.  To do that, navigate to <TOP>/iocBoot/<ioc>.  We need to make st.cmd executable.  Call 'chmod a+x st.cmd' from the command line.  Now we can run our IOC.  Type './st.cmd' and watch it boot up.  You should see output in your terminal like this:

ioc shell
jmock@rhel6-64k  $ ./st.cmd
#!../../bin/rhel6-x86_64/JeremyTest
< envPaths
epicsEnvSet("IOC","sioc-b34-jeremy")
epicsEnvSet("TOP","/afs/slac.stanford.edu/u/ld/jmock/JeremyTest")
epicsEnvSet("EPICS_BASE","/afs/slac/g/lcls/epics/base/R7.0.3.1-1.0")
cd "/afs/slac.stanford.edu/u/ld/jmock/JeremyTest"
## Register all support components
dbLoadDatabase "dbd/JeremyTest.dbd"
JeremyTest_registerRecordDeviceDriver pdbbase
## Load record instances
dbLoadRecords("db/example.db")
cd "/afs/slac.stanford.edu/u/ld/jmock/JeremyTest/iocBoot/sioc-b34-jeremy"
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.3.1-1.0.6
## EPICS Base built Nov 10 2021
############################################################################
iocRun: All initialization complete
## Start any sequence programs
#seq sncxxx,"user=jmock"
epics>

There are some useful commands you can run in the IOC shell, such as:

  • dbl → lists all loaded records
  • dbior → lists status of all registered drivers
  • dbgf <PV> → gets the value of a PV

  • dbpf <PV> <VAL> → puts a new value to a PV.

In your IOC, let's list all the PVs, then get, change, and get the value of your example PV

ioc shell
epics> dbl
EXAMPLE:TEST:RECORD:1
epics> dbgf EXAMPLE:TEST:RECORD:1
DBF_DOUBLE:         1.5
epics> dbpf EXAMPLE:TEST:RECORD:1 2.5
DBF_DOUBLE:         2.5
epics> dbgf EXAMPLE:TEST:RECORD:1
DBF_DOUBLE:         2.5
epics>

You can see that your example PV now has a value of 2.5.

You can also use command line tools in the SLAC environment to get and put this value, or any value in our control system.  This uses the EPICS protocol called Channel Access.  Read about the protocol and some of the commands here.

You can use caget and caput just like the dbgf and dbpf commands.  Try them out

bash shell
jmock@lcls-dev3  $ caget EXAMPLE:TEST:RECORD:1
EXAMPLE:TEST:RECORD:1          1.5
jmock@lcls-dev3  $ caput EXAMPLE:TEST:RECORD:1 2.5
Old : EXAMPLE:TEST:RECORD:1          1.5
New : EXAMPLE:TEST:RECORD:1          2.5
jmock@lcls-dev3  $ caget EXAMPLE:TEST:RECORD:1
EXAMPLE:TEST:RECORD:1          2.5
jmock@lcls-dev3  $

You can use cainfo to find out more about the PV.  It tells you the host, the access, and very important information about the data type.  This is a double, for example.

bash shell
jmock@lcls-dev3  $ cainfo EXAMPLE:TEST:RECORD:1
EXAMPLE:TEST:RECORD:1
    State:            connected
    Host:             134.79.216.240:46131
    Access:           read, write
    Native data type: DBF_DOUBLE
    Request type:     DBR_DOUBLE
    Element count:    1
jmock@lcls-dev3  $

Finally, you can use camonitor to, well, monitor the PV value.  It will return the new value each time the PV value changes.  Calling any of these functions with the -h flag will show more options and other help about them

Now let's take a moment to get your IOC running properly in the SLAC environment.  This is an important step in creating a new IOC.

<STOP> and get your IOC running properly

On your own:

  1. Add a calculation record that counts up.
  2. Bonus: Link the analog out record and the calc record together.




  • No labels