1 of 35

Practical EPICS Training�IOC Basics

erhtjhtyhy

Kevin Peterson

XSD-BC

January 20, 2023

Suggested line of text (optional):

WE START WITH YES.

2 of 35

Disclaimer

Target audience:

People who have used EPICS but never needed to know anything about IOCs

People who are new to EPICS

Goals:

Provide a foundation of IOC knowledge on which future trainings will build

Enable examination of existing IOCs with minimal confusion

2

3 of 35

What is an IOC?

An IOC:

  • serves EPICS Process Variables (PVs)
  • (optional) talks to controls hardware.

An IOC is just an application running on a computer

3

Channel

Access

Serial

Ethernet

4 of 35

What is a Process Variable (PV)?

PV = record_name + . + field_name

4

13PS1:cam1:NumImages.VAL

kmp3:userCalcOut2.CALC

kmp3:m1.RBV

kmp3:scan1.P1PV

5 of 35

What is a record?

  • Each record type performs a specific function
  • Records are customizable via fields
  • Records vary significantly in complexity
    • Simple records are associated with individual data types
      • bi, bo, mbbi, mbbo, longin, longout, ai, ao, stringin, stringout, waveform
    • Intermediate records often perform calculations or link multiple records
      • calcout, scalcout, acalcout, swait, transform, fanout, dfanout
    • Complex records are associated with devices or higher-level functionality
      • motor, scaler, mca, sscan, table, digitel, vs
    • Flexible records allow custom functionality to be implemented
      • sub, aSub, luascript

Records are the building blocks of EPICS

5

6 of 35

What is a record field?

  • Noteworthy fields:
    • VAL - the default field (used if no field is specified*)
    • NAME - the record name (helpful if records are aliased)
    • DESC - record description
    • RTYP - the record type
    • DTYP - the device support type (not meaningful for all record types)
    • SCAN - determines when a record processes
    • DISP - disable puts (ca & pva) from outside the IOC (when non-zero)
    • DISV/DISA/SDIS - disable record processing
      • Record processing is disabled when DISA equals DISV
      • DISA is set to the value of the PV in the SDIS field, if it isn't empty
    • TPRO - trace processing

A controllable or informative property of a record

6

7 of 35

How to learn more about record fields?

  • EPICS base record reference documentation
    • https://epics.anl.gov/base/R7-0/7-docs/RecordReference.html
    • Field documentation appears in multiple locations
      • Fields common to all record types
      • Fields common to input record types
      • Fields common to output record types
      • Record-specific documentation
  • synApps record reference documentation
    • In each module's documentation directory
      • https://github.com/epics-modules
      • /APSshare/epics/synApps_X_Y/support

It isn’t easy and requires multiple sources

7

8 of 35

Records in synApps modules

8

Module

Records

Module

Records

alive

alive

motor

motor

asyn

asyn

optics

table

busy

busy

scaler

scaler

calc

acalcout, scalcout, sseq, swait, transform

sscan

sscan

camac

camac

std

epid, timestamp, throttle

lua

luascript

vac

digitel, vs

mca

mca

vme

vme

9 of 35

The SCAN, PROC & FLNK fields

Records can be processed multiple ways:

  • Manually
    • Write 1 (or any non-zero value) to a record’s PROC field
    • Forward link (FLNK) from another record
  • Periodically
    • Set the SCAN field to something other than "Passive"
    • "I/O Intr" processes a record when the driver gets a new value, but is device/driver dependent

Records do nothing until they are processed

SCAN field options:

  • Passive
  • Event
  • I/O Intr
  • 10 second
  • 5 second
  • 2 second
  • 1 second
  • .5 second
  • .2 second
  • .1 second

9

10 of 35

Record link types

  • Input links read a value from another PV
  • The default link process command, NPP, is usually ok for input links
  • Change NPP to PP if values are stale
  • Change NPP to CP if the record should process every time the linked PV updates

Input Links

10

inlinkHelp is accessible from userTransform screens

11 of 35

Record link types

  • Output links write a value to another PV
  • The default link process command, NPP, is almost never the desired behavior for output links.
  • Change NPP to PP immediately and revert if problems are discovered.

