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: Re:RE: A question on asyn application
From: cxy via Tech-talk <tech-talk at aps.anl.gov>
To: "Mark Rivers" <rivers at cars.uchicago.edu>
Cc: "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Tue, 23 Jan 2024 11:19:28 +0800 (CST)
Hello Mark and Toesten,
         I  shrink the db tobe 3 params, attatched again. It uses the <path>/testAsynPortDriverApp structure, the string record is like this:
 record(stringin,"$(P)Ver")
{
   field(DESC,"Firmware version")
   field(DTYP, "asynOctetRead")
   field(INP, "@asyn($(PORT),$(ADDR)) OCTET_DATA")
   field(SCAN,"I/O Intr")
}

The bo record uses DTYP asynIne32:
record(bo,"$(P)Start")
{
   field(DESC, "start counter")
   field(DTYP, "asynInt32")
   field(OUT, "@asyn($(PORT),$(ADDR)) START")
   field(ZNAM, "0")
   field(ONAM, "1")
}
With asynReport 3 PORT1 after IOC has booted, it prompt:
epicsEnvSet("SNCSEQ","/opt/epics/seq")
epicsEnvSet("EPICS_BASE","/opt/epics/base")
cd "/opt/epics/asyn"
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);
dbLoadRecords("./db/ct08App.db","P=ct08:,R=asyn1,PORT=PORT1,ADDR=0,OMAX=80,IMAX=80")
ct08Configure("PORT1", "IPPort", NULL)
connection status: 0
#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()
Starting iocInit
############################################################################
## EPICS R7.0.6.1
## Rev. 2023-04-20T07:25+0000
############################################################################
ct08:Start devAsynInt32::initCommon enum registerInterruptUser asynManager:getInterruptPvt Driver does not support interrupts on interface asynEnum
ct08:Stop devAsynInt32::initCommon enum registerInterruptUser asynManager:getInterruptPvt Driver does not support interrupts on interface asynEnum
iocRun: All initialization complete
asynReport 3 PORT1
PORT1 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 0 exceptionNotifys 0
    traceMask:0x1 traceIOMask:0x2 traceInfoMask:0x1
    interposeInterfaceList
        asynOctet pinterface 0x7fe1a2dde480 drvPvt 0x21594d0
    interfaceList
        asynCommon pinterface 0x7fe1a2dded30 drvPvt 0x2157d40
        asynDrvUser pinterface 0x7fe1a2ddeac0 drvPvt 0x2157d40
        asynOctet pinterface 0x7fe1a2ddec00 drvPvt 0x2157d40
        asynInt32 pinterface 0x7fe1a2dded00 drvPvt 0x2157d40
        asynFloat64 pinterface 0x7fe1a2ddec60 drvPvt 0x2157d40
        asynEnum pinterface 0x7fe1a2ddeae0 drvPvt 0x2157d40
Port: PORT1
  Timestamp: <undefined>
  Input EOS[0]: 
  Output EOS[0]: 
Parameter list 0
Number of parameters is: 3
Parameter 0 type=string, name=OCTET_DATA, value is undefined
Parameter 1 type=asynInt32, name=START, value is undefined
Parameter 2 type=asynInt32, name=STOP, value is undefined

I make two test.
one is s simple test, I try to use writeRead() function to send "VER?" to the device, then read the version string. But it prompt: devAsynOctet:getIoIntInfo error calling registerInterruptUser asynManager:getInterruptPvt Driver does not support interrupts on interface asynOctet.
Another is to use  pasynOctetSyncIO->writeRead  directly to send ''VER?" and get the readback buffer, the whole IOC stopped directly with out any eror.
   status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, &eomReason);
   status=(asynStatus)setStringParam(OctetData,readBuffer);

Is there anything missed or confused in the file?


Looking forward to your reply.
Than you very much.


Yoon


At 2024-01-23 02:09:48, "Mark Rivers" <rivers at cars.uchicago.edu> wrote:

Hi Torsten and Yoon,

 

Yoon’s original message DOES have the asynEnumMask in both the interface mask and the interrupt mask.  This is from his original message, I have added red highlighting.

 

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*/

 

So I don’t understand why that message is appearing.

 

Yoon, please send the output of this command after the IOC has booted:

 

asynReport 3 PORT1

 

That will show what interfaces are configured to do callbacks.
 
Mark
 

 

 

From: Tech-talk <tech-talk-bounces at aps.anl.gov> On Behalf Of Torsten Bögershausen via Tech-talk
Sent: Monday, January 22, 2024 12:45 AM
To: cxy <ycx810212 at 163.com>; tech-talk at aps.anl.gov
Subject: Re: A question on asyn application

 

I think you are missing this mask:

 

| asynEnumMask,

 

here:

 

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*/

