EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024 Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024
<== Date ==> <== Thread ==>

Subject: A question on asyn application
From: cxy via Tech-talk <tech-talk at aps.anl.gov>
To: tech-talk at aps.anl.gov
Date: Mon, 22 Jan 2024 10:10:40 +0800 (CST)

Hello everyone,

I am using the asyn module to write a device IOC. I want to set the SCAN field as Intr I/O to adapt to the application requirement.
The db file is like this:
 record(stringin,"$(P)Ver")
{
   field(DESC,"Firmware version")
   field(DTYP, "asynOctetRead")
   field(INP, "@asyn($(PORT),$(ADDR)) VERSION")
   field(SCAN,"I/O Intr")
}
record(stringin,"$(P)Mod")
{
   field(DESC,"Get counter mod")
   field(DTYP, "asynOctetRead")
   field(INP, "@asyn($(PORT),$(ADDR)) MOD")
   field(SCAN,"I/O Intr")
}
record(stringout,"$(P)Reboot")
{
    field(DESC,"Reboot Device")
    field(DTYP,"asynOctetWrite")
    field(OUT,"@asyn($(PORT),$(ADDR))REBOOT")
    field(VAL, "REST")
}
record(stringin, "$(P)GateInStatus")
{
    field(DESC,"DS:AlwaysON/EN:Need Input")
    field(DTYP,"asynOctetRead")
    field(INP,"@asyn($(PORT),$(ADDR)) GATEINSTATUS")
    field(SCAN,"I/O Intr")
}
record(longin,"$(P)Count07")
{
   field(DESC,"Counter 07")
   field(DTYP, "asynInt32")
   field(INP, "@asyn($(PORT),$(ADDR)) COUNT07")
   field(SCAN,"I/O Intr")
}
... ...
When I run the st.cmd file, it prompt: initCommon enum registerInterruptUser asynManager: getInterruptPvt Driver does not support interrupts on intterface asynEnum”.  All the test-error picture,  st.cmd and the complete .cpp files are attatched. I don't know where  the problem is and how to correct it.   Maybe  a polling function is necessary in the .cpp file when the SCAN filed is "I/O Intr", and the write or read functions should be called in the polling function?
Looking forward to your feedback.  Thank you very much.
Best wishes,   
Yoon

Attachment: test-error.png
Description: PNG image

/*
 * ct08.cpp
 *
 * Asyn driver that inherits from the asynPortDriver class to test connection handling
 *
 * Author: Mark Rivers
 *
 * Created June 2, 2012
 */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <epicsTypes.h>
#include <epicsTime.h>
#include <epicsTimer.h>
#include <epicsThread.h>
#include <epicsString.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <iocsh.h>
#include <epicsExport.h>
#include "ct08.h"

/*Define symbolic constants*/
#define TIMEOUT (5.0)
#define BUFFER_SIZE (100)
#define POLLER_PERIOD 1
#define MAX_RESPONSE_LEN 256

static const char *driverName="ct08";

static void pollerTask(void *drvPvt);

ct08::ct08(const char *portName, const char *IPPortName, const char *outputString)
   : asynPortDriver(portName,
                    1, /* maxAddr */
                    asynOctetMask | asynInt32Mask | asynFloat64Mask |asynFloat64ArrayMask |asynEnumMask |asynDrvUserMask,/* Interface mask */
                    asynOctetMask | asynInt32Mask | asynFloat64Mask |asynFloat64ArrayMask |asynEnumMask |asynDrvUserMask, /* Interrupt mask */
                    0,
                    ASYN_CANBLOCK, /* asynFlags.  This driver does block and it is not multi-device*/
                    1, /* Autoconnect */
                    0, /* Default priority */
                    0) /* Default stack size*/
{
    asynStatus status;
    const char *functionName = "ct08";
   
    /*createParam*/
    createParam(P_VersionString, asynParamOctet, &P_Version);
    createParam(P_ModString, asynParamOctet, &P_Mod);
    createParam(P_RebootString, asynParamOctet, &P_Reboot);
    createParam(P_GateinstatusString, asynParamOctet, &P_Gateinstatus);
    createParam(P_Count07String, asynParamInt32, &P_Count07);
    createParam(P_StartString, asynParamInt32, &P_Start);
    createParam(P_StopString, asynParamInt32, &P_Stop);
    createParam(P_DistimestopString, asynParamInt32, &P_Distimestop);
    createParam(P_EntimestopString, asynParamInt32, &P_Entimestop);
    createParam(P_SetTmsString, asynParamInt32, &P_SetTms);
    createParam(P_ReadTmsString, asynParamInt32, &P_ReadTms);


    outputString_ = epicsStrDup(outputString);

    /* Connect to the port */
    status = pasynOctetSyncIO->connect(IPPortName, 0, &pasynUserIPPort_, NULL);
    if (status) {
        printf("%s:%s: pasynOctetSyncIO->connect failure, status=%d\n", driverName, functionName, status);
        return;
    }

    /* Create the thread that computes the waveforms in the background */
    status = (asynStatus)(epicsThreadCreate("ct08Task",
                          epicsThreadPriorityMedium,
                          epicsThreadGetStackSize(epicsThreadStackMedium),
                          (EPICSTHREADFUNC)::pollerTask,
                          this) == NULL);
    if (status) {
        printf("%s:%s: epicsThreadCreate failure, status=%d\n", driverName, functionName, status);
        return;
    }
}