Output Links

11

outlinkHelp is accessible from userTransform & scaler screens

12 of 35

Record link types

  • A forward link causes the linked record to process when the record containing the forward link is processed
  • Linked record is in the same IOC
    • record_name.FLNK = linked_record_name
    • record_name.FLNK = linked_record_name.PROC
  • Linked record is in a different IOC
    • record_name.FLNK = linked_record_name.PROC

Forward Links

12

13 of 35

What is a database?

  • A text file with a .db (or .template) extension
  • Generalized with macros to allow multiple instances to be loaded
  • Macros without default values are required
  • Macros required by the database should match the macros required by associated screens & autosave (.req) files

A collection of related records of various types

13

14 of 35

How are databases loaded?

dbLoadRecords("$(IP)/db/ADAM_4018.db", "P=kmp:,R=adam1,PORT=serial1,A=01")

dbLoadRecords("$(IP)/db/ADAM_4018.db", "P=kmp:,R=adam2,PORT=serial1,A=02")

dbLoadTemplate(“substitutions/ADAM_4018.substitutions”, “P=kmp:”)

ADAM_4018.substitutions:

file "$(IP)/db/ADAM_4018.db"

{

pattern

{R, PORT, A}

{adam1, serial1, 01}

{adam2, serial1, 02}

}

dbLoadRecords or dbLoadTemplate

14

15 of 35

How does one create an IOC?

  • The EPICS base approach
    • makeBaseApp.pl
      • Must be run multiple times
      • Creates IOC contents in the current directory
      • synApps support needs to be added manually
  • The synApps (xxx) approach
    • mkioc
      • A single command leaves you with an IOC you can build:
        • /APSshare/bin/mkioc -n -f -s 6-2-1 kmp
      • Creates a top-level IOC directory in the current directory
      • Common synApps support is included by default

No one does it from scratch

15

16 of 35

IOC Layout

kmp

├── bin

│ └── rhel8-x86_64

├── configure

│ ├── O.Common

│ └── O.rhel8-x86_64

├── db

├── dbd

├── iocBoot

│ └── iockmp

│ ├── autosave

│ ├── iocsh

│ ├── softioc

│ │ └── commands

│ └── substitutions

├── kmpApp

│ ├── Db

│ │ ├── O.Common

│ │ └── O.rhel8-x86_64

│ ├── op

│ │ ├── adl

│ │ └── ui

│ │ └── autoconvert

│ └── src

│ ├── O.Common

│ └── O.rhel8-x86_64

└── lib

└── rhel8-x86_64

16

17 of 35

IOC Layout

kmp

── bin

└── rhel8-x86_64

├── configure

├── O.Common

└── O.rhel8-x86_64

── db

── dbd

── iocBoot

└── iockmp

├── autosave

├── iocsh

├── softioc

│ └── commands

└── substitutions

Build configuration

├── kmpApp

├── Db

├── O.Common

└── O.rhel8-x86_64

── op

├── adl

└── ui

└── autoconvert

└── src

│ ├── O.Common

│ └── O.rhel8-x86_64

└── lib

└── rhel8-x86_64

17

18 of 35

IOC Layout

kmp

── bin

└── rhel8-x86_64

├── configure

│ ├── O.Common

│ └── O.rhel8-x86_64

── db

── dbd

── iocBoot

└── iockmp

├── autosave

├── iocsh

├── softioc

│ └── commands

└── substitutions

Intermediate build dirs

├── kmpApp

│ ├── Db

│ │ ├── O.Common

│ │ └── O.rhel8-x86_64

── op

├── adl

└── ui

└── autoconvert

└── src

│ ├── O.Common

│ └── O.rhel8-x86_64

└── lib

└── rhel8-x86_64

18

19 of 35

IOC Layout

kmp

├── bin

│ └── rhel8-x86_64

── configure

├── O.Common

└── O.rhel8-x86_64

├── db

├── dbd

├── iocBoot

│ └── iockmp

├── autosave

├── iocsh

├── softioc

│ └── commands

└── substitutions

Build products

── kmpApp

├── Db

│ ├── O.Common

│ └── O.rhel8-x86_64

