Load common iocsh fragments in an IOC
Add the site services of the common iocsh fragments to an Experimental
Physics and Industrial Control System (EPICS) input/output controller (IOC)
built against an installed tree. The IOC application in these steps is
named demo. It loads the iocLog, serial, caPutLog, autosave, reccaster, and
linStat fragments, and leaves out iocStatsAdmin, whose records collide with
linStat; see
Common iocsh fragments.
Prerequisites
- An installed tree built with
make install, which holds the fragments inmodules/commonIocsh/iocsh; see Build and install the environment. - An IOC application whose
iocBoot/<ioc_name>directory has aMakefilethat writesenvPaths, such as one thatmakeBaseApp.pl -icreates. - For
iocLog.iocshandcaPutLog.iocsh: a log server, such asiocLogServerfrom EPICS base, listening on Transmission Control Protocol (TCP) port 7004 of<log_host>. - For
setSerialParams.iocsh: a serial device that the IOC can open.
-
In the IOC’s
configure/RELEASE, or theconfigure/RELEASE.localfile it includes, name EPICS base and each module with the macro that the fragments read:MODULES = <installed_tree>/modules AUTOSAVE = $(MODULES)/autosave RECCASTER = $(MODULES)/recsync LINSTAT = $(MODULES)/linStat CAPUTLOG = $(MODULES)/caPutLog ASYN = $(MODULES)/asyn EPICS_BASE = <installed_tree>/base<installed_tree>is the path thatmake print-INSTALL_LOCATION_EPICSprints in the EPICS-env clone that built the tree. List only the modules whose fragments the IOC loads. Common iocsh fragment macros names the module each fragment needs. -
In the application’s
src/Makefile, add the database definition (DBD) files and libraries of those modules before the linedemo_LIBS += $(EPICS_BASE_IOC_LIBS):demo_DBD += caPutLog.dbd asSupport.dbd reccaster.dbd linStat.dbd system.dbd demo_DBD += asyn.dbd drvAsynSerialPort.dbd demo_LIBS += caPutLog autosave reccaster linStat asynThe
makeBaseApp.pltemplate already addsbase.dbdand$(EPICS_BASE_IOC_LIBS).system.dbdregisters the iocshsystemcommand, whichautosave.iocshuses to create its directories. -
To build the IOC against the installed modules, run this command from the top of the IOC application:
make CHECK_RELEASE=NOThe installed modules keep the
configure/RELEASEfiles of their upstream sources, which name a differentEPICS_BASE. With the release check on, the build stops atDefinition of EPICS_BASE conflicts with CAPUTLOG support. The build writesiocBoot/<ioc_name>/envPaths, which setsIOCto<ioc_name>and sets each module macro of step 1. -
Optional: to configure serial ports, create a serial configuration file in
iocBoot/<ioc_name>, such asserialPorts.cmd, with onesetSerialParams.iocshline for each port:iocshLoad("$(IOCSH_TOP)/iocsh/setSerialParams.iocsh", "PORT=S1,BAUD=19200,BITS=8,STOP=2,PARITY=odd")PORTis the asyn port name that the startup script gives todrvAsynSerialPortConfigure. -
To let caPutLog see puts, create an access security configuration file (ACF) in
iocBoot/<ioc_name>, such asdemo.acf, that marks writes withTRAPWRITE:ASG(DEFAULT) { RULE(1, READ) RULE(1, WRITE, TRAPWRITE) } -
In
iocBoot/<ioc_name>/st.cmd, setIOCSH_TOPand load the fragments between the DBD registration andiocInit:#!../../bin/linux-x86_64/demo < envPaths epicsEnvSet("IOCSH_TOP", "<installed_tree>/modules/commonIocsh") dbLoadDatabase("$(TOP)/dbd/demo.dbd") demo_registerRecordDeviceDriver(pdbbase) iocshLoad("$(IOCSH_TOP)/iocsh/iocLog.iocsh", "IOC=$(IOC),LOG_INET=<log_host>") drvAsynSerialPortConfigure("S1", "<tty_device>", 0, 0, 0) iocshLoad("$(IOCSH_TOP)/iocsh/serial.iocsh", "SERIAL_ENABLE=,SERIAL_CONFIG=$(TOP)/iocBoot/$(IOC)/serialPorts.cmd") asSetFilename("$(TOP)/iocBoot/$(IOC)/demo.acf") iocshLoad("$(IOCSH_TOP)/iocsh/caPutLog.iocsh", "LOG_INET=<log_host>") iocshLoad("$(IOCSH_TOP)/iocsh/autosave.iocsh", "IOC=$(IOC),AS_TOP=<as_top>") iocshLoad("$(IOCSH_TOP)/iocsh/reccaster.iocsh", "IOC=$(IOC)") iocshLoad("$(IOCSH_TOP)/iocsh/linStat.iocsh", "IOC=$(IOC)") iocInit()<log_host>is the address of the log server.<tty_device>is the serial device path, such as/dev/ttyS0.<as_top>is a writable directory for the autosave files.
IOCSH_TOPnames the directory that holdsiocsh, becauselinStat.iocshloads its host and process sub-fragments from$(IOCSH_TOP)/iocsh.iocLog.iocshloads first so that the log server receives the messages of the device setup that follows.serial.iocshloads after the port it configures exists. Leave out the lines of any service the IOC does not use; to skip serial setup, leave outSERIAL_ENABLE=.
Verification
With the log server of the prerequisites listening, boot the IOC of steps 1 to 6 and check its output:
-
Change to the boot directory of the IOC:
cd <ioc_top>/iocBoot/<ioc_name><ioc_top>is the top directory of the IOC application. -
Start the IOC with
st.cmd, write its output toboot.log, and let it exit at the end of input:../../bin/linux-x86_64/demo st.cmd < /dev/null > boot.log 2>&1 -
Show the log client, serial, caPutLog, and autosave lines of the boot:
grep -E 'log client|iocRun|caPutLog:|asynSetOption|afterIocRunning' boot.logThe output of the IOC
iocdemois:log client: connected to log server at '<log_host>:7004' asynSetOption("S1", -1, "baud", "19200") asynSetOption("S1", -1, "bits", "8") asynSetOption("S1", -1, "stop", "2") asynSetOption("S1", -1, "parity", "odd") afterIocRunning("caPutLogInit('<log_host>:7004', 0)") afterIocRunning("makeAutosaveFileFromDbInfo('<as_top>/iocdemo/req/settings.req','autosaveFields')") afterIocRunning("makeAutosaveFileFromDbInfo('<as_top>/iocdemo/req/values_pass0.req','autosaveFields_pass0')") afterIocRunning("makeAutosaveFileFromDbInfo('<as_top>/iocdemo/req/values_pass1.req','autosaveFields_pass1')") afterIocRunning("create_monitor_set('settings.req','5')") afterIocRunning("create_monitor_set('values_pass0.req','5')") afterIocRunning("create_monitor_set('values_pass1.req','10')") iocRun: All initialization complete sevr=info caPutLog: successfully initialized log client: connected to log server at '<log_host>:7004' afterIocRunning: caPutLogInit('<log_host>:7004', 0) afterIocRunning: makeAutosaveFileFromDbInfo('<as_top>/iocdemo/req/settings.req','autosaveFields') afterIocRunning: makeAutosaveFileFromDbInfo('<as_top>/iocdemo/req/values_pass0.req','autosaveFields_pass0') afterIocRunning: makeAutosaveFileFromDbInfo('<as_top>/iocdemo/req/values_pass1.req','autosaveFields_pass1') afterIocRunning: create_monitor_set('settings.req','5') afterIocRunning: create_monitor_set('values_pass0.req','5') afterIocRunning: create_monitor_set('values_pass1.req','10') 7.0.10 > caPutLog: disabledThe two
log client: connectedlines show that iocLog and caPutLog each reach the log server. TheasynSetOptionlines show thatserial.iocshran the serial configuration file. The lines withafterIocRunning(are the commands that caPutLog and autosave register beforeiocInit, and the lines withafterIocRunning:show each one running afteriocInit.caPutLog: successfully initializedshows that the logger started, andcaPutLog: disabledshows it stopping when the IOC exits. The IOC writes to both standard output and standard error, soboot.logdoes not keep the order in which these lines run. Some of these lines carry terminal color codes, which the output above leaves out.