- asynReport(level,portName)
- asynInterposeFlushConfig(portName,addr,timeout)
- asynInterposeEosConfig(portName,addr,processIn,processOut)
- asynSetTraceMask(portName,addr,mask)
- asynSetTraceIOMask(portName,addr,mask)
- asynSetTraceInfoMask(portName,addr,mask)
- asynSetTraceFile(portName,addr,filename)
- asynSetTraceIOTruncateSize(portName,addr,size)
- asynSetOption(portName,addr,key,val)
- asynShowOption(portName,addr,key)
- asynAutoConnect(portName,addr,yesNo)
- asynSetAutoConnectTimeout(timeout)
- asynWaitConnect(portName, timeout)
- asynEnable(portName,addr,yesNo)
- asynOctetConnect(entry,portName,addr,timeout,buffer_len,drvInfo)
- asynOctetRead(entry,nread)
- asynOctetWrite(entry,output)
- asynOctetWriteRead(entry,output,nread)
- asynOctetFlush(entry)
- asynOctetSetInputEos(portName,addr,eos,drvInfo)
- asynOctetGetInputEos(portName,addr,drvInfo)
- asynOctetSetOutputEos(portName,addr,eos,drvInfo)
- asynOctetGetOutputEos(portName,addr,drvInfo)
- asynRegisterTimeStampSource(portName,functionName);
- asynUnregisterTimeStampSource(portName)
asynReport:如果指定了portName,asynReport为指定端口调用asynCommon:report,如果没有指定portName, 为所有注册的驱动程序和InterposeInterface调用asynCommon:report。
asynInterposeFlushConfig:是一个通用的interposeInterface,它为没有实现flush的底层驱动程序实现了flush。它仅发出读取请求,直到没有剩下要读的字节。timeout是用于读取请求。
asynInterposeEosConfig:是一个通用interposeInterface,它为没有实现字符串末尾处理的底层驱动程序,实现了它。
asynSetTraceMask:为指定端口和地址调用asynTrace:setTraceMask。如果portName是0长度,则全局跟踪掩码被设置。
一个掩码确定能被显示的信息类型。各种选项可是被ORed到一起。当创建一个端口时,这个掩码的默认值是:ASYN_TRACE_ERRROR。
asynSetTraceIOMask:为指定端口和地址调用asynTrace:setTraceIOMask。如果portName是0长度,则全局跟踪掩码被设置。另一个掩码,它决定打印多少消息缓存。各种选项能够被ORed到一起。创建这个端口时,这个掩码的默认值是ASYN_TRACEIO_NODATA。
asynSetTraceInfoMask:为指定端口和地址调用asynTrace:setTraceInfoMask。如果portName是0长度,则全局跟踪掩码被设置。一个掩码确定了在每条消息开头打印数目信息。不同选项可以被ORed在一起。创建一个端口时,这个掩码的默认值是ASYN_TRACEINFO_TIME。
从asyn R4-35开始,可以用以+或|连接的整数或者符号名称指定asynSetTraceMask, asynSetTraceIOMask和asynSetTraceInfoMask。空白是被允许的,但需要引号。符号名称是像在asynDriver.h中定义的宏名称,但不是区分大小写的,并且前缀ASYN_, TRACE_, TRACEIO_和TRACEINFO_是可选的。示例:
- asynSetTraceMask port,0,ASYN_TRACE_ERROR
- asynSetTraceIOMask port,0,ascii+escape
- asynSetTraceInfoMask port,0,1+port+TRACEINFO_SOURCE|ASYN_TRACEINFO_THREAD
asynSetTraceFile:asynSetTraceFile调用asynTrace:setTraceFile。按如下处理文件名:
asynSetTraceIOTruncateSize:asynSetTraceIOTruncateSize调用asynTrace:setTraceIOTruncateSize。
asynSetOption:asynSetOption调用asynCommon:setOption。
asynShowOptin:asynShowOption调用asynCommon:getOption。
asynOctetXXX命令:提供了对asynOctetSyncIO方法的shell访问。entry是标识端口,地址的字符串常量。
此处:
命令asynOctetConnect, asynOctetDisconnect, asynOctetRead, asynOctetWrite, asynOctetWriteRead, asynOctet允许从ioc shell对设备进行I/O。示例是:
以下示例展示了使用https://blog.csdn.net/yuyuyuliang00/article/details/132668739中的asyn驱动模块创建了一个端口驱动程序来测试以上列出的部分asyn诊断命令。
以下这个驱动程序的源代码:
- #include
- #include
- #include
- #include
- #include
-
- #include "cantProceed.h"
- #include "epicsStdio.h"
- #include "epicsThread.h"
- #include "iocsh.h"
-
- #include "asynDriver.h"
- #include "asynOctet.h"
- #include "asynInt32.h"
-
- #include
- #define BUFFERSIZE 4096
-
- static int VALUE = 0;
-
- typedef struct deviceBuffer{
- char buffer[BUFFERSIZE];
- size_t nchars;
- int value;
- int low;
- int high;
- }deviceBuffer;
-
- typedef struct deviceInfo{
- deviceBuffer buffer;
- int connected;
- }deviceInfo;
-
- typedef struct infoPvt{
- deviceInfo device;
- const char * portName;
- int connected;
- double delay;
- asynInterface common;
- asynInterface octet;
- asynInterface int32;
- char eos[2];
- int eoslen;
- void * pasynPvt;
- void * pasynInt32Pvt;
- }infoPvt;
-
- static int infoDriverInit(const char * portName, double delay, int noAutoConnect, int low, int high);
-
-
- /* asynCommon */
- static void report(void *drvPvt, FILE * fp, int details);
- static asynStatus connect(void * drvPvt, asynUser *pasynUser);
- static asynStatus disconnect(void *drvPvt, asynUser * pasynUser);
- static asynCommon asynC = {report, connect, disconnect};
-
- /* asynOctet */
- static asynStatus infoWrite(void *drvPvt, asynUser *pasynUser,
- const char *data, size_t numchars, size_t *nbytesTransfered);
- static asynStatus infoRead(void *drvPvt, asynUser *pasynUser,
- char *data, size_t maxchars, size_t *nbytesTransfered, int *eomReason);
- static asynStatus infoFlush(void *drvPvt, asynUser *pasynUser);
- static asynStatus setEos(void *drvPvt, asynUser *pasynUser, const char *eos, int eoslen);
- static asynStatus getEos(void *drvPvt, asynUser *pasynUser, char *eos, int eossize, int *eoslen);
- static asynOctet asynO;
-
- /* asynInt32*/
- static asynStatus intWrite(void *drvPvt, asynUser * pasynUser, epicsInt32 value);
- static asynStatus intRead(void *drvPvt, asynUser * pasynUser, epicsInt32 *value);
- static asynStatus getIntBounds(void *drvPvt, asynUser * pasynUser, epicsInt32 *low, epicsInt32 *high);
- static asynInt32 asynI32;
-
-
- static int infoDriverInit(const char * pn, double delay, int noAutoConnect, int low, int high)
- {
- infoPvt *pinfoPvt;
- char *portName;
- asynStatus status;
- size_t nbytes;
- int attributes;
-
- nbytes = sizeof(infoPvt) + strlen(pn) + 1;
- pinfoPvt = (infoPvt *)callocMustSucceed(nbytes, sizeof(char), "infoPvt");
- portName = (char *)(pinfoPvt + 1);
- strcpy(portName, pn);
-
- pinfoPvt->device.buffer.low = low;
- pinfoPvt->device.buffer.high = high;
- pinfoPvt->device.buffer.value = (low + high) / 2;
-
- pinfoPvt->portName = portName;
- pinfoPvt->delay = delay;
- pinfoPvt->common.interfaceType = asynCommonType;
- pinfoPvt->common.pinterface = (void *)&asynC;
- pinfoPvt->common.drvPvt = pinfoPvt;
-
- attributes = 0;
- if (delay > 0.0){
- attributes |= ASYN_CANBLOCK;
- }
-
- status = pasynManager->registerPort(portName, attributes, !noAutoConnect, 0, 0);
-
- if (status != asynSuccess){
- printf("infoDriverInit registerDriver failed\n");
- return 0;
- }
-
- status = pasynManager->registerInterface(portName, &pinfoPvt->common);
- if (status != asynSuccess){
- printf("infoDriverInit registerInterface failed");
- return 0;
- }
-
-
- asynO.write = infoWrite;
- asynO.read = infoRead;
- asynO.flush = infoFlush;
- asynO.setInputEos = setEos;
- asynO.getInputEos = getEos;
- pinfoPvt->octet.interfaceType = asynOctetType;
- pinfoPvt->octet.pinterface = (void *)&asynO;
- pinfoPvt->octet.drvPvt = pinfoPvt;
-
- status = pasynOctetBase->initialize(portName, &pinfoPvt->octet, 1, 1, 0);
-
- if (status == asynSuccess){
- status = pasynManager->registerInterruptSource(
- portName, &pinfoPvt->octet, &pinfoPvt->pasynPvt);
- }
-
- if (status != asynSuccess){
- printf("infoDriverInit registerInterface asynOctet failed\n");
- return 0;
- }
-
-
- asynI32.write = intWrite;
- asynI32.read = intRead;
- asynI32.getBounds = getIntBounds;
- pinfoPvt->int32.interfaceType = asynInt32Type;
- pinfoPvt->int32.pinterface = (void *)&asynI32;
- pinfoPvt->int32.drvPvt = pinfoPvt;
-
- status = pasynInt32Base->initialize(portName, &pinfoPvt->int32);
-
- if (status == asynSuccess){
- status = pasynManager->registerInterruptSource(
- portName, &pinfoPvt->int32, &pinfoPvt->pasynInt32Pvt);
- }
-
- if (status != asynSuccess){
- printf("infoDriverInit registerInterface asynInt32 failed\n");
- return 0;
- }
-
- return 0;
- }
-
- static void report(void *drvPvt, FILE *fp, int details)
- {
- infoPvt * pinfoPvt = (infoPvt *)drvPvt;
- int i,n;
-
- fprintf(fp, "infoDriver connected:%s delay = %f\n",
- pinfoPvt->connected ? "Yes": "NO",
- pinfoPvt->delay);
- }
-
-
- static asynStatus connect(void *drvPvt, asynUser * pasynUser)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- int addr;
- asynStatus status;
-
- status = pasynManager->getAddr(pasynUser, &addr);
- if (status != asynSuccess) return status;
-
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s infoDriver: connect addr %d\n",
- pinfoPvt->portName, addr);
-
- if (pinfoPvt->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s infoDriver: connect port already connected\n",
- pinfoPvt->portName);
- return asynError;
- }
-
- if (pinfoPvt->delay > 0.0){
- epicsThreadSleep(pinfoPvt->delay * 10.);
- }
- pinfoPvt->connected = 1;
- pinfoPvt->device.connected = 1;
- pasynManager->exceptionConnect(pasynUser);
-
- return asynSuccess;
- }
-
- static asynStatus disconnect(void *drvPvt, asynUser *pasynUser)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- int addr;
- asynStatus status;
-
- status = pasynManager->getAddr(pasynUser, &addr);
- if (status != asynSuccess) return status;
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s infoDriver: disconnect addr %d\n",
- pinfoPvt->portName, addr);
-
- if (!pinfoPvt->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s infoDriver: disconnect port not connected\n",
- pinfoPvt->portName);
- return asynError;
- }
-
- pinfoPvt->connected = 0;
- pinfoPvt->device.connected = 0;
- pasynManager->exceptionDisconnect(pasynUser);
-
- return asynSuccess;
- }
-
- static asynStatus infoWrite(void *drvPvt, asynUser *pasynUser,
- const char *data, size_t nchars, size_t *nbytesTransfered)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- deviceBuffer *pdeviceBuffer;
- int addr;
- asynStatus status;
-
- //printf("infoWrite: %s\n", data);
- status = pasynManager->getAddr(pasynUser, &addr);
- if(status != asynSuccess) return status;
- addr = 0;
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s initDriver: write addr %d\n",
- pinfoPvt->portName, addr);
-
- pdeviceInfo = &pinfoPvt->device;
- if (!pdeviceInfo->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s infoDriver: write %d not connected\n", pinfoPvt->portName, addr);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver:write device %d not connected",
- pinfoPvt->portName, addr);
- return asynError;
- }
-
- if (pinfoPvt->delay > pasynUser->timeout){
- if (pasynUser->timeout > 0.0) epicsThreadSleep(pasynUser->timeout);
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s initDriver write timeout\n", pinfoPvt->portName);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver write timeout", pinfoPvt->portName);
-
- return asynTimeout;
- }
-
- pdeviceBuffer = &pdeviceInfo->buffer;
- if(nchars > BUFFERSIZE) nchars = BUFFERSIZE;
- if(nchars > 0){
- memcpy(pdeviceBuffer, data, nchars);
- }
- asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, data, nchars,
- "infoWrite nchars %lu\n", (unsigned long)nchars);
- pdeviceBuffer->nchars = nchars;
- if (pinfoPvt->delay > 0.0) {
- epicsThreadSleep(pinfoPvt->delay);
- }
- *nbytesTransfered = nchars;
- return status;
- }
-
- static asynStatus infoRead(void *drvPvt, asynUser *pasynUser, char *data,
- size_t maxchars, size_t *nbytesTransfered,int *eomReason)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- deviceBuffer *pdeviceBuffer;
- char *pfrom, *pto;
- char thisChar;
- size_t nremaining;
- size_t nout = 0;
- int addr;
- asynStatus status;
-
- if (eomReason) *eomReason = 0;
- if (nbytesTransfered) *nbytesTransfered = 0;
- status = pasynManager->getAddr(pasynUser, &addr);
- addr = 0;
-
- asynPrint(pasynUser, ASYN_TRACE_FLOW,
- "%s infoDriver: read addr %d\n", pinfoPvt->portName, addr);
- pdeviceInfo = &pinfoPvt->device;
- if (!pdeviceInfo->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s infoDriver: read device %d not connected\n",
- pinfoPvt->portName, addr);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver:read device %d not connected",
- pinfoPvt->portName, addr);
-
- return asynError;
- }
-
- if (pinfoPvt->delay > pasynUser->timeout){
- if (pinfoPvt->delay > 0.0){
- epicsThreadSleep(pasynUser->timeout);
- }
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s infoDriver read timeout\n", pinfoPvt->portName);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver read timeout", pinfoPvt->portName);
- return asynTimeout;
- }
-
- if (pinfoPvt->delay > 0.0){
- epicsThreadSleep(pinfoPvt->delay);
- }
-
- pdeviceBuffer = &pdeviceInfo->buffer;
- nremaining = pdeviceBuffer->nchars;
- pdeviceBuffer->nchars = 0;
- pfrom = pdeviceBuffer->buffer;
- pto = data;
-
- while (nremaining >0 && nout < maxchars){
- thisChar = *pto++ = *pfrom++;
- nremaining--;
- nout++;
-
- if (pinfoPvt->eoslen > 0){
- if (thisChar == pinfoPvt->eos[0]){
- if (pinfoPvt->eoslen == 1){
- if (eomReason) * eomReason |= ASYN_EOM_EOS;
- break;
- }
- }
- if (nremaining == 0){
- if (eomReason) *eomReason |= ASYN_EOM_CNT;
- break;
- }
-
- if (* pfrom == pinfoPvt->eos[1]){
- *pto++ = *pfrom++;
- nremaining--;
- nout++;
-
- if (eomReason){
- *eomReason |= ASYN_EOM_EOS;
- if(nremaining == 0){
- *eomReason |= ASYN_EOM_CNT;
- break;
- }
- }
- }
- }
- }
-
- if (nbytesTransfered) *nbytesTransfered = nout;
- if (eomReason){
- if (*nbytesTransfered >= maxchars) *eomReason |= ASYN_EOM_CNT;
- if (nremaining == 0) * eomReason |= ASYN_EOM_END;
- }
-
- pasynOctetBase->callInterruptUsers(pasynUser, pinfoPvt->pasynPvt, data,
- nbytesTransfered, eomReason);
- asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, data, nout,
- "infoRead nbytesTransfered %lu\n", (unsigned long)*nbytesTransfered);
- return status;
- }
-
- static asynStatus infoFlush(void *drvPvt, asynUser * pasynUser)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- deviceBuffer * pdeviceBuffer;
- int addr;
- asynStatus status;
-
- status = pasynManager->getAddr(pasynUser, &addr);
- if (status != asynSuccess) return status;
-
- addr = 0;
-
- asynPrint(pasynUser, ASYN_TRACE_FLOW,
- "%s initDriver: flush addr %d\n",
- pinfoPvt->portName, addr);
-
- pdeviceInfo = &pinfoPvt->device;
- if (!pdeviceInfo->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s initDriver:flush device %d not connected\n",
- pinfoPvt->portName, addr);
- return -1;
- }
-
- pdeviceBuffer = &pdeviceInfo->buffer;
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s infoDriver\n", pinfoPvt->portName);
- pdeviceBuffer->nchars = 0;
-
- return asynSuccess;
- }
-
- static asynStatus setEos(void *drvPvt, asynUser * pasynUser, const char *eos, int eoslen)
- {
- infoPvt * pinfoPvt = (infoPvt *)drvPvt;
- int i;
-
- if (eoslen > 2 || eoslen < 0){
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "setEos illegal eoslen %d", eoslen);
- return asynError;
- }
-
- pinfoPvt->eoslen = eoslen;
- for (i = 0; i < eoslen; i++){
- pinfoPvt->eos[i] = eos[i];
- }
-
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s setEos\n", pinfoPvt->portName);
- return asynSuccess;
- }
-
- static asynStatus getEos(void *drvPvt, asynUser * pasynUser,char *eos, int eossize, int *eoslen)
- {
- infoPvt * pinfoPvt = (infoPvt *)drvPvt;
- int i;
-
- * eoslen = pinfoPvt->eoslen;
-
- for (i = 0; i < *eoslen; i++){
- eos[i] = pinfoPvt->eos[i];
- }
-
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s setEos\n",
- pinfoPvt->portName);
-
- return asynSuccess;
- }
-
- static asynStatus intWrite(void *drvPvt, asynUser * pasynUser, epicsInt32 value)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- deviceBuffer *pdeviceBuffer;
- int addr;
- asynStatus status;
-
- //printf("infoWrite: %s\n", data);
- status = pasynManager->getAddr(pasynUser, &addr);
- if(status != asynSuccess) return status;
- addr = 0;
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s initDriver: intWrite addr %d\n",
- pinfoPvt->portName, addr);
- pdeviceInfo = &pinfoPvt->device;
- if (!pdeviceInfo->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s infoDriver: intWrite %d not connected\n", pinfoPvt->portName, addr);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver:intWrite device %d not connected",
- pinfoPvt->portName, addr);
- return asynError;
- }
-
- if (pinfoPvt->delay > pasynUser->timeout){
- if (pasynUser->timeout > 0.0) epicsThreadSleep(pasynUser->timeout);
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s initDriver intWrite timeout\n", pinfoPvt->portName);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver intWrite timeout", pinfoPvt->portName);
-
- return asynTimeout;
- }
-
- pdeviceBuffer = &pdeviceInfo->buffer;
- if (value < pdeviceBuffer->low){
- pdeviceBuffer->value = pdeviceBuffer->low;
- }
- else if (value > pdeviceBuffer->high){
- pdeviceBuffer->value = pdeviceBuffer->high;
- }
- else{
- pdeviceBuffer->value = value;
- }
-
- asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, "Write to device", strlen("Write to device"),
- "intWrite value = %d\n", pdeviceBuffer->value);
- if (pinfoPvt->delay > 0.0) {
- epicsThreadSleep(pinfoPvt->delay);
- }
- return status;
- }
-
- static asynStatus intRead(void *drvPvt, asynUser * pasynUser, epicsInt32 *value)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- deviceBuffer *pdeviceBuffer;
- int addr;
- asynStatus status;
-
- //printf("infoRead: %s\n", data);
- status = pasynManager->getAddr(pasynUser, &addr);
- if(status != asynSuccess) return status;
- addr = 0;
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s initDriver: intRead addr %d\n",
- pinfoPvt->portName, addr);
- pdeviceInfo = &pinfoPvt->device;
- if (!pdeviceInfo->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s infoDriver: intRead %d not connected\n", pinfoPvt->portName, addr);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver:intRead device %d not connected",
- pinfoPvt->portName, addr);
- return asynError;
- }
-
- if (pinfoPvt->delay > pasynUser->timeout){
- if (pasynUser->timeout > 0.0) epicsThreadSleep(pasynUser->timeout);
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s initDriver intRead timeout\n", pinfoPvt->portName);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver intRead timeout", pinfoPvt->portName);
-
- return asynTimeout;
- }
-
- pdeviceBuffer = &pdeviceInfo->buffer;
- * value = pdeviceBuffer->value;
-
- asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, "Read from device", strlen("Read from device"),
- "intRead value = %d\n", pdeviceBuffer->value);
- if (pinfoPvt->delay > 0.0) {
- epicsThreadSleep(pinfoPvt->delay);
- }
- return status;
- }
-
-
- static asynStatus getIntBounds(void *drvPvt, asynUser * pasynUser, epicsInt32 *low, epicsInt32 *high)
- {
- infoPvt *pinfoPvt = (infoPvt *)drvPvt;
- deviceInfo *pdeviceInfo;
- deviceBuffer *pdeviceBuffer;
- int addr;
- asynStatus status;
-
- //printf("getIntBounds: %s\n", data);
- status = pasynManager->getAddr(pasynUser, &addr);
- if(status != asynSuccess) return status;
- addr = 0;
- asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s initDriver: getIntBounds addr %d\n",
- pinfoPvt->portName, addr);
- pdeviceInfo = &pinfoPvt->device;
- if (!pdeviceInfo->connected){
- asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s infoDriver: getIntBounds %d not connected\n", pinfoPvt->portName, addr);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver:getIntBounds device %d not connected",
- pinfoPvt->portName, addr);
- return asynError;
- }
-
- if (pinfoPvt->delay > pasynUser->timeout){
- if (pasynUser->timeout > 0.0) epicsThreadSleep(pasynUser->timeout);
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s initDriver getIntBounds timeout\n", pinfoPvt->portName);
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s infoDriver getIntBounds timeout", pinfoPvt->portName);
-
- return asynTimeout;
- }
-
- pdeviceBuffer = &pdeviceInfo->buffer;
- * low = pdeviceBuffer->low;
- * high = pdeviceBuffer->high;
-
- asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, "get limits from device", strlen("get limits from device"),
- "getIntBounds low = %d, high = %d\n", pdeviceBuffer->low, pdeviceBuffer->high);
- return status;
- }
-
- // static int infoDriverInit(const char * portName, double delay, int noAutoConnect, int low, int high);
- static const iocshArg infoDriverInitArg0 = { "portName", iocshArgString };
- static const iocshArg infoDriverInitArg1 = { "delay", iocshArgDouble };
- static const iocshArg infoDriverInitArg2 = { "noautoconnect", iocshArgInt };
- static const iocshArg infoDriverInitArg3 = { "low", iocshArgInt };
- static const iocshArg infoDriverInitArg4 = { "high", iocshArgInt };
-
- static const iocshArg *infoDriverInitArgs[] = {
- &infoDriverInitArg0,&infoDriverInitArg1,
- &infoDriverInitArg2,&infoDriverInitArg3, &infoDriverInitArg4};
-
- static const iocshFuncDef infoDriverInitFuncDef = {
- "infoDriverInit", 5, infoDriverInitArgs};
-
- static void infoDriverInitCallFunc(const iocshArgBuf *args)
- {
- infoDriverInit(args[0].sval,args[1].dval,args[2].ival,args[3].ival, args[4].ival);
- }
-
- static void infoDriverRegister(void)
- {
- static int firstTime = 1;
- if (firstTime) {
- firstTime = 0;
- iocshRegister(&infoDriverInitFuncDef, infoDriverInitCallFunc);
- }
- }
-
- epicsExportRegistrar(infoDriverRegister);
将以上程序添加到应用程序的dbd文件如下:device.dbd
registrar(infoDriverRegister)
将以上device.c和device.dbd文件添加到相同目录下Makefile中,并且添加所需的其它库文件:
- ...
- # dbd文件
- infoDriver_DBD += asyn.dbd
- infoDriver_DBD += device.dbd
- # 库文件
- infoDriver_LIBS += asyn
- # 源文件
- infoDriver_SRCS += device.c
-
- ...
回到这个IOC的顶层目录,执行make命令,进行编译。
进入这个点IOC程序的启动目录中,在st.cmd脚本中按定义的格式调用infoDriverInit:
- #!../../bin/linux-aarch64/infoDriver
-
- #- You may have to change infoDriver to something else
- #- everywhere it appears in this file
-
- < envPaths
-
- cd "${TOP}"
-
- ## Register all support components
- dbLoadDatabase "dbd/infoDriver.dbd"
- infoDriver_registerRecordDeviceDriver pdbbase
-
- infoDriverInit("MyPort", 0.5, 0, 0, 1000)
- dbLoadRecords("$(ASYN)/db/asynRecord.db","P=Asyn:,R=AsynRecord,PORT=MyPort,ADDR=0,OMAX=0,IMAX=0")
-
- cd "${TOP}/iocBoot/${IOC}"
- iocInit
启动这个IOC程序:
- root@orangepi5:/usr/local/EPICS/program/infoDriver/iocBoot/iocinfoDriver# ../../bin/linux-aarch64/infoDriver st.cmd
- #!../../bin/linux-aarch64/infoDriver
- < envPaths
- epicsEnvSet("IOC","iocinfoDriver")
- epicsEnvSet("TOP","/usr/local/EPICS/program/infoDriver")
- epicsEnvSet("SUPPORT","/usr/local/EPICS/synApps/support")
- epicsEnvSet("ASYN","/usr/local/EPICS/synApps/support/asyn")
- epicsEnvSet("EPICS_BASE","/usr/local/EPICS/base")
- cd "/usr/local/EPICS/program/infoDriver"
- ## Register all support components
- dbLoadDatabase "dbd/infoDriver.dbd"
- infoDriver_registerRecordDeviceDriver pdbbase
- infoDriverInit("MyPort", 0.5, 0, 0, 1000)
- cd "/usr/local/EPICS/program/infoDriver/iocBoot/iocinfoDriver"
- iocInit
- Starting iocInit
- ############################################################################
- ## EPICS R7.0.7
- ## Rev. 2023-05-26T09:07+0000
- ## Rev. Date build date/time:
- ############################################################################
- iocRun: All initialization complete
- epics>
在epics命令提示环境中测试以上部分asyn诊断命令:
- epics> asynOctetConnect("myid","MyPort",0,1,20)
- epics> asynOctetWrite("myid","HelloWorld")
- epics> asynOctetRead("myid")
- eomReason 0x4
- HelloWorld
- epics> asynOctetWriteRead("myid","This is a test")
- eomReason 0x4
- This is a test
- epics> asynOctetDisconnect("myid")
- epics> asynReport(1,"MyPort")
- MyPort multiDevice:No canBlock:Yes autoConnect:Yes
- enabled:Yes connected:Yes numberConnects 1
- nDevices 0 nQueued 0 blocked:No
- asynManagerLock:No synchronousLock:No
- exceptionActive:No exceptionUsers 1 exceptionNotifys 0
- traceMask:0x1 traceIOMask:0x0 traceInfoMask:0x1
- infoDriver connected:Yes delay = 0.500000
- epics> asynSetTraceMask("MyPort",-1, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW)
- epics> asynOctetWrite("myid","HelloWorld")
- 2023/09/05 12:55:25.521 MyPort asynManager::queueLockPort locking port
- 2023/09/05 12:55:25.522 MyPort asynManager::queueLockPort taking mutex 0x55702ab790
- 2023/09/05 12:55:25.522 MyPort asynManager::queueLockPort queueing request
- 2023/09/05 12:55:25.523 MyPort addr -1 queueRequest priority 0 not lockHolder
- 2023/09/05 12:55:25.524 MyPort schedule queueRequest timeout in 2.000000 seconds
- 2023/09/05 12:55:25.525 MyPort asynManager::queueLockPort waiting for event
- 2023/09/05 12:55:25.526 asynManager::portThread port=MyPort callback
- 2023/09/05 12:55:25.526 MyPort asynManager::queueLockPortCallback signaling begin event
- 2023/09/05 12:55:25.526 MyPort asynManager::queueLockPortCallback waiting for mutex from queueUnlockPort
- 2023/09/05 12:55:25.526 MyPort asynManager::queueLockPort got event from callback
- 2023/09/05 12:55:25.528 MyPort initDriver: write addr 0
- 2023/09/05 12:55:26.028 MyPort queueUnlockPort
- 2023/09/05 12:55:26.030 MyPort asynManager::queueUnlockPort waiting for event
- 2023/09/05 12:55:26.031 MyPort queueUnlockPort unlock mutex 0x55702ab790 complete.
- epics> asynOctetRead("myid")
- 2023/09/05 12:56:12.292 MyPort asynManager::queueLockPort locking port
- 2023/09/05 12:56:12.293 MyPort asynManager::queueLockPort taking mutex 0x55702ab790
- 2023/09/05 12:56:12.293 MyPort asynManager::queueLockPort queueing request
- 2023/09/05 12:56:12.293 MyPort addr -1 queueRequest priority 0 not lockHolder
- 2023/09/05 12:56:12.294 MyPort schedule queueRequest timeout in 2.000000 seconds
- 2023/09/05 12:56:12.295 MyPort asynManager::queueLockPort waiting for event
- 2023/09/05 12:56:12.296 asynManager::portThread port=MyPort callback
- 2023/09/05 12:56:12.296 MyPort asynManager::queueLockPortCallback signaling begin event
- 2023/09/05 12:56:12.296 MyPort asynManager::queueLockPortCallback waiting for mutex from queueUnlockPort
- 2023/09/05 12:56:12.296 MyPort asynManager::queueLockPort got event from callback
- 2023/09/05 12:56:12.296 MyPort infoDriver: read addr 0
- 2023/09/05 12:56:12.797 MyPort queueUnlockPort
- 2023/09/05 12:56:12.797 MyPort asynManager::queueUnlockPort waiting for event
- 2023/09/05 12:56:12.798 MyPort queueUnlockPort unlock mutex 0x55702ab790 complete.
- eomReason 0x4
- HelloWorld
使用asyRecord.adl进行测试:
medm -x -macro "P=Asyn:,R=AsynRecord" asynRecord.adl
出现以下窗口:

