EPICS asyn诊断帮助

news2024/12/23 5:23:43

iocsh命令

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。

  1. ASYN_TRACE_ERROR:报告运行时错误,例如,超时。
  2. ASYN_TRACEIO_DEVICE:设备支持报告I/O活动。
  3. ASYN_TRACEIO_FILTER:在设备支持和底层驱动之间的任何层报告它对I/O进行的任何过滤。
  4. ASYN_TRACEIO_DRIVER:底层驱动报告I/O活动。
  5. ASYN_TRACE_FLOW:报告逻辑流。设备支持应该报告所有队列请求,进入的回调以及对驱动的所有调用。在设备支持和底层驱动之间的层应该报告它们对更低层驱动的所有调用。底层驱动报告它们对其它支持的调用。
  6. ASYN_TRACE_WARNING:报告警告,即,在ASYN_TRACE_ERROR和ASYN_TRACE_FLOW之间的情况。

asynSetTraceIOMask:为指定端口和地址调用asynTrace:setTraceIOMask。如果portName是0长度,则全局跟踪掩码被设置。另一个掩码,它决定打印多少消息缓存。各种选项能够被ORed到一起。创建这个端口时,这个掩码的默认值是ASYN_TRACEIO_NODATA。

  1. ASYN_TRACEIO_NODATA:不打印来自消息缓存的任何数据。
  2. ASYN_TRACEIO_ASCII:用"%s"格式打印。
  3. ASYN_TRACEIO_ESCAPE: 调用epicsStrPrintEscaped.
  4. ASYN_TRACEIO_HEX :用%2.2x打印每个字节。

asynSetTraceInfoMask:为指定端口和地址调用asynTrace:setTraceInfoMask。如果portName是0长度,则全局跟踪掩码被设置。一个掩码确定了在每条消息开头打印数目信息。不同选项可以被ORed在一起。创建一个端口时,这个掩码的默认值是ASYN_TRACEINFO_TIME。

  1. ASYN_TRACEINFO_TIME:打印这条消息的日期和时间。
  2. ASYN_TRACEINFO_PORT:打印[port, addr, reason],此处port是端口名,addr是asyn地址,而reason是pasynUser->reason。这些是asyn中3段"地址"信息。
  3. ASYN_TRACEINFO_SOURCE:打印文件名和行号,即[__FILE__, __LINE__],此处asynPrint或asynPrintIO状态发生的位置。
  4. ASYN_TRACEINFO_THREAD:打印线程名称,线程ID和线程优先级,即[epicsThreadGetNameSelf(), epicsThreadGetIdSelf(), epicsThreadGetPrioritySelf()]。

从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。按如下处理文件名:

  1. 未指定。一个NULL指针被传递给setTraceFile。后续消息被发送给errlog。
  2. 一个空字符串("")或"stderr":stderr被传递给setTraceFile。
  3. "stdout":stdout被传递给setTraceFile。
  4. 任何其它字符串:用选项"w"打开这个指定的文件,并且文件指针被传递给setTraceFile。

asynSetTraceIOTruncateSize:asynSetTraceIOTruncateSize调用asynTrace:setTraceIOTruncateSize。

asynSetOption:asynSetOption调用asynCommon:setOption。

asynShowOptin:asynShowOption调用asynCommon:getOption。

asynOctetXXX命令:提供了对asynOctetSyncIO方法的shell访问。entry是标识端口,地址的字符串常量。

此处:

  • filename:一个指定文件名的ascii字符串。如果null或null字符串,则输出被发送到stdout。
  • level:汇报级别。
  • portName:一个指定驱动的portName的ascii字符串。
  • addr:指定设备地址的整数。用于多设备端口,-1值标识端口自身。对于支持单设备的端口,忽略addr。
  • mask:要设置的掩码。
  • key:对应所需选项的键。
  • val:对应这个选项的值。
  • yesNo:值(0,1)表示(no, yes)。
  • entry:一个字符串,标识asynOctetConnect请求。
  • timeout:用毫秒整数指定timeout。默认是1。
  • buffer_len:对应I/O的缓存长度。默认为160。注意:传递给asynOctetWrite的输出字符串可以有转义字符。buffer_len必须足够大来处理转义字符。例如,如果\x02出现在输出字符串中,它算作4个字符。
  • drvInfo:通过接口asynDrvUser传递给驱动的字符串。
  • nread:要读取最大数目的字节。默认=buffer_len。
  • flush:(0,1)表示在读取前(不要,要)flush。默认0。
  • output:输出字符串。

