EPICS IOC初始化

概要 -- 环境需要一个主程序

如果需要一个主程序(在除了vxWork和RTEMS外的所有环境上最可能),由驻留在由iocsh执行的启动脚本中的语句执行初始化。一个示例主程序是:

int main(int argc,char  *argv[])
{
   if (argc >= 2) {
       iocsh(argv[1]);
       epicsThreadSleep(.2);
   }
   iocsh(NULL);
   epicsExit(0)
   return 0;
}

首次调用iocsh执行来自启动脚本文件名的命令,此文件名必须以一个参量被传递给这个程序。用NULL参量第二次调用iocsh使得iocsh进入交互模式。这用户能够发出在"IOC Test Facility"章节中描述的命令以及像help的更多命令。

传递的命令文件通常被称为启动脚本,并且包含像这样的语句:

< envPaths
cd ${TOP}
dbLoadDatabase "dbd/appname.dbd"
appname_registerRecordDeviceDriver pdbbase
dbLoadRecords "db/file.db", "macro=value"
cd ${TOP}/iocBoot/${IOC}
iocInit

在IOC的启动目录中自动产生envPath文件并且其定义了若干环境变量,它们在这个启动脚本后面有用。总是提供在以下显示的定义;为在应用程序的configure/RELEASE文件中引用的每个支持模块创建其它条目。

epicsEnvSet("ARCH","linux-x86")
epicsEnvSet("IOC","iocname")
epicsEnvSet("TOP","/path/to/application")
epicsEnvSet("EPICS_BASE","/path/to/base")

概要 -- vxWorks

在IOC启动时在装载了vxWorks之后,像通常被放在vxWorks启动脚本中的以下命令被发出来装载和初始化这个程序代码:

# Many vxWorks board support packages need the following:
#cd <full path to IOC boot directory>
< cdCommands
cd topbin
ld 0,0, "appname.munch"

cd top
dbLoadDatabase "dbd/appname.dbd"
appname_registerRecordDeviceDriver pdbbase
dbLoadRecords "db/file.db", "macro=value"

cd startup
iocInit

在IOC启动目录中自动产生cdCommands脚本并且定义了若干vxWorks全局变量,它们允许cd命令到各种位置,并且也设置若干环境变量。总是提供以下展示的定义;将为在 应用程序configure/RELEASE文件中每个支持模块创建更多的条目:

startup = "/path/to/application/iocBoot/iocname"
putenv "ARCH=vxWorks-68040"
putenv "IOC=iocname"
top = "/path/to/application"
putenv "TOP=/path/to/application"
topbin = "/path/to/application/bin/vxWorks-68040"
epics_base = "/path/to/base"
putenv "EPICS_BASE=/path/to/base"
epics_basebin = "/path/to/base/bin/vxWorks-68040"

在启动脚本中ld命令装载IOC需要的EPICS核心,记录,设备和驱动支持,和已经链接进它的任何应用程序特定模块。

dbLoadDataBase装载描述这个应用程序使用的record/device/driver的数据库定义文件。

dbLoadRecords装载记录实例定义。

iocInit初始化各种epics组件并且启动这个IOC运行。

概要 -- RTEMS

取决于用于一款硬件的电路板支持包,RTEMS程序可以用很多不同方式启动。使用Cexp包的系统能够当成vxWorks。其它系统从非易失内存或者从DOOTP/DHCP服务器读取参数。确切的机制取决于BSP。TFTP或NFS文件系统接着被挂载并且IOC shell用于从启动脚本读取命令。通过初始化参数指定这个启动脚本的位置。这个脚本经常类似或者等同于与vxWorks一起使用的脚本。

RTEMS启动代码就在从非易失内存设置初始化参数前调用:

epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config  *);

就在设置这个初始化参数后:

epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config  *);

一个程序会提供这两个例程中任何一个或者全部来执行所需的任何自定义初始化。在头文件epicsRtemsInitHooks.h中能够找到这些函数原型和一些有用的外部变量声明。

IOC初始化

如在以上启动脚本中展示的,通常用iocInit启动一个IOC,这实际上在两个不同部分中实现的。第一部分可以作为iocBuild命令被单独运行,它把IOC置入一个静默状态,而没有使得它启动的各种内部线程实际上运行。第二个命令iocRun从这个状态能够用于使得它快速上线。使用iocPause命令能够静默一个运行的IOC,它冻结所有内部运行;到此iocRun命令能够从它停止的位置重启它,或者IOC能够被关闭(退出程序,或者在vxWorks/RTEMS上重启)。还未用暂停一个IOC的可能性编写大部分设备支持和驱动,所以这个特性在一个同外部设备或软件会话的IOC上使用会不安全。

使用iocBuild和iocRun命令的IOC初始化由以下步骤组成:

配置一个主线程

 只要IOC还未被初始化,首先宣布initHookAtIocBuild。

主线程的epicsThreadIsOkToBlock标记被设置,消息"Starting iocInit"被记录并且调用epicsSignalInstallSigHupIgnore,这在Unix架构上防止这个进程如果在后面收到一个HUP信号时关闭。

