假设已经构建了EPICS Base,即是已经设置了环境变量EPICS_BASE,并且在系统搜索PATH中已经存在了EPICS的可执行文件。EPICS base在本机上的安装路径如下。
在EPICS路径下,用mkdir aiDirver创建一个目录,并且通过切换到这个路径下。用makeBaseApp.pl创建这个IOC程序框架。
root@orangepizero2:/usr/local/EPICS/program/aiDriver# makeBaseApp.pl -t ioc aiDriver
root@orangepizero2:/usr/local/EPICS/program/aiDriver# makeBaseApp.pl -i -t ioc aiDriver
Using target architecture linux-aarch64 (only one available)
The following applications are available:
aiDriver
What application should the IOC(s) boot?
The default uses the IOC's name, even if not listed above.
Application name?
root@orangepizero2:/usr/local/EPICS/program/aiDriver# ls
aiDriverApp configure iocBoot Makefile
root@orangepizero2:/usr/local/EPICS/program/aiDriver#
root@orangepizero2:/usr/local/EPICS/program/aiDriver# ls -R
.:
aiDriverApp configure iocBoot Makefile
./aiDriverApp:
Db Makefile src
./aiDriverApp/Db:
Makefile
./aiDriverApp/src:
aiDriverMain.cpp Makefile
./configure:
CONFIG CONFIG_SITE Makefile RELEASE RULES RULES_DIRS RULES.ioc RULES_TOP
./iocBoot:
iocaiDriver Makefile
./iocBoot/iocaiDriver:
Makefile st.cmd
1)configure目录中RELEASE文件中指明了这个IOC应用程序所依赖的其它EPICS模块,在本例中,只使用了base模块:
...
EPICS_BASE = /usr/local/EPICS/base
...
1)aiDriverApp/src中存放了本例中为aiRecord记录编写的驱动程序devAiDriver.c:
#include
#include
#include
#include
#include "alarm.h"
#include "dbDefs.h"
#include "dbAccess.h"
#include "epicsMath.h"
#include "recGbl.h"
#include "devSup.h"
#include "aiRecord.h"
#include "epicsExport.h"
/* Create the dset for devAiDriver */
static long init_record(dbCommon *pcommon);
static long read_ai(aiRecord *prec);
aidset devAiDriver = {
{6, NULL, NULL, init_record, NULL},
read_ai, NULL
};
// 导出这个驱动程序
epicsExportAddress(dset, devAiDriver);
static long init_record(dbCommon *pcommon)
{
aiRecord *prec = (aiRecord *)pcommon;
srand((unsigned)time(NULL));
prec->udf = FALSE;
return 0;
}
static long readLocked(struct link *pinp, void *dummy)
{
aiRecord *prec = (aiRecord *) pinp->precord;
long status = 0;
// 产生一个0-999之间的随机数
prec->rval = rand() % 1000;
if (dbLinkIsConstant(&prec->tsel) &&
prec->tse == epicsTimeEventDeviceTime)
dbGetTimeStamp(pinp, &prec->time);
return status;
}
static long read_ai(aiRecord *prec)
{
long status = dbLinkDoLocked(&prec->inp, readLocked, NULL);
if (status == S_db_noLSET)
status = readLocked(&prec->inp, NULL);
return status;
}
2)然后编写一个dbd文件devAiDriver.dbd:
device(ai,INST_IO,devAiDriver, "Random Ai")
3) 修改同一级目录下的Makefile文件,添加以下两行:
aiDriver_DBD += devAiDriver.dbd
aiDriver_SRCS += devAiDriver.c
4) 进入目录aiDriver/aiDriverApp/Db中,编写记录实例文件:
root@orangepizero2:/usr/local/EPICS/program/aiDriver/aiDriverApp/Db# cat aiTest.db
record(ai, "$(TEST):AiRandom")
{
field(DESC, "Test Ai Driver")
field(SCAN, "1 second")
field(DTYP, "Random Ai") # 指定设备驱动
field(ASLO, "1.0")
field(LINR, "NO CONVERSION")
}
5) 在与4)相同路径下的Makefile中添加以下一行:
DB += aiTest.db
切换到这个IOC的顶层目录,执行make,进行编译:
root@orangepizero2:/usr/local/EPICS/program/aiDriver# make
make -C ./configure install
...
make[1]: Leaving directory '/usr/local/EPICS/program/aiDriver/iocBoot'
root@orangepizero2:/usr/local/EPICS/program/aiDriver#
1)进入启动目录aiDriver/iocBoot/iocaiDriver,修改启动脚本st.cmd
#!../../bin/linux-aarch64/aiDriver
#- You may have to change aiDriver to something else
#- everywhere it appears in this file
< envPaths
cd "${TOP}"
## Register all support components
dbLoadDatabase "dbd/aiDriver.dbd"
aiDriver_registerRecordDeviceDriver pdbbase
## 装载记录实例
dbLoadRecords("db/aiTest.db","TEST=Random")
cd "${TOP}/iocBoot/${IOC}"
iocInit
2) 启动这个IOC程序,并用dbl查看这个IOC程序中加载的记录:
root@orangepizero2:/usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver# ../../bin/linux-aarch64/aiDriver st.cmd
#!../../bin/linux-aarch64/aiDriver
< envPaths
epicsEnvSet("IOC","iocaiDriver")
epicsEnvSet("TOP","/usr/local/EPICS/program/aiDriver")
...
epics> dbl
Random:AiRandom
相同局域网中,通过安装通道访问库的计算机,访问查看这个Random:AiRandom记录
[root@main-machine blctrl]# camonitor Random:AiRandom
Random:AiRandom 2023-06-06 01:34:43.853698 682
Random:AiRandom 2023-06-06 01:34:44.853710 143
Random:AiRandom 2023-06-06 01:34:45.853702 869
^C
可以看到被访问的记录,每秒钟产生一个0-1000之间的随机数。
以上详细描述了如何为一个EPICS记录开发驱动程序。此处开发的驱动程序是每秒为使用这个驱动程序的aiRecord提供一个0-999之间的RAW值。如果需要与具体硬件连接,请使用asyn模块。