EPICS-- asyn模块-- asynDriver--2 标准的基于寄存器的接口

一、介绍

这部分描述基于寄存器设备的接口。为以下提供了支持:

  • Int32:以32位整数出现的寄存器。
  • Int64:以64位整数出现的寄存器。
  • UInt32Digital:以32位无符号整数出现的寄存器,并且掩码可用于寻址特定的位。
  • Float64:以双精度浮点出现的寄存器。
  • Int8Array:8位整数的数组。
  • Int16Array:16位整数的数组。
  • Int32Array:32位整数的数组。
  • Int64Array:64位整数的数组。
  • Float32Array:单精度浮点的数组。
  • Float64Array:双精度浮点的数组。
  • Enum:字符串,整数值和整数严重性的数组。
  • GenericPointer:void * 指针。

注意:硬件可以注册更小的尺寸,例如16位寄存器。标准接口仍然可以设置未用位为0。

对于所有这些接口,提供了一个默认实现和一个同步实现。我们使用Int32作为一个示例。

1) asynInt32:一个带有以下方法的接口:read, write, getBounds, registerIngterrupt和cancelInterruptUser。

2) asynInt32Base:一个由实现了asynInt32的驱动程序实现的接口。它也有一个那些的实现:

  • 注册这个asynInt32接口
  • 有用于read, write和getBounds的默认方法。在被传递给初始化的接口中一个空方法被一个asynInt32Base实现的方法替代。
  • 实现了registerInterruptUser和cancelInterruptUser。调用者应该把这些方法留空,因为asynIntBase总是用它的实现替代这些方法。

实现了asynInt32的驱动程序通常调用asynInt32Base:initialize。它实现了registerInterruptUser和cancelInterruptUser。如果驱动程序提供中断支持,它必须:

  • 调用pasynInt32Base->initialize
  • 调用pasynManager->registerInterruptSource
  • 与asynManager交互,调用已经注册了asynInt32Base:registerInterruptUser的用户。驱动程序在有新数据可用时调用用户。

asyn/testEpicsApp/src/int32Driver.c提供了一个如何为中断提供支持的示例。

3) asynInt32SyncIO:一个asynInt32的同步接口。

二、addr--它对基于寄存器的接口意味着什么?

底层基于寄存器的驱动程序通常是多设备的。addr的含义是:

  • Int32:驱动程序支持一个Int32值的数组。addr选择一个数组元素。例如,一个16通道ADC支持addr从0到15。
  • Int64:驱动程序支持一个Int64值的数组。addr选择一个数组元素。
  • Int8Array:每个addr是一个Int8值的数组。
  • Int16Array:每个addr是一个Int16值的数组。
  • Int32Array:每个addr是一个Int32值的数组。
  • Int64Array:每个addr是一个Int64值的数组。
  • Float64:驱动程序支持一个Float64值的数组。addr选择一个数组元素。
  • Float32Array:每个addr是一个Float32值的数组。
  • Float64Array:每个addr是一个Float64值的数组。
  • UInt32Digital:驱动程序支持一个UInt32值的数组。addr选择一个数组元素。例如,一个128位数字I/O模块以一个4个UInt32寄存器出现。

三、示例驱动程序

两个实现并且使用这个接口的驱动程序示例是:

  • 模拟到数字转换器:一个示例是一个16通道ADC。驱动程序实现了接口asynCommon和asynInt32。它使用接口asynInt32Base。它可以调用asynManager:interruptStart和asynManager:interruptEnd来支持中断。它可以使用pasynUser->reason和addr来确定要调用哪个回调。asyn/testEpicsApp/int32Driver.c是一个如何实现一个实现了asynInt32和asynFloat64的驱动程序的软示例。
  • 数字I/O模块:一个示例是一个64位数字输入和数字输出模块。这个驱动程序实现了接口asynCommon和asynUInt32Digital。它使用了接口asynUInt32DigitalBase。它可以调用asynManager:interruptStart和asynManager:interruptEnd来支持中断。它可以使用reason,mask和addr来决定要调用哪些回调。asyn/testEpicsApp/uintDigitalDriver.c是一个实现了asynUInt32Digital的驱动程序的软示例。