{

 

 

From: Tech-talk <tech-talk-bounces at aps.anl.gov> on behalf of cxy via Tech-talk <tech-talk at aps.anl.gov>
Reply to: cxy <ycx810212 at 163.com>
Date: Monday, 22 January 2024 at 07:18
To: "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Subject: A question on asyn application

 

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

#include <asynInt32.h>
#include <asynFloat64.h>
#include <asynOctet.h>
#include <asynDrvUser.h>
#include "asynPortDriver.h"
#include <asynOctetSyncIO.h>
#include <asynStandardInterfaces.h>

#define MAX_MESSAGE_SIZE 80
#define TIMEOUT 1.0
using namespace std;

#define P_VersionString "OCTET_DATA" /*asynOctetRead*/
#define P_StartString "START" /*asynInt32*/
#define P_StopString "STOP" /*asynInt32*/

class ct08: public asynPortDriver {
public:
    ct08(const char *portName, const char *IPPortName, const char *outputString);    
    /*Method overwritten from asynPortDriver*/
    virtual asynStatus writeFloat64(asynUser* pasynUser, epicsFloat64 value);
    virtual asynStatus writeInt32(asynUser* pasynUser, epicsInt32 value);
    virtual asynStatus writeOctet(asynUser* pasynUser, const char* data, size_t maxchars, size_t *nActual);
    virtual asynStatus readOctet(asynUser* pasynUser, const char* data, size_t maxchars, size_t *nActual, int *eom);

    /*global parameter-int index*/
   // int P_Version;
    int OctetData;
    int P_Start;
    int P_Stop;

    /*our method*/
    void pollerTask(void);

protected:
  /**values used for pasynUser->reason, and indexex into the parameter liberay.*/

private:
    asynUser *pasynUserIPPort_;
    const char *outputString_;
    char writeBuffer[MAX_MESSAGE_SIZE];
    char readBuffer[MAX_MESSAGE_SIZE];
};

record(stringin,"$(P)Ver")
{
   field(DESC,"Firmware version")
   field(DTYP, "asynOctetRead")
   field(INP, "@asyn($(PORT),$(ADDR)) OCTET_DATA")
   field(SCAN,"I/O Intr")
}

record(stringout,"$(P)VerOut")
{
   field(DESC,"Firmware version")
   field(DTYP, "asynOctetWrite")
   field(OUT, "@asyn($(PORT),$(ADDR)) OCTET_DATA")
   field(VAL,"VER?")
}

record(bo,"$(P)Start")
{
   field(DESC, "start counter")
   field(DTYP, "asynInt32")
   field(OUT, "@asyn($(PORT),$(ADDR)) START")
   field(ZNAM, "0")
   field(ONAM, "1")
}

record(bo,"$(P)Stop")
{
   field(DESC, "stop counter")
   field(DTYP, "asynInt32")
   field(OUT, "@asyn($(PORT),$(ADDR)) STOP")
   field(ZNAM,"0")
   field(ONAM, "1")
}


/*
 * 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 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 |asynEnumMask |asynDrvUserMask,/* Interface mask */
                    asynOctetMask | asynInt32Mask | asynFloat64Mask |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, &OctetData);
    createParam(P_StartString, asynParamInt32, &P_Start);
    createParam(P_StopString, asynParamInt32, &P_Stop);

    outputString_ = epicsStrDup(outputString);

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

/** 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);
        pasynOctetSyncIO->setInputEos(pasynUserIPPort_,"\r\n",2);
        pasynOctetSyncIO->setOutputEos(pasynUserIPPort_,"\r\n",2);
        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); 
    }


    /* 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::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::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";
  
  printf("function=%s\n",function);  
  if(function==OctetData)
  {
   sprintf(writeBuffer, "%s", "VER?");
   printf("data is :%s, writterBuffer is:%s\n",data, writeBuffer);
   status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, &eomReason);
   status=(asynStatus)setStringParam(OctetData,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=OctetData)
  {
    sprintf(writeBuffer, "%s", "VER?\r\n");
    status=pasynOctetSyncIO->writeRead(pasynUserIPPort_, writeBuffer, sizeof(writeBuffer), readBuffer, sizeof(readBuffer), TIMEOUT, nActual, &nRead, eom);
    status=(asynStatus)setStringParam(OctetData,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: RE: A question on asyn application Ralph Lange via Tech-talk
References:
A question on asyn application cxy via Tech-talk
Re: A question on asyn application Torsten Bögershausen via Tech-talk
RE: A question on asyn application Mark Rivers via Tech-talk

Navigate by Date:
Prev: RE: A question on asyn application Mark Rivers via Tech-talk
Next: Re: RE: A question on asyn application Ralph Lange 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: A question on asyn application Mark Rivers via Tech-talk
Next: Re: RE: A question on asyn application Ralph Lange 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 ·