本实例的目的是练习向IOCSH shell注册自己的函数:
1) 使用当前用户在其家目录中新建一个exer目录并且其下新建一个exer1目录,并切换到exer1目录下,并在此目录下用makeBaseApp.pl以base下的ioc为模板新建一个应用程序目录和ioc启动目录。
[blctrl@main-machine ~]$ mkdir exer
[blctrl@main-machine ~]$ cd exer/
[blctrl@main-machine exer]$ mkdir exer1
[blctrl@main-machine exer]$ cd exer1/
[blctrl@main-machine exer1]$ /usr/local/EPICS/base/bin/linux-x86_64/makeBaseApp.pl -t ioc exer1
[blctrl@main-machine exer1]$ /usr/local/EPICS/base/bin/linux-x86_64/makeBaseApp.pl -i -t ioc exer1
Using target architecture linux-x86_64 (only one available)
The following applications are available:
exer1
What application should the IOC(s) boot?
The default uses the IOC's name, even if not listed above.
Application name?
[blctrl@main-machine exer1]$ ls
configure exer1App iocBoot Makefile
2) 查看当前的目录结构:
[blctrl@main-machine exer1]$ ls
configure exer1App iocBoot Makefile
[blctrl@main-machine exer1]$ ls -R
.:
configure exer1App iocBoot Makefile
./configure:
CONFIG CONFIG_SITE Makefile RELEASE RULES RULES_DIRS RULES.ioc RULES_TOP
./exer1App:
Db Makefile src
./exer1App/Db:
Makefile
./exer1App/src:
exer1Main.cpp Makefile
./iocBoot:
iocexer1 Makefile
./iocBoot/iocexer1:
Makefile st.cmd
3) 进入到 exer1App/src/路径下,编辑四个文件exer1Hello.c和exer1Hello.dbd文件以及exer1Add.c和exer1Add.dbd文件,内容如下:
exer1Hello.c:
/* 展示如何向iocsh注册一条新命令的示例 */
# include <stdio.h>
# include <epicsExport.h>
# include <iocsh.h>
/* iocsh将能够直接调用这条命令。*/
void hello(const char * name)
{
if (name)
{
printf("Hello %s, from my fisrt exer1\n", name);
}
else{
printf("Hello from my exer1\n");
}
}
/* iocsh所需的信息 */
/*
定义这个参数的名称以及类型
*/
static const iocshArg helloArg0 = {"name", iocshArgString};
/* 定义参数数组,数组元素为iocshArg结构体的指针 */
static const iocshArg * helloArgs[] = {&helloArg0};
/* 这个函数的名称,这个函数需要的参数数目,以及其参数数组 */
static const iocshFuncDef helloFuncDef = {"hello", 1, helloArgs};
/* 由iocsh调用的包装器,选择hello需要的参数类型 */
static void helloCallFunc(const iocshArgBuf * args)
{
hello(args[0].sval);
}
/* 在启动时运行,注册程序 */
static void helloRegister(void)
{
//注册时,传给iocshRegister一个函数定义结构体iocshFuncDef的地址
//以及一个调用包装器
iocshRegister(&helloFuncDef, helloCallFunc);
}
/* 导出注册程序 */
epicsExportRegistrar(helloRegister);
exer1Hello.dbd:
registrar(helloRegister)
exer1Add.c:
# include <stdio.h>
# include <epicsExport.h>
# include <iocsh.h>
void add(int a, int b, const char * name, double time)
{
printf("a:%d\n",a);
printf("b:%d\n",b);
printf("%d + %d = %d\n", a, b , a+b);
if (name)
{
printf("Hello %s, from my fisrt exer1Add\n", name);
}
else{
printf("Hello from my exer1Add\n");
}
printf("time: %3.2f\n", time);
}
static const iocshArg addArg0 = {"a", iocshArgInt};
static const iocshArg addArg1 = {"b", iocshArgInt};
static const iocshArg addArg2 = {"name", iocshArgString};
static const iocshArg addArg3 = {"time", iocshArgDouble};
static const iocshArg * addArgs[] = {&addArg0, &addArg1,&addArg2,&addArg3};
static const iocshFuncDef addFuncDef = {"add", 4, addArgs};
static void addCallFunc(const iocshArgBuf * args)
{
add(args[0].ival, args[1].ival,args[2].sval,args[3].dval);
}
static void addRegister(void)
{
iocshRegister(&addFuncDef, addCallFunc);
}
epicsExportRegistrar(addRegister);
exer1Add.dbd:
registrar(addRegister)
4) 编辑相同目录下的Makefile文件,并且添加标注的几行:
TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
#=============================
# Build the IOC application
PROD_IOC = exer1
# exer1.dbd will be created and installed
DBD += exer1.dbd
# exer1.dbd will be made up from these files:
exer1_DBD += base.dbd
# Include dbd files from all support applications:
#exer1_DBD += xxx.dbd
exer1_DBD += exer1Hello.dbd # 添加行1
exer1_DBD += exer1Add.dbd # 添加行2
exer1_SRCS += exer1Hello.c # 添加行3
exer1_SRCS += exer1Add.c # 添加行4
# Add all the support libraries needed by this IOC
#exer1_LIBS += xxx
# exer1_registerRecordDeviceDriver.cpp derives from exer1.dbd
exer1_SRCS += exer1_registerRecordDeviceDriver.cpp
# Build the main IOC entry point on workstation OSs.
exer1_SRCS_DEFAULT += exer1Main.cpp
exer1_SRCS_vxWorks += -nil-
# Add support from base/src/vxWorks if needed
#exer1_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
# Finally link to the EPICS Base libraries
exer1_LIBS += $(EPICS_BASE_IOC_LIBS)
#===========================
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE
5) 退回到这个IOC的顶层目录,即exer1目录,执行make
[blctrl@main-machine src]$ cd ../..
[blctrl@main-machine exer1]$ ls
configure exer1App iocBoot Makefile
[blctrl@main-machine exer1]$ make
make -C ./configure install
make[1]: Entering directory '/home/blctrl/exer/exer1/configure'
...
make[2]: Leaving directory '/home/blctrl/exer/exer1/iocBoot/iocexer1'
make[1]: Leaving directory '/home/blctrl/exer/exer1/iocBoot'
6) 运行这个IOC,方法如下,进入到iocBoot/iocexer1目录下,执行以下命令:
[blctrl@main-machine exer1]$ cd iocBoot/iocexer1/
[blctrl@main-machine iocexer1]$ ls
envPaths Makefile st.cmd
[blctrl@main-machine iocexer1]$ ../../bin/linux-x86_64/exer1 st.cmd
#!../../bin/linux-x86_64/exer1
< envPaths
epicsEnvSet("IOC","iocexer1")
epicsEnvSet("TOP","/home/blctrl/exer/exer1")
epicsEnvSet("EPICS_BASE","/usr/local/EPICS/base")
cd "/home/blctrl/exer/exer1"
## Register all support components
dbLoadDatabase "dbd/exer1.dbd"
exer1_registerRecordDeviceDriver pdbbase
## Load record instances
#dbLoadRecords("db/xxx.db","user=blctrl")
cd "/home/blctrl/exer/exer1/iocBoot/iocexer1"
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.3.1
## EPICS Base built Sep 8 2022
############################################################################
iocRun: All initialization complete
## Start any sequence programs
#seq sncxxx,"user=blctrl"
epics>
7)验证iocsh中是否有hello命令,并且执行这个命令:
epics> help hello
hello name
epics> hello
Hello from my exer1
epics> hello(EPICS)
Hello EPICS, from my fisrt exer1
epics> hello EPICS
Hello EPICS, from my fisrt exer1
epics> help add
add a b name time
epics> add(1,2,blctrl, 5.0)
a:1
b:2
1 + 2 = 3
Hello blctrl, from my fisrt exer1Add
time: 5.00
epics> add 1 2 blctrl 5.0
a:1
b:2
1 + 2 = 3
Hello blctrl, from my fisrt exer1Add
time: 5.00
结论:通过以上练习,我们学会了如何向EPICS iocsh shell注册自己的函数以及在这个shell中运行所注册的函数。