四、asynInt32XX(XX=32或64)

asynIntXX描述了由使用整数用于与设备进行通信的驱动程序实现的方法。

typedef void (*interruptCallbackInt32)(void *userPvt, asynUser *pasynUser, 
                                       epicsInt32 data);
typedef struct asynInt32Interrupt {
    int addr;
    asynUser *pasynUser;
    interruptCallbackInt32 callback;
    void *userPvt;
} asynInt32Interrupt;
#define asynInt32Type "asynInt32"
typedef struct asynInt32 {
    asynStatus (*write)(void *drvPvt, asynUser *pasynUser, epicsInt32 value);
    asynStatus (*read)(void *drvPvt, asynUser *pasynUser, epicsInt32 *value);
    asynStatus (*getBounds)(void *drvPvt, asynUser *pasynUser,
                           epicsInt32 *low, epicsInt32 *high);
    asynStatus (*registerInterruptUser)(void *drvPvt,asynUser *pasynUser,
                           interruptCallbackInt32 callback, void *userPvt,
                           void **registrarPvt);
    asynStatus (*cancelInterruptUser)(void *drvPvt, asynUser *pasynUser,
                    void *registrarPvt);
} asynInt32;

/* 
   asynInt32Base做以下事情:
   为asynInt32调用registerInterface。
   提供所有方法的默认实现。
   可以直接调用registerInterruptUser和cancelInterruptUser,而不是通过queueRequest。
*/

#define asynInt32BaseType "asynInt32Base"
typedef struct asynInt32Base {
    asynStatus (*initialize)(const char *portName,
                            asynInterface *pint32Interface);
} asynInt32Base;
epicsShareExtern asynInt32Base *pasynInt32Base;

asynIntXX

write 写一个整数到设备
read 从设备读取一个整数
getBounds 获取范围。例如,一个16位ADC可以设置low=-32768和high=32767
registerInterruptUser 注册一个当新数据可用时将被调用的回调。因为可以直接调用它,而不是通过一个queueRequest,这个方法一定不能阻塞。
cancelInterruptUser 取消一个回调。因为能够直接调用它,而不是通过queueRequest,这个方法一定不能阻塞。

asynIntXXBase是一个接口和相关联代码,实现了接口asynIntXX的驱动程序使用它。asynInt32XXXBase提供了处理registerInterruptUser/cancelInterruptUser的代码。驱动程序必须自己通过对asynManager:interruptStart和asynManager:interruptEnd的调用调用回调。

asynIntXXBase

initialize

在一个驱动程序调用registerPort后,它可以调用

