====
Demo
====
You can build an `EPICS `_ IOC
with the steps described below.
This demo uses `virtual CAN interfaces `_
for an IOC on your system.
It also uses `sumo `_
to fetch and build all the needed device supports.
The demo shows how data is transferred from one output record
via the CAN bus to one input record.
How to build
------------
.. note::
If you are interested in how the demo works in detail, look at:
`Demo details`_
Download `ioc-multican-1.1.tgz `_.
Unpack with::
tar -xzf ioc-multican-1.1.tgz
Build everything with::
cd ioc-multican-1.1
./create-ioc.sh
How to run
----------
.. note::
You need 'sudo' permissions for this test since the IOC uses real time
task priorities that is not allowed for ordinary users.
In one terminal start the ioc with::
./start-ioc.sh
In another terminal you can inspect the records with these commands::
source ./setenv.sh
camonitor ca1testo cantesto ca2testo cantesti
This shows that the records are processed in this order:
- ca1testo : get counter, trigger can write
- cantesto : write to CAN bus, trigger ca2testo
- ca2testo : processed after CAN write
- cantesti : read from CAN bus, this comes last
You can also see timestamps with::
source ./setenv.sh
camonitor cantesto_ts.VALA cantesti_ts.VALA
This shows the human readable microsecond timestamp of
the CAN write and CAN read object.
With the 'candump' utility you can see your CAN bus I/O with::
candump any
What to do next
---------------
You may extend the database file 'socanTest.db' with other records
and for example, the SDO protocol.
Instead of the virtual CAN bus interfaces from this example you may want to
use physical CAN bus interfaces of CAN Bus I/O card. To do this, replace in
file 'iocBoot/iocsocanTest/st.cmd' the names "vcan0" to "vcan3" with "can0"
to "can3".
Demo details
------------
The demo uses `sumo `_ to
build MultiCAN and all supports that it depends on. sumo has a
dependency database that contains information where to get an
EPICS support and on which other supports it depends.
The demo script creates a dependency database
with command `sumo config new sumo-free-database INITIAL `_.
It then creates a file 'configure/MODULES' with command
`sumo build complete `_.
Here are the relevant parts of the dependency database::
{
"ALARM": {
"R4-5-1": {
"aliases": {
"BASE": "EPICS_BASE",
"MISC_DBC": "DBC"
},
"dependencies": [
"BASE",
"MISC_DBC"
],
"source": {
"git": {
"tag": "R4-5-1",
"url": "https://git.code.sf.net/p/almlib-hzb/code"
}
}
}
},
"BASE": {
"R3-15-9": {
"make-recipes": {
"config": [
"sed -i 's/rhs\\.pConstEntry/rhs.pEntry/' $DIR/src/libCom/cxxTemplates/tsSLList.h",
"sed -i '/^STATIC_LDFLAGS_YES/i POSIX_CFLAGS+= -std=gnu17' $DIR/configure/os/CONFIG.linux-x86.linux-x86",
"echo \"export EPICS_HOST_ARCH=$$(perl $(BASE)/src/tools/EpicsHostArch.pl)\" > $DIR/setenv.sh",
"echo \"export EPICS_BASE=$(BASE)\" >> $DIR/setenv.sh",
"echo \"export PATH=\\$$EPICS_BASE/bin/\\$$EPICS_HOST_ARCH:\\$$PATH\" >> $DIR/setenv.sh"
],
"distclean": [
"$(MAKE) -C $DIR distclean",
"rm -f $DIR/setenv.sh"
]
},
"source": {
"git": {
"tag": "R3.15.9",
"url": "https://github.com/epics-base/epics-base.git"
}
}
},
},
"MCAN": {
"R2-10-2-Linux": {
"aliases": {
"BASE": "EPICS_BASE"
},
"dependencies": [
"ALARM",
"BASE",
"MISC_DBC",
"SOCAN",
"SOFT_DEVHWCLIENT",
"TOOLS_HGEN"
],
"make-recipes": {
"config": [
"cd $DIR && sed -i -e 's#^\\(USE_SCAN_Linux\\) *=.*#\\1=NO#;s#^\\(USE_SOCAN_Linux\\) *=.*#\\1=YES#' configure/CONFIG"
]
},
"source": {
"git": {
"tag": "R2-10-2",
"url": "https://git.code.sf.net/p/mcan/code"
}
}
}
},
"MISC_DBC": {
"R3-1-1": {
"aliases": {
"BASE": "EPICS_BASE"
},
"dependencies": [
"BASE"
],
"source": {
"git": {
"tag": "R3-1-1",
"url": "https://git.code.sf.net/p/misc-dbc-hzb/code"
}
}
}
},
"SOCAN": {
"1.2.1": {
"make-recipes": {
"all": [
"$(MAKE) -C $DIR epics"
]
},
"source": {
"hg": {
"tag": "1.2.1",
"url": "http://hg.code.sf.net/p/socan/code"
}
}
}
},
"SOFT_DEVHWCLIENT": {
"R3-1-1": {
"aliases": {
"BASE": "EPICS_BASE"
},
"dependencies": [
"BASE"
],
"source": {
"git": {
"tag": "R3-1-1",
"url": "https://git.code.sf.net/p/soft-devhwclient-hzb/code"
}
}
}
},
"TOOLS_HGEN": {
"1.8.1": {
"make-recipes": {
"all": [
"$(MAKE) -C $DIR epics"
]
},
"source": {
"hg": {
"tag": "1.8.1",
"url": "http://hg.code.sf.net/p/hgen/code"
}
}
}
}
}
The demo script then creates an EPICS ioc with
`makeBaseApp.pl `_.
The created directory tree is then modified for the demo application.
File ``configure/MODULES`` defines what support modules the application
needs, this is the content of this file::
{
"alias": [
"BASE:EPICS_BASE",
"SOFT_DEVHWCLIENT:DEVHWCLIENT"
],
"module": [
"ALARM:R4-5-1",
"BASE:R3-15-9",
"MCAN:R2-10-2-Linux",
"MISC_DBC:R3-1-1",
"SOCAN:1.2.1",
"SOFT_DEVHWCLIENT:R3-1-1",
"TOOLS_HGEN:1.8.1"
]
}
The file ``socanTestApp/src/Makefile`` contains these statements to use
MultiCAN::
socanTest_DBD += alm.dbd
socanTest_DBD += hwLowcalRecord.dbd
socanTest_DBD += MultiCAN.dbd
socanTest_DBD += socan.dbd
socanTest_LIBS += socan sci
socanTest_LIBS += alm
socanTest_LIBS += hwLowcalRecord mCANSupport mCANCore
The startup script ``iocBoot/iocsocanTest/st.cmd`` initializes the application.
Here are the relevant parts for the usage of MultiCAN::
# initialize almlib:
alm_init()
# Initialize MCAN:
mcanInit()
gpsInit()
dbg_init()
# Set initHook for MultiCAN:
mCANRegisterInitHooks()
# Enable handshake in LowCAL:
var glbl_lowcal_use_handshake 1
# Override inhibit time with 0 (microseconds):
var glbl_lowcal_override_inhibit 0
# Print messages for errors in GPS layer:
var gpsPrintErrors 0
# init socan
socantest("abc")
#socan_tracelevel(2)
socan_tracelevel(0)
socan_errprintlevel(3)
socan_add_port("vcan0")
socan_add_port("vcan1")
socan_add_port("vcan2")
socan_add_port("vcan3")
socan_init()
All calls to \*_init functions up to ``var gpsPrintErrors 0`` are needed
to initialize MultiCAN.
The commands below ``# init socan`` initialize the socan support that
is used by MultiCAN.
``socan_tracelevel(0)`` defines that socan doean't print trace output.
``socan_errprintlevel(3)`` defines that even minor errors are printed to the console.
``socan_add_port(INTERFACE)`` defines which interface maps to which port number, staring implicitly
with port 0. So "vcan0" maps to port 0, "vcan1" to port 1 and so on.
``socan_init()`` initializes the socan module.
The database definition file ``socanTestApp/Db/socanTest.db``
defines some records. We show here the two CAN
bus records. Both use the 'lowCAL' protocol::
record(longout,"cantesto")
# write to CAN bus:
# variable-type: server basic write-only,
# data-type: unsigned long, length: 4 bytes
# port: 0, out-cob: 2, in-cob: 0,
# inhibit: 1.0 [ms], timeout: 1000 [ms]
{
field(DTYP,"lowcal")
field(OUT,"@b L 4 0 2 0 0 a 3e8 0")
field(DOL, "counter NPP NMS")
field(OMSL, "closed_loop")
field(FLNK, "ca2testo")
}
record(longin,"cantesti")
# read from the CAN bus
# variable-type: server basic write-only,
# data-type: unsigned long, length: 4 bytes,
# port: 1, out-cob: 0, in-cob: 2,
# inhibit: 1.0 [ms], timeout: 1000 [ms],
{
field(DTYP,"lowcal")
field(INP,"@h L 4 1 0 2 0 a 3e8 0")
field(SCAN,"I/O Intr")
field(FLNK, "cantesto_ts")
}
The demo script then compiles the IOC and initializes the virtual
CAN interfaces with the scripts ``init-can.sh`` and ``link-vcan-devices.sh``
that are part of the socan device support.