├── op

│ ├── adl

│ └── ui

│ └── autoconvert

└── src

├── O.Common

└── O.rhel8-x86_64

└── lib

└── rhel8-x86_64

19

20 of 35

IOC Layout

kmp

── bin

└── rhel8-x86_64

── configure

├── O.Common

└── O.rhel8-x86_64

── db

── dbd

├── iocBoot

└── iockmp

├── autosave

├── iocsh

── softioc

└── commands

└── substitutions

Run-time configuration

├── kmpApp

│ ├── Db

│ │ ├── O.Common

│ │ └── O.rhel8-x86_64

│ ├── op

│ │ ├── adl

│ │ └── ui

│ │ └── autoconvert

│ └── src

│ ├── O.Common

│ └── O.rhel8-x86_64

└── lib

└── rhel8-x86_64

20

21 of 35

IOC Layout

kmp

── bin

└── rhel8-x86_64

── configure

├── O.Common

└── O.rhel8-x86_64

── db

── dbd

├── iocBoot

└── iockmp

── autosave

── iocsh

├── softioc

│ │ └── commands

│ └── substitutions

Start scripts

├── kmpApp

│ ├── Db

│ │ ├── O.Common

│ │ └── O.rhel8-x86_64

│ ├── op

│ │ ├── adl

│ │ └── ui

│ │ └── autoconvert

│ └── src

│ ├── O.Common

│ └── O.rhel8-x86_64

└── lib

└── rhel8-x86_64

21

22 of 35

How does support get into an IOC?

  • configure/RELEASE
    • Defines the locations of EPICS base and EPICS modules
    • Often includes other RELEASE files
  • kmpApp/src/Makefile
    • Specifies which database definitions (dbd) to include
    • Specifies which libraries should be included in the IOC binary
    • Specifies which local code should be included in the IOC binary
    • Libraries will not be included unless an associated dbd file is included
    • The order of the libraries is important (single-pass linker)
  • iocBoot/iockmp/st.cmd
    • The primary IOC config file that is sourced when the IOC is started
    • Name can vary slightly based on how the IOC was created

A quick overview

22

23 of 35

st.cmd

< envPaths

dbLoadDatabase("../../dbd/iockmpLinux.dbd")

iockmpLinux_registerRecordDeviceDriver(pdbbase)

### Databases are loaded

### Drivers are initialized/configured here

iocInit

### Sequence programs & autosave are started here

dbl > dbl-all.txt

date

The startup script, simplified

23

24 of 35

autosave

  • Autosaved values overwrite db defaults
  • Databases with associated req files (_settings.req) are automatically added to built_*.req by autosaveBuild
  • Multiple .sav files can be created
    • Default
      • .sav & .savB
      • actually restored
    • Periodic
      • .sav0, .sav1, .sav2, …
      • overwritten cyclically
    • Dated
      • .sav-230109-134502
      • written once at boot time

Mostly automatic when mkioc is used

iockmp

├── auto_positions.req

├── auto_settings.req

├── autosave/

│ ├── built_positions.req

│ └── built_settings.req

├── common.iocsh

── envPaths

── iocsh/

── settings.iocsh

── softioc/

├── st.cmd.Linux

└── substitutions/

24

25 of 35

How to build & clean a Linux IOC

  • Confirm the RHEL version
    • uname -r → 3.10.0-1160.62.1.el7.x86_64
    • cat /etc/redhat-release → Red Hat Enterprise Linux Server release 7.9
  • Set EPICS_HOST_ARCH environment variable
    • bash: export EPICS_HOST_ARCH=rhel7-x86_64
    • tcsh: setenv EPICS_HOST_ARCH rhel7-x86_64
  • Initiate the build in the top-level IOC directory
    • make

  • Remove intermediate build dirs (for the current EPICS_HOST_ARCH)
    • make clean
  • Remove all intermediate build dirs and top-level build directories
    • make distclean
  • Show all make options
    • make help

25

26 of 35

Running an IOC

# Create an alias for the script (assuming PWD = IOC’s top-level dir)

$ alias kmp=${PWD}/iocBoot/iockmp/softioc/kmp.sh

