一、概述
为了将EPICS接口到硬件,没有必要创建驱动程序支持模块。对于简单的硬件,设备支持就足够了。目前,大多数硬件支持两者都有。这是有历史原因的。在EPICS出现之前就有GTACS。在从GTACS到EPICS的变化过程中,记录支持发生了巨大变化。为了保留所有现有硬件支持,GTACS驱动程序的使用没有任何变化。创建设备支持层只是为了保护现有的驱动程序形成记录支持更改。由于EPICS现在同时拥有设备和驱动程序支持,问题就出现了:什么时候需要驱动程序支持,什么时候不需要?让我们给出创建驱动程序的几个理由。
- 硬件实际上是一个子网,例如GPIB。在这种情况下,应该为访问子网提供驱动程序。除了可能发出错误消息外,没有理由让驱动程序意识到EPICS。
- 硬件很复杂。在这种情况下,提供驱动程序支持有助于软件模块化。Allen Bradley driver就是一个很好的例子,它也是一个支持子网的例子。
- 由其他人维护的现有驱动程序是可用的。
- 驱动程序应该是通用的,也就是说,不绑定到EPICS。CAMAC驱动就是一个很好的例子。它被其他系统使用,比如CODA。这可能是驱动程序支持的最重要的原因。
- 对于通用设备,如GPIB, CAN, CAMAC等,应该创建一个通用的驱动层。这个通用层应该独立于EPICS和底层接口。它还应该为低级驱动程序定义一个接口。这允许替换低级接口,而不会影响IOC记录、记录支持或设备支持。
要将驱动程序连接到EPICS,唯一需要做的就是提供驱动程序支持模块,该模块可以在现有驱动程序之上分层,并为驱动程序提供数据库定义。下一节将描述驱动程序支持模块。数据库的定义在“数据库定义”一章中描述。
二、设备驱动
设备驱动程序是直接与硬件接口的模块。提供它们是为了将设备支持例程与如何与硬件接口的细节隔离开来。设备驱动程序不知道数据库记录的内部情况。因此,在记录类型和设备驱动程序之间没有必要的对应关系。例如,Allen Bradley驱动程序为许多不同类型的信号提供支持,包括模拟输入、模拟输出、二进制输入和二进制输出。
一般来说,只有设备支持例程知道如何调用设备驱动程序。由于设备支持因设备而异,设备驱动程序提供的例程集几乎完全依赖于驱动程序。唯一的要求是必须提供例程report和init。当然,设备支持例程必须知道驱动程序提供了哪些例程。
drvSup.h文件描述了驱动程序支持入口表的格式。驱动程序支持模块必须提供一个驱动程序入口表。一个例子的定义是:
static long report(int level);
static long init(void);
struct {
long number;
DRVSUPFUN report;
DRVSUPFUN init;
} drvAb={
2,
report,
init
};
epicsExportAddress(drvet,drvGpib);
上面的例子是关于Allen Bradley驱动的。它有一个相关的ascii定义:
driver(drvGpib)
由此可见,驱动程序支持模块应该提供两个EPICS可调用例程: init 和 report 。
2.1 init
这个例程没有参数,是由iocInit调用的。驱动程序需要查找并初始化它所支持的硬件。例如,Allen Bradley的init例程是:
static long init(void)
{
return(ab_driver_init());
}
2.2 report
report例程由dbior IOC测试例程调用。它负责生成一个报告,描述它在初始化时发现的硬件。它传递了一个参数level,它提示要显示多少信息。一个来自Allen Bradley的例子是:
static long report(int level)
{
return(ab_io_report(level));
}
level的指导原则如下:
- Level = 0 : 为每个设备显示一行摘要
- Level = 1 :显示更多信息
- Level = 2 :显示大量信息。甚至可以提示别人想要什么
2.3 硬件配置
硬件配置包括:
- VME / VXI地址空间
- VME中断向量级别
- 设备的具体信息
硬件链接中包含的信息提供了一些但不是全部的配置信息。特别是它没有定义VME / VXI地址和中断向量。这些附加信息就是本章中硬件配置的含义。
定义硬件配置信息的问题是EPICS尚未解决的问题。以前,配置信息是在module_type .h中定义的。许多现有的设备/驱动程序支持模块仍然使用这种方法。它不应该用于任何新的支持,原因如下:
- 没有办法为整个EPICS社区管理这个文件。
- 不允许任意的配置信息
- 用户很难确定配置信息是什么
现在很容易为每个IOC中使用的设备/驱动程序支持包含ASCII定义,这使得配置问题比以前更易于管理。以前,如果您想支持新的VME模块,则必须选择module_type .h中没有使用的地址。现在您只需要检查实际使用的模块。
由于没有EPICS定义的硬件配置规则,因此应该使用以下基本准则:
- 永远不要使用**#define来指定VME地址之类的东西。而是使用变量并分配默认值。允许在iocInit**执行之前更改默认值。最好的方法是提供一个可以从IOC启动文件调用的全局例程。注意,这些例程的所有参数都应该是以下参数之一:
int
char*
double
- 尽可能调用”设备支持库“章节中描述的例程