选择More...菜单的asynOctet Interface I/O:

弹出以下窗口,在Out的ASCII文本框中输入一个字符串,这里为HelloWord,按回车,可以看到Input的ASCII文本框中显示读回的HelloWorld,并且EOM reason中显示字符串结束的原因。

选择More...菜单的Register Interface I/O,弹出以下窗口,将Interface下的菜单选中asynInt32,在Output文本框中输入一个数值68,按回车后,在Input文本框中回读到这个数值:

补充一个记录实例文件:
- record(calc,"$(P)$(R)_P$(PORT)_A$(A)_calc") {
- field(DESC, "Counter")
- field(SCAN,"Passive")
- field(CALC, "(A<99)?(A+1):0")
- field(INPA,"$(P)$(R)_P$(PORT)_A$(A)_calc NPP NMS")
- field(FLNK,"$(P)$(R)_P$(PORT)_A$(A)_so")
- field(EGU, "Counts")
- field(HOPR, "10")
- field(FLNK,"$(P)$(R)_P$(PORT)_A$(A)_so")
- }
-
- record(stringout,"$(P)$(R)_P$(PORT)_A$(A)_so") {
- field(DOL,"$(P)$(R)_P$(PORT)_A$(A)_calc NPP NMS")
- field(OMSL,"closed_loop")
- field(FLNK,"$(P)$(R)_P$(PORT)_A$(A)_si")
- }
-
- record(stringin,"$(P)$(R)_P$(PORT)_A$(A)_si") {
- field(DTYP,"asynOctetWriteRead")
- field(INP,"@asyn($(PORT),$(A)) $(P)$(R)_P$(PORT)_A$(A)_so")
- }
以上实例文件运行过程为:当calc记录运行时,其从自己的VAL读取一个值,如果这个数值小于99就VAL增加1,否则VAL变为0,在运行结束前,通过FLNK使stringout记录运行,stringout从calc记录的VAL字段读取一个值,将其转换成字符串表示形式,存入到自己的VAL字段,并且在运行结束前,通过FLNK使得stringin记录运行,当stringin运行时,通过接口asynOctetWriteRead设备支持,将从stringout读取的字符串写入到端口驱动程序中,然后从端口驱动中回读字符串,写入到自己的VAL字段中。
将以下记录加载命令,添加到st.cmd启动脚本文件的iocInit前:
dbLoadRecords("db/test.db", "P=Test:,R=Client,PORT=MyPort,A=0")
重启这个IOC,用dbl命令查看加载的记录:
- epics>dbl
- Asyn:AsynRecord
- Test:Client_PMyPort_A0_calc
- Test:Client_PMyPort_A0_si
- Test:Client_PMyPort_A0_so
用CSS进行以上记录运行的显示:

asynRegisterTimeStampSource:为指定端口调用pasynManager->registerTimeStampSource。时间戳源函数必须在这个程序的dbd文件中被定义为"函数"。
asynReisgerTimeStampSource:为指定端口调用pasynManager->unregisterTimeStampSource。这恢复成asynManager中默认的时间戳源函数。