命令asynOctetConnect, asynOctetDisconnect, asynOctetRead, asynOctetWrite, asynOctetWriteRead, asynOctet允许从ioc shell对设备进行I/O。示例是:

以下示例展示了使用https://blog.csdn.net/yuyuyuliang00/article/details/132668739中的asyn驱动模块创建了一个端口驱动程序来测试以上列出的部分asyn诊断命令。

以下这个驱动程序的源代码:

#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#include "cantProceed.h"
#include "epicsStdio.h"
#include "epicsThread.h"
#include "iocsh.h"

#include "asynDriver.h"
#include "asynOctet.h"
#include "asynInt32.h"

#include <epicsExport.h>
#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中默认的时间戳源函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/989909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Greenplum执行SQL卡住的问题

问题 今天社区群里面一位同学反映他的SQL语句执行会hang住&#xff0c;执行截图如下。 分析 根据提示信息&#xff0c;判断可能是网络有问题&#xff0c;或者是跟GP使用UDP包有关系。 此同学找了网络检查的人确定网络没有问题&#xff0c;于是猜测跟UDP包有关。 参考文章ht…

合宙Air724UG LuatOS-Air LVGL API控件-窗口 (Window)

窗口 (Window) 分 享导出pdf 示例代码 win lvgl.win_create(lvgl.scr_act(), nil) lvgl.win_set_title(win, "Window title") -- close_btn lvgl.win_add_btn_right(win, "\xef\x80\x8d") -- --lvgl.obj_set_event_cb(cl…

企业架构LNMP学习笔记23

1、隐藏版本号&#xff1a; Nginx对外提供服务&#xff0c;为了避免被针对某个版本的漏洞进行攻击。经常做法是隐藏掉软件的版本信息&#xff0c;提供一定的安全性。 server_tokens off; https和CA&#xff1a; 1&#xff09;基于SSL CA证书的公私钥的安全性。 CA是需要生成…

pip安装skimage的方法

在安装skimage时&#xff0c;可能会报错误&#xff1a; 可以尝试&#xff1a;pip install scikit-image进行安装&#xff0c;使用时只需要&#xff1a;import skimage

Multisim14.0仿真(十)同相放大器

一、仿真原理图&#xff1a; 二、仿真效果图&#xff1a;

5.xaml RadioButton按钮

1.运行图 2.运行源码 a.Xaml源码 <Grid Name="Grid1"><!--GroupName="role" 设置组名,同一组名,他们是互斥--><RadioButton Content="管理员" GroupName

数据库作业练习题

数据库知识 1.不属于关系数据库的是&#xff08;B&#xff09; A.Oracle B.Essbase C.SQL Server D.DB2 Oracle和SQL Server属于关系数据库&#xff0c;DB2是个老古董了&#xff0c;看见DB也应该知道是数据库了&#xff0c;就剩下Essbase了&#xff0c;故选B。Essbase是一种多…

代码审查和合并请求:团队合作中的关键

在现代软件开发中&#xff0c;团队合作是不可或缺的一部分。为了确保代码质量、减少错误以及促进知识共享&#xff0c;代码审查和合并请求成为了开发团队中的关键实践。在本文中&#xff0c;我们将深入探讨代码审查和合并请求的重要性、流程以及最佳实践。 代码审查的重要性 …

2023-09-08 LeetCode每日一题(计算列车到站时间)

2023-09-08每日一题 一、题目编号 2651. 计算列车到站时间二、题目链接 点击跳转到题目位置 三、题目描述 给你一个正整数 arrivalTime 表示列车正点到站的时间&#xff08;单位&#xff1a;小时&#xff09;&#xff0c;另给你一个正整数 delayedTime 表示列车延误的小时…

超高清Mac动态壁纸桌面:Dynamic Wallpaper for Mac中文版本

Dynamic Wallpaper for Mac是一款引人注目的动态壁纸软件&#xff0c;为你的Mac桌面带来全新的视觉体验。 [特点1]&#xff1a;轻松定制动态壁纸&#xff1a;这款软件具有用户友好的界面&#xff0c;使得定制动态壁纸变得异常简单。用户可以轻松选择和调整动画效果&#xff0c…

INDEMIND:减少近90%的现场部署时间,商用机器人也能开机即用?

把商用机器人现场部署时间减少80-90%&#xff0c;噱头or真实力&#xff1f; 费时费力的现场部署 与扫地机器人开机即用不同&#xff0c;一般商用机器人在使用前&#xff0c;还有最后“一道工序”&#xff0c;现场部署。这个过程&#xff0c;需要专门的现场部署工程师逐个区域…

idea远程调试debug

idea远程调试debug 第一步 jdk也要选对应的 配置好了之后先启动远程的jar包 启动好之后就需要启动ide上的服务 然后和本地打断点一样打上标记就行了&#xff0c;方法执行到这会停住 通常连接不上远程服务器的原因会是防火墙对应的端口没有开启开启后就能正常连了

端口已被占用

报的错误 Exception in thread "Thread-76" java.net.BindException: Address already in use: bindat sun.nio.ch.Net.bind0(Native Method)at sun.nio.ch.Net.bind(Net.java:433)at sun.nio.ch.Net.bind(Net.java:425)at sun.nio.ch.ServerSocketChannelImpl.bind…

从管易云到金蝶云星空通过接口配置打通数据

从管易云到金蝶云星空通过接口配置打通数据 接通系统&#xff1a;管易云 金蝶管易云是金蝶集团旗下以电商和新零售为核心业务的子公司&#xff0c;公司于2008年成立&#xff0c;拥有从事电商及新零售业务相关专业知识工作者超过1000人。为伊利、网易有道、东阿阿胶、金龙鱼、海…

AsConvSR

编辑 | Happy 首发 | AIWalker 链接 | https://mp.weixin.qq.com/s/p9u6RYkd37MmN12rUCMCuQ 前段时间&#xff0c;NTIRE2023各个竞赛落下帷幕&#xff0c;近期各个冠亚军方案提出者也在逐步公开方案细节。今天给大家概要介绍一下"RTSR-Track1"赛道冠军方案&#xff0…

OpenCV 03(数据结构--Mat)

一、Mat介绍 Mat是OpenCV在C语言中用来表示图像数据的一种数据结构.在python中转化为numpy的ndarray. Mat由header和data组成, header中记录了图片的维数, 大小, 数据类型等数据. 1.1 Mat拷贝 - Mat共享数据 在python中Mat数据对应numpy的ndarray, 使用numpy提供的深浅拷贝方…

数据结构与算法-树论基础二叉树

大家来看以下几个结构&#xff1a;下图中的结构除了一颗不是树其余的都是&#xff0c;我们可以发现这个跟我们现实生活的树是不是非常相似. 在树形结构里面有几个重要的术语&#xff1a; 1.结点&#xff1a;树里面的元素。 2.父子关系&#xff1a;结点之间相连的边 3.子树&…

Android:基于mvvm框架使用viewPage

一、前言&#xff1a; 最近在学习viewpage的使用&#xff0c;加上一直以来用mvvm框架。就想着记录一下。 二、代码展示&#xff1a; 1.引入依赖 //viewPage2引用(微信左右滑动页面)implementation androidx.viewpager2:viewpager2:1.0.0 2.在xml中的使用 3.在代码中找到vie…

基于大规模MIMO通信系统的半盲信道估计算法matlab性能仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 %EM算法收敛所需的迭代 nIter 1; Yp Y(:,1:L_polit,:); %与导频序列相对应的部分 q…

包管理工具--》发布一个自己的npm包

包管理工具系列文章目录 一、包管理工具--》npm的配置及使用&#xff08;一&#xff09; 二、包管理工具--》npm的配置及使用&#xff08;二&#xff09; 三、包管理工具--》发布一个自己的npm包 四、包管理工具--》yarn的配置及使用 五、包管理工具--》其他包管理器之cnpm…