到此,宣布initHookAtBeginning。

多用途模块

调用coreRelase,它调用一条显示正在运行哪个iocCore版本的消息。

调用taskwdInit启动任务看门狗。这接收监控其它任务的请求。它周期地运行并且检查是否任何任务被挂起。如果这样,发出一条错误消息,并且也能够调用由任务自身或者对IOC状态感兴趣的其它软件注册地回调例程。详细见"任务看门狗"。

通过调用callackInit,启动多用途回调任务。以不同调度优先级启动三个任务。

宣布initHookAfterCallbackInit。

通道访问链接

调用dbCaLinkInit。这初始化处理数据库通道访问链接的模块,但还不允许它的任务运行。

宣布initHookAfterCaLinkInit。

驱动支持

initDrvSup定位每个设备支持驱动入口表并且调用每个驱动的init例程。

宣布initHookAfterInitDrvSup。

记录支持

initRecSup定位每个记录支持入口表并且未每种记录类型调用init例程。

宣布initHookAfterInitRecSup。

设备支持

initDevSup定位每个设备支持入口表并且调用它的init例程指定这是初始调用。

宣布initHookAfterInitDevSup。

数据库记录

调用initDatabase,这使得在数据库上进行三次passes,执行以下函数:

  1. 为每个记录初始化字段REST,RDES,MLOK,MLST,PACT和DST。调用记录支持的init_record(第一次pass)
  2. 转换每个PV_LINK为DB_LINK或CA_LINK。调用任何扩展的设备支持的add_record例程。
  3. 调用基类支持的init_record(第二次pass)

最终它注册一个epicsAtExit例程,当IOC程序退出时,关闭这个数据库。

接着调用dbLockInitRecords创建锁集。

接着运行dbBkpInit初始化数据库调试模式。

宣布initHookAfterInitDatabase。

再次设备支持

initDevSup定位每个设备支持入口表并且调用它的init例程指定这是最终调用。

initHookAfterFinishDevSup宣布。

扫描和访问安全

通过调用scanInit初始化周期,事件,和I/O事件扫描器,但创建的扫描线程还不被允许运行任何记录。

一个对asInit的调用初始化访问安全。如果这报告出错,IOC初始化被取消。

dbProcessNotifyInit初始化对过程通知的支持。

在允许设置的短暂延时后,宣布initHookAfterScanInit。

初始化运行

initialProcess运行所有PINI设置为YES的记录。

宣布initHookAfterInitialProcess。

通道访问服务器

通过调用rsrv_init启动通道访问服务器,但它的任务不被允许运行,因此它还不向网络宣布它的存在。

宣布initHookAfterCaServerInit。

到此,IOC已经完全被初始化了但仍然静默。宣布了initHookAfterIocBuild。如果使用iocBuild启动,这个命令到此结束。

使能记录运行

如果使用iocRun命令使得IOC脱离它的初始静默状态,它从这开始。

 宣布initHookAtIocRun。

接着例程scanRun和dbCaRun被调用来使能它们的相关联任务并且设置全局变量interruptAccept为TRUE(这现在在scanRun内发生)。直到设置了这个,否则应该忽略所有I/O中断。

宣布initHookAfterDataBaseRunning。

如果首次执行了iocRun命令(或iocInit),宣布initHookAfterInterrupt。

使能CA服务器

通过调用rsrv_run允许通道访问服务器任务运行。

宣布initHookAfterCaServerRunning。如果这个IOC首次启动,宣布initHookAtEnd。

记录下一条命令完成消息,并且宣布initHookAfterIocRunning。

暂停一个IOC

命令iocPause切换正在运行的IOC到静默状态,使所有记录运行冻结(除了可能地异步I/O操作的结束)。使用iocRun可能能够重启一个暂停的IOC,但它能否完全恢复取决于它已经静默了多久以及已经运行的任何设备驱动的状态。组成暂停操作的操作如下:

  1. 宣布initHookAtIocPause
  2. 通过调用rsrv_pause,暂停通道访问服务器
  3. 宣布initHookAfterIocServerPaused
  4. 调用例程dbCaPause和scanPause来暂停相关联的任务并且设置全局变量interruptAccept为False
  5. 宣布initHookAfterDatabasePause
  6. 在记录一条暂停消息后,宣布initHookAfterIocPaused

更改iocCore固定的限制

在装载iocCore来更改iocCore固定的限制之后,以下命令能够被发出。应该在任何dbLoadDatabase命令前给出这些命令:

callbackSetQueueSize(size)
dbPvdTableSize(size)
scanOnceSetQueueSize(size)
errlogInit(buffersize)
errlogInit2(buffersize, maxMessageSize)

callbackSetQueueSize(size)

对多用途回调任务的请求被放置在一个环形缓存中。这个命令能够用于为这个环形缓存设置尺寸。默认是2000。当环形缓存溢出时发出一条消息。重写这个默认值很少需要。通常当一个回调任务出错时,环形缓存溢出消息出现。