$ kmp

Usage: kmp.sh {console|restart|run|start|caqtdm|medm|status|stop|usage}

# Start caQtDM

$ kmp caqtdm &

# Start the IOC (in the background using screen or procServ)

$ kmp start

# Confirm the IOC is running

$ kmp status

kmp is running (pid=1281733) in a screen session (pid=1281732)

Use the script

26

27 of 35

Connecting to an IOC’s shell

# Manually connect to an IOC running in screen from the IOC’s host

$ screen -x kmp

# Connect to an IOC running in screen or procServ from the IOC’s host

$ kmp console

# Connect to an IOC running in screen or procServ with logging from any host

$ /APSshare/bin/iocConsole.py iockmp

# Manually connect to an IOC running in procServ from the IOC’s subnet

$ telnet s100bcda 53127

There are many ways to do it

27

28 of 35

Disconnecting from an IOC’s shell

  • Close the terminal that is connected to the screen or procServ session
    • Disconnects from both screen & procServ
    • Kills an IOC running outside of screen & procServ
  • Ctrl+a, Ctrl+d
    • Disconnects from both screen & procServ
    • Kills an IOC running outside of screen & procServ
  • Ctrl+a, d
    • Only disconnects from screen

There are not many ways to do it

28

29 of 35

IOC shell commands

help [command] - shows available commands or syntax of specified command

dbpr record_name [0-9] - displays fields and values for a given record

dbl - lists all records in an IOC

dbl record_type - lists all records of a specific type in an IOC

dbl record_type "field_list" - lists specified fields (space-separated list) of records of a specific type in an IOC

dbpf pv_name value - change a PV’s value – analogous to caput

dbgf pv_name - read a PV’s value – analogous to caget

epicsEnvShow - prints environment variables

seqShow - shows running sequence programs

seqStop - stops a running sequence program

29

30 of 35

CA command-line utilities

caget - get the value of one of more PVs

caput - change the value of a PV

camonitor - monitor the value of one or more PVs

cainfo - print info about a PV, including which host is running the IOC

Example:

$ caget kmp3:m1.{DESC,RTYP,DTYP,VAL}

kmp3:m1.DESC motor 1

kmp3:m1.RTYP motor

kmp3:m1.DTYP asynMotor

kmp3:m1.VAL 60

CA = Channel Access

30

31 of 35

Graphical User Interfaces (GUIs)

  • Both MEDM & caQtDM use environment variables to find screens
    • MEDM uses the EPICS_DISPLAY_PATH
    • caQtDM uses the CAQTDM_DISPLAY_PATH
  • caQtDM supports most of the important MEDM command-line options
  • The MEDM & caQtDM start scripts in the IOC’s top-level directory call setup_epics_common which adds directories to the display paths.
  • Screens can be launched manually:
    • /APSshare/bin/caQtDM -x -attach -macro "P=kmp:,M=m1" /APSshare/epics/synApps_6_2_1/support/motor-R7-2-2/motorApp/op/ui/autoconvert/motorx_all.ui &

MEDM & caQtDM

31

32 of 35

Where does EPICS support reside at the APS?

/APSshare (read-only)

└── epics

├── base-X.Y.Z

└── synApps_X_Y

└── support

/net/s##dserv/xorApps (read-write)

└── epics

└── synApps_X_Y

├── ioc

│ └── ## beamline IOCs are deployed here

└── support

└── Local support modules are deployed here

On the dserv, historically

32

33 of 35

How to add streamDevice support to an IOC

  • kmpApp/Db
    • Add .db and .proto files
  • iocBoot/iockmp/settings.iocsh
    • Change the STREAM_PROTOCOL_PATH from this:
      • "."
    • To this:
      • ".:$(TOP)/kmpApp/Db"
  • iocBoot/iockmp/iocsh/
    • Create a new .iocsh file that loads the .db files (and sets up the hardware communication*)
  • iocBoot/iockmp/st.cmd
    • Source the new .iocsh file
  • kmpApp/op/adl or kmpApp/op/ui or beamline screen location
    • Add the displays*
  • Restart the IOC

33

34 of 35

Questions?

35 of 35

35