pasynIntXXBase->initialize(...

在这个asynInterface中任何空方法被默认实现替代。

每个方法的默认实现做实现事情:

asynIntXX

write 报告一个错误"write it not supported"并且返回asynError
read 报告一个错误"read it not supported"并且返回asynError
getBounds 报告一个错误"getBounds it not supported"并且返回asynError
registerInterruptUser 注册一个中断回调
cancelInterruptUser 取消这个回调

五、asynIntXXSyncIO(XX=32或64)

asynIntXXSyncIO描述一个asynInt32XX的同步接口。调用它的代码必须愿意阻塞。

#define asynInt32SyncIOType "asynInt32SyncIO"
typedef struct asynInt32SyncIO {
    asynStatus (*connect)(const char *port, int addr,
                          asynUser **ppasynUser, const char *drvInfo);
    asynStatus (*disconnect)(asynUser *pasynUser);
    asynStatus (*write)(asynUser *pasynUser, epicsInt32 value,double timeout);
    asynStatus (*read)(asynUser *pasynUser, epicsInt32 *pvalue,double timeout);
    asynStatus (*getBounds)(asynUser *pasynUser,
                    epicsInt32 *plow, epicsInt32 *phigh);
    asynStatus (*writeOnce)(const char *port, int addr,
                    epicsInt32 value,double timeout, const char *drvInfo);
    asynStatus (*readOnce)(const char *port, int addr,
                    epicsInt32 *pvalue,double timeout, const char *drvInfo);
    asynStatus (*getBoundsOnce)(const char *port, int addr,
                    epicsInt32 *plow, epicsInt32 *phigh,const char *drvInfo);
} asynInt32SyncIO;
epicsShareExtern asynInt32SyncIO *pasynInt32SyncIO;

asynIntXXSyncIO

connect 连接一个端口和地址,返回一个指向asynUser的指针。
disconnect 断开。这释放由connect分配的所有资源
write 调用pasynIntXX->write并且等待这个操作结束或超时
read 调用pasynIntXX->read并且等待这个操作结束或超时
getBounds 调用pasynIntXX->getBounds并且等待这个操作结束或者超时
writeOnce 这进行一次连接,write,断开。
readOnce 这进行一次连接,read,断开。
getBoundsOnce 这进行一次连接,getBounds,断开。

六、asynUInt32Digital

asynUInt32Digital描述了通过一个Int32寄存器的比特位进行通信的方法。

typedef enum {
    interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth
} interruptReason;

typedef void (*interruptCallbackUInt32Digital)(void *userPvt, 
                 asynUser *pasynUser, epicsUInt32 data);
typedef struct asynUInt32DigitalInterrupt {
    epicsUInt32 mask;
    int addr;
    asynUser *pasynUser;
    interruptCallbackUInt32Digital callback;
    void *userPvt;
} asynUInt32DigitalInterrupt;
#define asynUInt32DigitalType "asynUInt32Digital"
typedef struct asynUInt32Digital {
    asynStatus (*write)(void *drvPvt, asynUser *pasynUser,
         epicsUInt32 value, epicsUInt32 mask);
    asynStatus (*read)(void *drvPvt, asynUser *pasynUser,
        epicsUInt32 *value, epicsUInt32 mask);
    asynStatus (*setInterrupt)(void *drvPvt, asynUser *pasynUser,
        epicsUInt32 mask, interruptReason reason);
    asynStatus (*clearInterrupt)(void *drvPvt, asynUser *pasynUser,
        epicsUInt32 mask);
    asynStatus (*getInterrupt)(void *drvPvt, asynUser *pasynUser,
        epicsUInt32 *mask, interruptReason reason);
    asynStatus (*registerInterruptUser)(void *drvPvt, asynUser *pasynUser,
        interruptCallbackUInt32Digital callback,void *userPvt,epicsUInt32 mask,
        void **registrarPvt);
    asynStatus (*cancelInterruptUser)(void *drvPvt, asynUser *pasynUser,
                    void *registrarPvt);
} asynUInt32Digital;

/* 
   asynUInt32DigitalBase做了以下方法:
   为asynUInt32Digital调用registerInterface。
   实现了registerInterruptUser和cancelInterruptUser
   提供了所有方法的默认实现。
   registerInterruptUser和cancelInterruptUser可以被直接调用,而不是通过queueReqeust。
*/

#define asynUInt32DigitalBaseType "asynUInt32DigitalBase"
typedef struct asynUInt32DigitalBase {
    asynStatus (*initialize)(const char *portName,
                            asynInterface *pasynUInt32DigitalInterface);
} asynUInt32DigitalBase;
epicsShareExtern asynUInt32DigitalBase *pasynUInt32DigitalBase;

asynUInt32Digital

write 用在value中相应位修改由mask指定的位
read 读取由mask指定的位到值。value的其它位将被设置为0
setInterrupt 为reason设置由mask指定的位到中断
clearInterrupt 清除由mask指定的中断位
getInterrupt 置位为reason启动的mask的每一位。
registerInterruptUser 注册一个回调,当驱动程序探测到由mask指定的任何位中一个变化时,调用这个回调。由于它能够被直接调用,而不是通过queueRequest,这个方法一定不能阻塞。
cancelInterruptUser 取消这个注册的回调。由于它能够被直接调用,而不是通过queueRequest,这个方法一定不能阻塞。

asynUInt32DigitalBase是一个接口和相关联代码,它被实现了接口asynUInt32Digital的驱动程序使用。asynUInt32DigitalBase提供了实现了registerInterruptUser和cancelInterruptUser的代码。

asynUInt32DigitalBase

initialize

在一个驱动程序调用registerPort后,它可以调用

pasynUInt32DigitalBase->initialize(...

在asynInterface中任何空方法被默认实现替代。

每个方法的默认实现做以下事情:

asynUInt32Digital

write 报告一个错误"write is not supported"并且返回一个asynError。
read 报告一个错误"read is not supported"并且返回一个asynError。
setInterrupt 报告一个错误"setInterrupt is not supported"并且返回一个asynError。
clearInterrupt 报告一个错误"clearInterrupt is not supported"并且返回一个asynError。
getInterrupt 报告一个错误"getInterrupt is not supported"并且返回一个asynError。
registerInterruptUser 注册一个interrupt用户。底层驱动程序必须通过对asynManager:interruptStart和asynManager:interruptEnd的调用调用这个注册的回调。
cancelInterruptUser 取消这个回调。

七、asynUInt32DigitalSyncIO

asynUInt32DigitalSyncIO描述了一个asynUInt32Digital的同步接口。调用它的代码必须愿意阻塞。

connect 连接到一个端口和地址,返回一个指向一个asynUser结构体的指针
disconnect 断开连接。这释放了由connect分配的所有资源。

write

调用pasynUInt32Digital->write并且等待这个操作结束或超时。
read 调用pasynUInt32Digital->read并且等待这个操作结束或超时。
setInterrupt 调用pasynUInt32Digital->setInterrupt并且等待这个操作结束或超时。
clearInterrupt 调用pasynUInt32Digital->clearInterrupt并且等待这个操作结束或超时。
getInterrupt 调用pasynUInt32Digital->getInterrupt并且等待这个操作结束或超时。
writeOnce, ..., getInterruptOnce 进行一次连接,(write, ..., getInterrupt),和断开连接。

八、asynFloat

asynFloat描述了通过IEEE双精度浮点值进行通信的方法。

typedef void (*interruptCallbackFloat64)(void *userPvt, asynUser *pasynUser,
            epicsFloat64 data);
typedef struct asynFloat64Interrupt {
    asynUser *pasynUser;
    int addr;
    interruptCallbackFloat64 callback;
    void *userPvt;
} asynFloat64Interrupt;
#define asynFloat64Type "asynFloat64"
typedef struct asynFloat64 {
    asynStatus (*write)(void *drvPvt, asynUser *pasynUser, epicsFloat64 value);
    asynStatus (*read)(void *drvPvt, asynUser *pasynUser, epicsFloat64 *value);
    asynStatus (*registerInterruptUser)(void *drvPvt, asynUser *pasynUser,
        interruptCallbackFloat64 callback, void *userPvt,void **registrarPvt);
    asynStatus (*cancelInterruptUser)(void *drvPvt, asynUser *pasynUser,
                    void *registrarPvt);
} asynFloat64;

/* asynFloat64Base做以下事情:
   为asynFloat64调用registerInterface.
   提供所有方法的默认实现。
   registerInterruptUser和cancelInterfaceUser可以直接被调用,而不是通过queueRequest。
*/

#define asynFloat64BaseType "asynFloat64Base"
typedef struct asynFloat64Base {
    asynStatus (*initialize)(const char *portName,
                            asynInterface *pasynFloat64Interface);
} asynFloat64Base;
epicsShareExtern asynFloat64Base *pasynFloat64Base;

asynFloat64 

write 写一个值
read 读一个值
registerInterruptUser 注册一个回调,当新值可用时,它被调用。由于它可以被直接调用,而不是通过queueRequest,这个方法一定不能阻塞。
cancelInterruptUser 取消这个回调。由于它可以被直接调用,而不是通过queueRequest,这个方法一定不能阻塞。

asynFloat64Base

initialize

在一个驱动程序调用registerPort后,它可以调用:

pasynFloat64Base->initialize(...

在asynInterface中任何空方法被默认实现替代。

每个方法的默认实现做以下事情:

asynFloat64

write 报告一个错误"write is not supported"并且返回asynError
read 报告一个错误"read is not supported"并且返回asynError
registerInterruptUser 注册这个中断用户。底层驱动程序必须通过对asynManager:interruptStart和asynManager:interruptEnd的调用调用这个注册的回调。
cancelInterruptUser 取消这个回调

九、asynFloat64SyncIO

asynFloat64SyncIO描述一个asynFloat64的同步接口。调用它的代码必须愿意阻塞。

#define asynFloat64SyncIOType "asynFloat64SyncIO"
typedef struct asynFloat64SyncIO {
    asynStatus (*connect)(const char *port, int addr,
                       asynUser **ppasynUser, const char *drvInfo);
    asynStatus (*disconnect)(asynUser *pasynUser);
    asynStatus (*write)(asynUser *pasynUser,epicsFloat64 value,double timeout);
    asynStatus (*read)(asynUser *pasynUser,epicsFloat64 *pvalue,double timeout);
    asynStatus (*writeOnce)(const char *port, int addr,
                       epicsFloat64 value,double timeout,const char *drvInfo);
    asynStatus (*readOnce)(const char *port, int addr,
                       epicsFloat64 *pvalue,double timeout,const char *drvInfo);
} asynFloat64SyncIO;
epicsShareExtern asynFloat64SyncIO *pasynFloat64SyncIO;

asynFloat64SyncIO

connect 连接到一个端口和地址,返回指向一个asynUser结构体的指针
disconnect 断开连接。它释放由connect分配的所有资源
write 调用pasynFloat64->write并且等待这个操作结束或者超时
read 调用pasynFloat64->read并且等待这个操作结束或者超时
writeOnce 这进行一次连接,write并且断开
readOnce 这进行一次连接,read并且断开

十、asynXXXArray(XXX=Int8, Int16, Int32, Int64, Float32或Float64)

asynXXXArray描述了通过8,16,32或64位整数,或者32或64位IEEE浮点值进行通信的方法。

typedef void (*interruptCallbackXXXArray)(
              void *userPvt, asynUser *pasynUser,
              epicsXXX *data, size_t nelements);
typedef struct asynXXXArrayInterrupt {
    asynUser *pasynUser;
    int addr;
    interruptCallbackXXXArray callback;
    void *userPvt;
} asynXXXArrayInterrupt;
#define asynXXXArrayType "asynXXXArray"
typedef struct asynXXXArray {
    asynStatus (*write)(void *drvPvt, asynUser *pasynUser,
                       epicsXXX *value, size_t nelements);
    asynStatus (*read)(void *drvPvt, asynUser *pasynUser,
                       epicsXXX *value, size_t nelements, size_t *nIn);
    asynStatus (*registerInterruptUser)(void *drvPvt, asynUser *pasynUser,
         interruptCallbackXXXArray callback,
         void *userPvt,void **registrarPvt);
    asynStatus (*cancelInterruptUser)(void *drvPvt, asynUser *pasynUser,
                    void *registrarPvt);
} asynXXXArray;

/* 
   asynXXXArrayBase做以下事情:
   为asynXXXArray调用regisgterInterrface。
   提供了所有访问的默认实现。
   registerInterruptUser和cancelInterruptUser可以被直接调用,而不是通过queueRequest。
*/

#define asynXXXArrayBaseType "asynXXXArrayBase"
typedef struct asynXXXArrayBase {
    asynStatus (*initialize)(const char *portName,
                            asynInterface *pXXXArrayInterface);
} asynXXXArrayBase;
epicsShareExtern asynXXXArrayBase *pasynXXXArrayBase;

asynXXXArray

write 写一个值的数组
read 读取一个值的数组
registerInterruptUser 注册一个在新数据可用时被调用的回调。
cancelInterruptUser 取消回调

asynXXXArrayBase

initialize

在一个驱动程序调用registerPort后,它可以调用:

pasynXXXArrayBase->initialize(...

在asynInterface中任何空方法被默认实现替代

每个方法的默认实现做以下事情:

asynXXXArrayBase

write 报告一个错误"write is not supported"并且返回asynError
read 报告一个错误"read is not supported"并且返回asynError
registerInterruptUser 注册一个中断回调。
cancelInterruptUser 取消这个中断

十一、asynXXXArraySyncIO

asynXXXArraySyncIO描述一个asynXXXArray的同步接口。调用它的代码必须愿意阻塞。

#define asynXXXArraySyncIOType "asynXXXArraySyncIO"
typedef struct asynXXXArraySyncIO {
    asynStatus (*connect)(const char *port, int addr,
                          asynUser **ppasynUser, const char *drvInfo);
    asynStatus (*disconnect)(asynUser *pasynUser);
    asynStatus (*write)(asynUser *pasynUser, epicsXXX *pvalue,size_t nelem,double timeout);
    asynStatus (*read)(asynUser *pasynUser, epicsXXX *pvalue,size_t nelem,size_t *nIn,double timeout);
    asynStatus (*writeOnce)(const char *port, int addr,
                    epicsXXX *pvalue,size_t nelem,double timeout, const char *drvInfo);
    asynStatus (*readOnce)(const char *port, int addr,
                    epicsXXX *pvalue,size_t nelem,size_t *nIn,double timeout, const char *drvInfo);
} asynXXXArraySyncIO;
epicsShareExtern asynXXXArraySyncIO *pasynXXXArraySyncIO;

asynXXXArraySyncIO 

connect 连接到一个端口和地址,返回一个指向一个asynUser的指针
disconnect 断开连接。这释放connect分配的所有资源。
write 调用pasynXXXArray->write并且等待这个操作结束或者超时
read 调用pasynXXXArray->read并且等待这个操作结束或者超时
writeOnce 这进行一次连接,write并且断开连接
readOnce 这进行一次连接,read并且断开连接
getBoundsOnce 这进行一次连接,getBounds并且断开连接

十二、asynEnum

asynEnum描述由驱动实现的为设备定义枚举字符串,值以及严重性的方法。

这个接口由驱动程序使用来为EPICS bi,bo,mbbi和mbbo记录设置枚举字符串和值。strings[]用于定义在bi和bo记录中ZNAM和ONAM字段,以及在mbbi和mbbo记录中ZRST,ONST,...FFST字段。由于对于bi和bo记录整数0和1对应ZNAM和ONAM状态,对于bi和bo记录忽略整数values[]。整数values[]用于为mbbi和mbbo记录分配ZRVL,ONVL,...,FFVL字段。整数severities[]用于设置bi和bo记录的ZSV和OSV字段和mbbi和mbbo记录的ZRSV,ONSV,...,FFSV。在write()和read()函数中的nelements参数由客户端使用来指定strings[], values[]和severities[]数组的维度。驱动程序一定不能访问这些数组超过元素nElements-1。在read()中nIn参数被驱动程序使用来设置枚举字符串,值和严重性的实际数目。asynEnum接口没有对字符串施加大小限制。但在bi,bo,mbbo和mbbi记录中字符串字段当前被限制于26个字符。

客户端必须确保在read()函数中strings[]中传递的char *指针要么被设置成NULL或者已经由malloc()分配。如果一个string指针包含一个非NULL值,驱动程序read()函数必须首先调用free()。在复制当前枚举字符串值到它们前,驱动程序必须接着使用malloc()分配这些字符串。

typedef void (*interruptCallbackEnum)
              void *userPvt, asynUser *pasynUser,
              char *strings[], int values[], int severities[], size_t nelements);
typedef struct asynEnumInterrupt {
    asynUser *pasynUser;
    int addr;
    interruptCallbackEnum callback;
    void *userPvt;
} asynEnumInterrupt;
#define asynEnumType "asynEnum"
typedef struct asynEnum {
    asynStatus (*write)(void *drvPvt, asynUser *pasynUser,
                       char *strings[], int values[], int severities[], size_t nelements);
    asynStatus (*read)(void *drvPvt, asynUser *pasynUser,
                       char *strings[], int values[], int severities[], size_t nelements, size_t *nIn);
    asynStatus (*registerInterruptUser)(void *drvPvt, asynUser *pasynUser,
             interruptCallbackEnum callback, void *userPvt,
             void **registrarPvt);
    asynStatus (*cancelInterruptUser)(void *drvPvt, asynUser *pasynUser,
             void *registrarPvt);
} asynEnum;

/* asynEnumBase does the following:
   asynEnumBase做以下事情:
   为asynEnum调用registerInterface.
   实现了registerInterruptUser和cancelInterruptUser
   提供了所有方法的默认实现。
   registerInterruptUser和cancelInterruptUser可以被直接调用,而不是通过queueRequest。
*/

#define asynEnumBaseType "asynEnumBase"
typedef struct asynEnumBase {
    asynStatus (*initialize)(const char *portName,
                            asynInterface *pEnumInterface);
} asynEnumBase;
epicsShareExtern asynEnumBase *pasynEnumBase;

asynEnum

write 写枚举字符串,枚举值和枚举严重性到驱动程序
read 从驱动程序读取枚举字符串,枚举值和枚举严重性
registerInterruptUser 注册一个回调,当有新的枚举字符串,值和严重性时,将调用它。由于它可以被直接调用,而不是通过queueRequest,这个方法一定不能阻塞。
cancelInterruptUser 取消这个调用。由于它可以被直接调用,而不是通过queueRequest,这个方法一定不能阻塞。

asynEnumBase是一个接口和相关联代码,它被实现了asynEnum接口的驱动程序使用。asynEnumBase提供了处理registerInterruptUser/cancelInterruptUser的代码。这个驱动程序必须它自己通过对asynManager:interruptStart和asynManager:interruptEnd的调用调用这些回调。

asynEnumBase

initialize

在一个驱动程序调用registerPort后,它可以调用

pasynEnumBase->initialize(...

在asynInterface中的任何空方法被默认实现替代。

每个方法的默认实现做以下事情:

asynEnum

write 报告一个错误"write is not supported"并且返回asynError
read 报告一个错误"read is not supported"并且返回asynError
registerInterruptUser 注册一个中断回调
cancelInterruptUser 取消这个回调

十三、asynEnumSyncIO

asynEnumSyncIO描述一个asynEnum的同步接口。调用它的代码将愿意阻塞。

#define asynEnumSyncIOType "asynEnumSyncIO"
typedef struct asynEnumSyncIO {
    asynStatus (*connect)(const char *port, int addr, 
                          asynUser **ppasynUser, const char *drvInfo);
    asynStatus (*disconnect)(asynUser *pasynUser);
    asynStatus (*write)(asynUser *pasynUser, char *strings[], int values[], int severities[], 
                       size_t nElements, double timeout);
    asynStatus (*read)(asynUser *pasynUser, char *string[], int values[],  int severities[], 
                       size_t nElements, size_t *nIn, double timeout);
    asynStatus (*writeOnce)(const char *port, int addr, char *strings[], int values[],  int severities[], 
                           size_t nElements, double timeout, const char *drvInfo);
    asynStatus (*readOnce)(const char *port, int addr, char *strings[], int values[],  int severities[], 
                           size_t nElements, size_t *nIn, double timeout, const char *drvInfo);
} asynEnumSyncIO;
epicsShareExtern asynEnumSyncIO *pasynEnumSyncIO;

asynEnumSyncIO

connect 连接一个端口和地址,返回一个指向一个asynUser的指针
disconnect 断开连接。这释放了由connect分配的所有资源
write 调用pasynEnum->write并且等待这个操作结束或超时
read 调用pasynEnum->read并且等待这个操作结束或超时
writeOnce 这进行一次连接,写和断开连接
readOnce 这进行一次连接,读和断开连接
getBoundsOnce 这进行一次连接,getBounds和断开连接

十四、asynGenericPointer

asynGenericPointer描述了一个通过void*指针进行通信的方法。asyn客户端和端口驱动程序必须确认正在被指向的对象的类型是一致的。

typedef void (*interruptCallbackGenericPointer)(void *userPvt, asynUser *pasynUser,
            void *pdata);
typedef struct asynGenericPointerInterrupt {
    asynUser *pasynUser;
    int addr;
    interruptCallbackGenericPointer callback;
    void *userPvt;
} asynGenericPointerInterrupt;
#define asynGenericPointerType "asynGenericPointer"
typedef struct asynGenericPointer {
    asynStatus (*write)(void *drvPvt, asynUser *pasynUser, void *pvalue);
    asynStatus (*read)(void *drvPvt, asynUser *pasynUser, void *pvalue);
    asynStatus (*registerInterruptUser)(void *drvPvt, asynUser *pasynUser,
        interruptCallbackGenericPointer callback, void *userPvt,void **registrarPvt);
    asynStatus (*cancelInterruptUser)(void *drvPvt, asynUser *pasynUser,
                    void *registrarPvt);
} asynGenericPointer;

/* 
   asynGenericPointerBase做以下事情:
   为asynGenericPointer调用registerInterface.
   实现了registerInterruptUser和cancelInterruptUser。
   提供了所有方法的默认实现。
   registerInterruptUser和cancelInterruptUser可以被直接调用,而不是通过queueRequest。
*/

#define asynGenericPointerBaseType "asynGenericPointerBase"
typedef struct asynGenericPointerBase {
    asynStatus (*initialize)(const char *portName,
                            asynInterface *pasynGenericPointerInterface);
} asynGenericPointerBase;
epicsShareExtern asynGenericPointerBase *pasynGenericPointerBase;

asynGenericPointer

write 写一个值
read 读一个值
registerInterruptUser 注册一个回调,当新数据可用时,调用它。由于它可以被直接调用,而不是通过一个queueRequest,这个方法一定不能阻塞。
cancelInterruptUser 取消这个回调。由于它可以被直接调用,而不是通过一个queueRequest,这个方法一定不能阻塞。

asynGenericPointerBase

initialize

在驱动程序调用registerPort后,它可以调用:

pasynGenericPointBase->initialize(...

在asynInterface中任何空方法被默认实现替代。

每个方法的默认实现做以下事情:

write 报告一个错误"write is not supported"并且返回asynError
read 报告一个错误"read is not supported"并且返回asynError
registerInterruptUser 注册这个中断用户。底层驱动程序必须通过对asynManager:interruptStart和asynManager:interruptEnd的调用调用这个注册的回调。
cancelInterruptUser 取消这个回调

十五、asynGenericPointerSyncIO

asynGenericPointerSyncIO描述asynGenericPointer的同步接口。调用它的代码必须愿意阻塞。

#define asynGenericPointerSyncIOType "asynGenericPointerSyncIO"
typedef struct asynGenericPointerSyncIO {
    asynStatus (*connect)(const char *port, int addr,
                       asynUser **ppasynUser, const char *drvInfo);
    asynStatus (*disconnect)(asynUser *pasynUser);
    asynStatus (*write)(asynUser *pasynUser,void *pvalue,double timeout);
    asynStatus (*read)(asynUser *pasynUser,void *pvalue,double timeout);
    asynStatus (*writeRead)(asynUser *pasynUser,void *pwrite_buffer,void *pread_buffer,double timeout);
    asynStatus (*writeOnce)(const char *port, int addr,
                       void *pvalue,double timeout,const char *drvInfo);
    asynStatus (*readOnce)(const char *port, int addr,
                       void *pvalue,double timeout,const char *drvInfo);
    asynStatus (*writeReadOnce)(const char *port, int addr,
                       void *pwrite_buffer,void *pread_buffer,double timeout,const char *drvInfo);
} asynGenericPointerSyncIO;
epicsShareExtern asynGenericPointerSyncIO *pasynGenericPointerSyncIO;

asynGenericPointerSyncIO

connect 连接一个端口和地址,返回一个指向一个asynUser结构体的指针
disconnect 断开连接。这释放由connect分配的所有资源
write 调用pasynGenericPointer->write并且等待这个操作结束或超时
read 调用pasynGenericPointer->read并且等待这个操作结束或超时
writeRead 调用pasynGenericPointer->write,接着pasynGenericPointer->read并且等待这些操作结束或超时
writeOnce 这进行一次连接,写和断开连接
readOnce 这进行一次连接,读和断开连接
writeReadOnce 这进行一次连接,writeRead和断开连接

猜你喜欢

转载自blog.csdn.net/yuyuyuliang00/article/details/127881700
今日推荐