dbPvdTableSize(size)

 记录实例名称被存储在一个过程变量目录,其是一个哈希表。哈希条目的默认数目是512。调用dbPvdTableSize能够更改这个尺寸。必须在任何dbLoad命令前调用它,并且必须是在256和65536之间的2的指数。如果一个IOC包含非常大的数据库(几千个记录),则一个更大的哈希表加速搜索记录。


scanOnceSetQueueSize(size)

scanOnce请求被放在一个环形缓存中。这个命令可以用于为这个环形缓存设置尺寸。默认是1000。重写这个默认值应该很少需要。通常当scanOnce任务出错时这个环形缓存溢出消息出现。


errlogInit(buffersize) errlogInit2(buffersize, maxMessageSize)

这些命令能够为errlog消息队列增加(但不能减少)默认缓存和最大消息尺寸。默认缓存尺寸是1280个字节,最大消息尺寸默认为256个字节。

initHooks

inithooks功能允许应用程序函数在ioc初始化过程中各种状态下被调用。这些状态在initHooks.h中被调用,它包含以下定义:

typedef enum {
    initHookAtIocBuild = 0,         / * Start of iocBuild/iocInit commands  */
    initHookAtBeginning,
    initHookAfterCallbackInit,
    initHookAfterCaLinkInit,
    initHookAfterInitDrvSup,
    initHookAfterInitRecSup,
    initHookAfterInitDevSup,
    initHookAfterInitDatabase,
    initHookAfterFinishDevSup,
    initHookAfterScanInit,
    initHookAfterInitialProcess,
    initHookAfterCaServerInit,
    initHookAfterIocBuilt,          / * End of iocBuild command  */

    initHookAtIocRun,               / * Start of iocRun command  */
    initHookAfterDatabaseRunning,
    initHookAfterCaServerRunning,
    initHookAfterIocRunning,        / * End of iocRun/iocInit commands  */

    initHookAtIocPause,             / * Start of iocPause command  */
    initHookAfterCaServerPaused,
    initHookAfterDatabasePaused,
    initHookAfterIocPaused,         / * End of iocPause command  */

/ * Deprecated states, provided for backwards compatibility.
  * These states are announced at the same point they were before,
  * but will not be repeated if the IOC gets paused and restarted.
  */
    initHookAfterInterruptAccept,   / * After initHookAfterDatabaseRunning  */
    initHookAtEnd,                  / * Before initHookAfterIocRunning  */
}initHookState;

typedef void ( *initHookFunction)(initHookState state);
int initHookRegister(initHookFunction func);
const char  *initHookName(int state);

在iocInit达到所需状态前被注册的任何函数将在它达到那个状态时被调用。initHookName函数返回这个传递给它的state的用于打印的静态字符串表示。以下框架代码展示了如何使用这个功能:

static initHookFunction myHookFunction;

int myHookInit(void)
{
  return(initHookRegister(myHookFunction));
}

static void myHookFunction(initHookState state)
{
  switch(state) {
    case initHookAfterInitRecSup:
      ...
      break;
    case initHookAfterInterruptAccept:
      ...
      break;
    default:
      break;
  }
}

可以注册任意数目的函数。

环境变量

iocCore使用的各种环境变量:

EPICS_CA_ADDR_LIST
EPICS_CA_AUTO_ADDR_LIST
EPICS_CA_CONN_TMO
EPICS_CAS_BEACON_PERIOD
EPICS_CA_REPEATER_PORT
EPICS_CA_SERVER_PORT
EPICS_CA_MAX_ARRAY_BYTES
EPICS_TS_NTP_INET
EPICS_IOC_LOG_PORT
EPICS_IOC_LOG_INET

解释EPICS_CA_...和EPICS_CAS_..变量见EPICS通道访问参考手册。解释EPICS_IOC_LOG_..变量见"iocLogClient"(要被添加)。EPICS_TS_NTP_INET只在VxWorks和TRMES上使用,它在那里设置网络时间协议服务器的地址。如果它未被定义,IOC使用启动服务器作为它的NTP服务器。

能够通过epicsEnvSet命令或者在VxWorks上使用putenv设置这些变量。例如:

epicsEnvSet("EPICS_CA_CONN_TMO,"10")

所有epicsEnvSet命令应该在iocCore被装载后并且在任何dbLoad命令前被发出。

以下命令能够发送给iocsh:

epicsPrtEnvParams:这只显示由iocCore使用的环境变量。

epicsEnvShow: 这显示在你系统上所有的环境变量。

初始化日志

初始化日志系统。详见"IOC Error Logging"章节。以下能够用于指示日志客户端使用一个特定的主机日志服务器。

epicsEnvSet("EPICS_IOC_LOG_PORT", "<port>")
epicsEnvSet("EPICS_IOC_LOG_INET", "<inet addr>")

必须在装载了iocCore后立即给出这些命令。

要启动日志,你必须发出这个命令:

iocLogInit

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值