static void pollerTask(void *drvPvt)
{
    ct08 *pPvt = (ct08 *)drvPvt;

    pPvt->pollerTask();
}

/** Poller task that runs as a separate thread. */
void ct08::pollerTask(void)
{
    asynStatus status;
    char response[MAX_RESPONSE_LEN] = "";
    size_t numWrite, numRead;
    int isConnected;
    int eomReason;
    static const char *functionName = "pollerTask";
}

/** Called when asyn clients call pasynInt32->write().
 *   * This function sends a signal to the simTask thread if the value of P_Run has changed.
 *     * For all parameters it sets the value in the parameter library and calls any registered callbacks..
 *       * \param[in] pasynUser pasynUser structure that encodes the reason and address.
 *         * \param[in] value Value to write. */
asynStatus ct08::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;
    size_t nRead;
    size_t nActual;
    int eomReason;
    //int readValue;
    const char *paramName;
    const char* functionName = "writeInt32";

    /* Set the parameter in the parameter library. */
    status = (asynStatus) setIntegerParam(function, value);
    
    /* Fetch the parameter string name for possible use in debugging */
   // getParamName(function, &paramName); //debug 2-1
   
    
    if (function==P_Start) {
        sprintf(writeBuffer, "%d", value);
        status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, strlen(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, &nActual, &nRead, &eomReason); //debug 2-2
        //sscanf(readBuffer, "%d", readValue);
        printf("P_Start returns %s \r\n",readBuffer);  
    }

     if (function==P_Stop) {
        sprintf(writeBuffer, "%d", value);
        status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, strlen(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, &nActual, &nRead, &eomReason); //debug 2-2
      //  sscanf(readBuffer, "%d", readValue);
        printf("P_Start returns %s \r\n",readBuffer); 
    }

      if (function==P_SetTms) {
        sprintf(writeBuffer, "%d", value);
        status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, strlen(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, &nActual, &nRead, &eomReason); //debug 2-2
        //sscanf(readBuffer, "%d", readValue);
        printf("P_SetTms returns %s \r\n",readBuffer); 
    }


    /* Do callbacks so higher layers see any changes */
    status = (asynStatus) callParamCallbacks();

    if (status)
        epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                  "%s:%s: status=%d, function=%d, name=%s, value=%d",
                  driverName, functionName, status, function, paramName, value);
    else
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
              "%s:%s: function=%d, name=%s, value=%d\n",
              driverName, functionName, function, paramName, value);
    return status;
}

asynStatus ct08::readInt32(asynUser *pasynUser, epicsInt32* value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;
    const char *functionName = "readInt32";
    size_t nActual;
    size_t nRead;
    int eom;       
    if(function==P_Count07)
    {
        sprintf(writeBuffer, "%s", "CTR?070701");// to change it tobe CTMR?000701, change the readBuffer size tobe 100,then send count and timer to it's PV seperately.
        status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer,sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, &nActual, &nRead, &eom);
        status=(asynStatus)setStringParam(P_Count07,readBuffer);
    }
    if(function==P_ReadTms)
    {   
        sprintf(writeBuffer, "%s", "TPR?");// to change it tobe CTMR?000701, change the readBuffer size tobe 100,then send count and timer to it's PV seperately.
        status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer,sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, &nActual, &nRead, &eom);
        status=(asynStatus)setStringParam(P_ReadTms,readBuffer);
    }

   status=(asynStatus)callParamCallbacks();

    if (status)
        epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                  "%s:%s: status=%d, function=%d",
                  driverName, functionName, status, function);
    else
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
              "%s:%s: function=%d\n",
              driverName, functionName, function);
    return status;
}

asynStatus ct08::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
{
   int function=pasynUser->reason;
   asynStatus status=asynSuccess;
   const char *paramName;
   const char* functionName="writeFloat64";

   /*Set parameter in the parameter liberay*/
   status=(asynStatus)setDoubleParam(function, value);
   /*Fetch the parameter in the parameter liberary*/
   getParamName(function,&paramName);

   /*do callbacks so higher layers see any changes*/
   status=(asynStatus)callParamCallbacks();
   
   if(status)
      epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                "%s:%s: status=%d, function=%d, name=%s, value=%f",
                driverName, functionName, status, function, paramName, value);
   else
      asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, name=%s, value=%f\n", driverName, functionName, paramName, value);
   return status;
}

asynStatus ct08::readFloat64(asynUser *pasynUser, epicsFloat64* value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;
    const char *functionName = "readFloat64Array";

    if (status)
        epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                  "%s:%s: status=%d, function=%d",
                  driverName, functionName, status, function);
    else
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
              "%s:%s: function=%d\n",
              driverName, functionName, function);
    return status;
}

asynStatus ct08::writeOctet(asynUser* pasynUser, const char* data, size_t maxchars, size_t *nActual)
{
  int function=pasynUser->reason;
  asynStatus status=asynSuccess;
  size_t nRead;
  int eomReason;
  const char *functionName="writeOctet";
  if(function==P_Reboot)
  {
   sprintf(writeBuffer,"%s","REST");
   // status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, data, maxchars, readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, &eomReason);
    status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, &eomReason);
    status=(asynStatus)setStringParam(P_Reboot,readBuffer);

   /*test code*/
   const char *readData;  
   getParamName(P_Reboot, &readData);
   printf("P_Reboot is %s \r\n",readData);
   /*test code end*/
  }
  if(function==P_Distimestop)
  {
   sprintf(writeBuffer,"%s","DSAS");
   status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, &eomReason);
   status=(asynStatus)setStringParam(P_Distimestop,readBuffer);
  }
  if(function==P_Entimestop)
  {
   sprintf(writeBuffer,"%s","ENCS");
   status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, &eomReason);
   status=(asynStatus)setStringParam(P_Entimestop,readBuffer);
  }

  status=(asynStatus)callParamCallbacks();

  if(status)
      epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s:%s:status=%d,function=%d,value=%s", driverName, functionName, status,function, data);
  else
      asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, value=%s\n", driverName,functionName,function,data);
  return status;
}

asynStatus ct08::readOctet(asynUser* pasynUser, const char* data, size_t maxchars, size_t *nActual, int *eom)
{
  int function=pasynUser->reason;
  asynStatus status=asynSuccess;
  size_t nRead;
  const char *functionName="readOctet";
  if(function=P_Version)
  {
    sprintf(writeBuffer, "%s", "VER?");
    status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, eom);
    status=(asynStatus)setStringParam(P_Version,readBuffer);
  }
  if(function=P_Mod)
  {
    sprintf(writeBuffer,"%s","MOD?");
    status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, eom);
    status=(asynStatus)setStringParam(P_Mod,readBuffer);
  }
  if(function=P_Gateinstatus)
  {
    sprintf(writeBuffer,"%s","GATEIN?");
    status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, eom);
    status=(asynStatus)setStringParam(P_Gateinstatus,readBuffer);
  }

  status=(asynStatus)callParamCallbacks();

  if(status)
       epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s:%s:status=%d,function=%d,value=%s", driverName, functionName, status, function, data);
  else
      asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, value=%s\n", driverName,functionName,function,data);
  return status;
}

extern "C" {
int ct08Configure(const char *portName, const char *IPPortName, const char *outputString)
{
    new ct08(portName, IPPortName, outputString);
    return(asynSuccess);
}


/* EPICS iocsh shell commands */

static const iocshArg initArg0 = { "portName",iocshArgString};
static const iocshArg initArg1 = { "IPPortName",iocshArgString};
static const iocshArg initArg2 = { "output string",iocshArgString};
static const iocshArg * const initArgs[] = {&initArg0, &initArg1, &initArg2};
static const iocshFuncDef initFuncDef = {"ct08Configure",3,initArgs};
static void initCallFunc(const iocshArgBuf *args)
{
    ct08Configure(args[0].sval, args[1].sval, args[2].sval);
}

void ct08Register(void)
{
    iocshRegister(&initFuncDef,initCallFunc);
}

epicsExportRegistrar(ct08Register);
}
#!../../bin/linux-x86_64/ct08
<envPaths
cd "${TOP}"

dbLoadDatabase("./dbd/testCt08.dbd")
ct08_registerRecordDeviceDriver(pdbbase)

# This is a bogus IP address that will never connect
#drvAsynIPPortConfigure("IPPort", "164.54.160.220:20", 0, 0, 1);
# This is a real IP address that will connect
drvAsynIPPortConfigure("IPPort", "192.168.1.123:7777", 0, 0, 1);
#drvAsynIPPortConfigure("IPPort", "newport-xps12:5001 COM", 0, 0, 1);
ct08Configure("PORT1", "IPPort", NULL)
#asynSetTraceMask("PORT1",0,9)
asynSetTraceIOMask("PORT1",0,0x2)

dbLoadRecords("./db/ct08App.db","P=ct08:,R=asyn1,PORT=PORT1,ADDR=0,OMAX=80,IMAX=80")
iocInit()


Replies:
Re: A question on asyn application Torsten Bögershausen via Tech-talk

Navigate by Date:
Prev: Re: re2c on Windows Ralph Lange via Tech-talk
Next: Re: A question on asyn application Torsten Bögershausen via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024
Navigate by Thread:
Prev: Re: re2c on Windows Ralph Lange via Tech-talk
Next: Re: A question on asyn application Torsten Bögershausen via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024
ANJ, 22 Jan 2024 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·