Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

Does VISA have VXI-11 Server implement to serve the interrupt channel for SRQ?

Hi Makoto,

sData is binary (copied from pcData), and sHexData is human readable for debug display.

The stream << is an overload operator for send() of the ClientSocket Class, and

the stream >> is an overload operator for the recv().  See code below.

 

const ClientSocket& ClientSocket::operator << ( const std::string& s ) const
{
 if ( ! Socket::send ( s ) )
 {
  throw SocketException ( "Could not write to socket." );
 }

 return *this;

}


const ClientSocket& ClientSocket::operator >> ( std::string& s ) const
{
 if ( ! Socket::recv ( s ) )
 {
  throw SocketException ( "Could not read from socket." );
 }

 return *this;
}

and Socket Class is a base class of the ClientSocket class and has member functions: create, bind, listen, accept, connect, send, recv,...

0 Kudos
Message 11 of 21
(3,545 Views)

Let me point out two more things about the following code:

<<<
for ( int i = 0; i < (int) sizeof(tdsIntrSrqData); i++)
{
sData += pcData[i];
sprintf(acTemp, "%02X", pcData[i]);
if ( i % 4 == 0 )
  sHexData += "\n\t";
sHexData += acTemp;
}

DEBUG_INFO("device_intr_srq_1: sData to send to NI-VISA: >>>>>>>>>>>>>>>>>>>>>>>>>>>>%s",
sHexData.c_str());
//Send data to TCP Socket
*s_pobjTcpClientInterrupt << sData;
>>>
 
(1) I now understand sData contains the same binary image of original tdsIntrSrqData struct, though the type is string.  When Socket::recv ( s ) trys to send the given string, how will be the byte-length decided?  Doesn't Socket::recv() terminate when 0x00 code is encountered? Or,  does Socket::recv() strictly send out the string's true byte-length (ignoring 0x00 code)?
 
(2) The above FOR loop iterates the full struct length of tdsIntrSrqData, because the FOR loop specifies sizeof(tdsIntrSrqData) regardless  handle_val[40] content.  However, handle_val[40] field of DeviceSrqParms is actually opaque length (variable length) data, which length is specified by handle_len field.  Therefore actual socket-send length is not always sizeof(tdsIntrSrqData) bytes. If the handle_val[40] contains less than 40-bytes (or , handle_len < 40), the actual socket-send length must be shorter, therefore the length shall be up to the content.  Plus, when handle_len is not multiple of 4, the actual socket-send length must be adjusted in order to align with 4-byte alignment, by adding 1..3 bytes of padding. This is because any ONC RPC message/response must be 4-byte aligned.
 
Message 12 of 21
(3,539 Views)

(1). when using operator (+=), the data size dynamically allocate in std::string, so the data size based on the memory size and could be read from member function size(), length(), or capacity().  It's not like the data type char *, the length is based on the null terminated string.  So, we use send ( m_sock, sData.c_str(), sData.size(), MSG_NOSIGNAL );

(2). The data I send back is exactly 40 bytes long as defined below, so I don't have to handle the 4-byte alignment:

The first 24 bytes received from VISA, and 26 bytes padding of zero.  The newly declare variable structure tdsSrqData has to do the memset(&SrqData, 0, sizeof(SRQ_Data));

struct SRQ_Data
{
 int  i32ProcId;
 int  i32Pointer;
 int  i32EventType; //NI-VISA hard coded this value to 0x3FFF200B
 int  i32LinkId;
 int  i32IpAddr;
 int  i32Context;
 char acZero[16];  // size of SRQ data is 40 bytes so 16 = 40 - 24 (the size of the 6 integers above)
};SRQ_Data SRQ_Data;

This data structure is useful for displaying, and usage.  the handle_val and this data structure could be exchange using type-casting. 

ptdsSRQ_Data =  (SRQ_Data *) (ptdsDeviceSrqParms->handle.handle_val);

ptdsDeviceSrqParms->handle.handle_val = (char *) ptdsSRQ_Data;

 

0 Kudos
Message 13 of 21
(3,530 Views)

Hi Dominator,

 

I am also trying to establish interrupt channel with NI-Max and This tread is very helpful for me.

I am able to establish interrupt channel with NI-Max client but still I am not getting VI_EVENT_SERVICE_REQ  event at NI-Visa client side  and viWaitonEvent() function giving timeout.

 

I have created new thread for my issue: -

http://forums.ni.com/t5/Instrument-Control-GPIB-Serial/How-to-create-the-VXI11-interrupt-channel-whi...

 

Please help.

0 Kudos
Message 14 of 21
(3,058 Views)

Hi C++Coder,

Do you have the function device_intr_srq_1() to handle the sending back the package that NI-VISA send you?

 

void * device_intr_srq_1(Device_SrqParms *argp, CLIENT *clnt)
{
    static char                     *clnt_res;
    static uint32_t                    ui32XId = 1;
    static VISA_SRQ_PACKAGE_DATA_t     *ptdsIRQ_Data =  (VISA_SRQ_PACKAGE_DATA_t *) (argp->handle.handle_val);
    bool                            bIsNetworkOrdered;

    bIsNetworkOrdered = LXI_GetNetworkOrder();
   
    memset((char *)&clnt_res, 0, sizeof(clnt_res));
    if (clnt_call (clnt, device_intr_srq,
        (xdrproc_t) xdr_Device_SrqParms, (caddr_t) argp,
        (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
        s_tdsTimeValTimeout) != RPC_SUCCESS)
    {
        DEBUG_INFO("device_intr_srq_1: Fail to sent package Device_SrqParms");
        return (NULL);
    }

    DEBUG_INFO("device_intr_srq_1: clnt_call() success");
    INTR_SRQ_DATA                tdsIntrSrqData;
    uint32_t                    ui32Length = (sizeof( INTR_SRQ_DATA ) - 4) | 0X80000000;

    //Create RPC Header
    tdsIntrSrqData.tdsRPC_Send_Header.length = BYTES_ORDER(bIsNetworkOrdered, ui32Length);
    tdsIntrSrqData.tdsRPC_Send_Header.xid = BYTES_ORDER(bIsNetworkOrdered, ui32XId++);
    tdsIntrSrqData.tdsRPC_Send_Header.msg_type = MSG_TYPE_SEND;
    tdsIntrSrqData.tdsRPC_Send_Header.rpcvers = BYTES_ORDER(bIsNetworkOrdered, 2);
    tdsIntrSrqData.tdsRPC_Send_Header.prog = BYTES_ORDER(bIsNetworkOrdered, DEVICE_INTR);
    tdsIntrSrqData.tdsRPC_Send_Header.vers = BYTES_ORDER(bIsNetworkOrdered, DEVICE_INTR_VERSION);
    tdsIntrSrqData.tdsRPC_Send_Header.proc = BYTES_ORDER(bIsNetworkOrdered, device_intr_srq);
    memset(tdsIntrSrqData.tdsRPC_Send_Header.auth, 0, sizeof(tdsIntrSrqData.tdsRPC_Send_Header.auth));
    //Append stored SRQ data
    memcpy(&tdsIntrSrqData.tdsDevSrqData.handle.handle_val, argp->handle.handle_val, sizeof(DeviceSrqParms));
    tdsIntrSrqData.tdsDevSrqData.handle.handle_len = BYTES_ORDER(bIsNetworkOrdered, argp->handle.handle_len);
       
    char *pcData = (char *) &tdsIntrSrqData;
    try
    {
        std::string sData = "";
        for ( int i = 0; i < (int) sizeof(tdsIntrSrqData); i++)
        {
            sData += pcData[i];
        }

        *pobjTcpClientInterruptSocket << sData;
    }
    catch ( SocketException& )
    {
        std::cout << "Send data failed\n";
    }

    clnt_res = tdsIntrSrqData.tdsDevSrqData.handle.handle_val;

    DEBUG_INFO("device_intr_srq_1: Success: clnt_res=%p", &clnt_res);
   
    return ((void *)&clnt_res);
}    // End device_intr_srq_1

0 Kudos
Message 15 of 21
(3,056 Views)

Hi Dominator,

 

Thanks for response!

 

Yes I have device_intr_srq_1() function and it is being called manually when RQS bit is set. It sends the msg which contains rpc header + Device_SrqParms . Might be I am doing some silly mistake. Let me try with your code.

  

 I have some questions please help me in reslving the same:-

 

Please let me know from where you get information about RPCHDR? I haven’t found any doc which describes this message format for NI-VISA?

 

What is VISA_SRQ_PACKAGE_DATA_t which you are using in your device_intr_srq_1()?

 

Thanks

0 Kudos
Message 16 of 21
(3,045 Views)

Hi C++Coder,

Do you work on LXI for your company?

 

The data structure RPCHDR and VISA_SRQ_PACKAGE_DATA_t are captured using NI-Spy when SRQ Interrupt is enabled and sent to VXI-11 Client, that is where it got it from, and I use variable ptdsIRQ_Data for displaying purposes only which I removed in this thread.  Here is the data structure defined:

 

//Enable Data structure passes in to be returned to requester if there is SQR interrupted.
struct VISA_SRQ_PACKAGE_DATA_t
{
    int        i32ProcId;
    int        i32Pointer;
    int        i32EventType;    //NI-VISA hard coded this value to 0x3FFF200B
    int        i32LinkId;
    int        i32IpAddr;
    int        i32Context;
    char    acZero[16];        // size of IRQ data is 40 bytes so 16 = 40 - 24 (the size of the 6 integer above)
};
typedef struct VISA_SRQ_PACKAGE_DATA_t VISA_SRQ_PACKAGE_DATA_t;

0 Kudos
Message 17 of 21
(2,971 Views)

Hi Dominator,

Sorry for late reply, I was out of town for some days.

 

>Do you work on LXI for your company?

  Yes, this is my first project.

> Please let me know from where you get information about RPCHDR?

Let me rephrase my question:- how do you know that we have to send RPCHDR as socket messge. Is there any standard document which explain this requirement?

 

ViEnableEvent is executed successfully but viWaitOnEvent is still giving time out.

> 1.  viWaitOnEvent (TCPIP0::172.21.111.220::... (0x027C0580), SERVICE_REQ, 300, 0, 0x00000000)

> Process ID: 0x000002D4         Thread ID: 0x00001394

> Start Time: 07:57:36.218       Call Duration 00:00:00.313

> Status: 0xBFFF0015 (VI_ERROR_TMO)

 

Might be the message which I am sending to Ni-Client is not correct.  Could you please verify my socket message mentioned below.

 

tdsIntrSrqData.tdsRPC_Send_Header.length 140928
tdsIntrSrqData.tdsRPC_Send_Header.xid 16777216
tdsIntrSrqData.tdsRPC_Send_Header.msg_type 0
tdsIntrSrqData.tdsRPC_Send_Header.rpcvers 33554
tdsIntrSrqData.tdsRPC_Send_Header.prog 29700275
tdsIntrSrqData.tdsRPC_Send_Header.vers 16777216
tdsIntrSrqData.tdsRPC_Send_Header.proc 41943040
tdsIntrSrqData.tdsRPC_Send_Header.auth 00D8F67C
tdsIntrSrqData.tdsDevSrqData.handle.handle_len
tdsIntrSrqData.tdsDevSrqData.handle.handle_val
        FFFFFF80 00 00 54
        00 00 00 01
        00 00 00 00
        00 00 00 02
        00 06 07 FFFFFFB1
        00 00 00 01
        00 00 00 19
        00 00 00 00
        00 00 00 00
        00 00 00 00
        00 00 00 00
        00 00 00 28
        00 00 02 FFFFFFD4
        02 7C 05 FFFFFF80
        3F FFFFFFFF 20 0B
        00 00 00 01
        0A 78 01 08
        00 00 00 00
        00 00 00 00
        00 00 00 00
        00 00 00 00
        00 00 00 00
ptdsIRQ_Data->i32ProcId     -738066432
ptdsIRQ_Data->i32Pointer    -2147124222
ptdsIRQ_Data->i32EventType  186711871
ptdsIRQ_Data->i32LinkId     16777216
ptdsIRQ_Data->i32IpAddr     134313994
ptdsIRQ_Data->i32Context    0
ptdsIRQ_Data->acZero


 

I am running VXI server and NI-client on my PC. There is no additional h/w attached with my PC.

 

Please find the attached wireshark snap shots logs and my code.

 

 

Thanks

Download All
0 Kudos
Message 18 of 21
(2,940 Views)

Hi C++Coder,

Here is the link to document proviced by ICS Electronics: "SRQ HANDLING WITH A VXI-11 INTERRUPT CHANNEL ON ICS's MODEL 8065 ETHERNET-TO-GPIB CONTROLLER"

The RPC Header mentions on page 2, last paragraph on the right column.

http://www.icselect.com/pdfs/ab80_4.pdf

 

I don't have time to go over your code, I downloaded, but with weir code (html, xml ??), but I can say the data you have is wrong, the RPC header is garbage, but the handle_val contains RPC header.

 

 

The handle_len should be 40

The handle_val suppose to have 40 bytes,  so your data is shifted by the RPC Header block.

        00 00 02 D4        <== Process ID
        02 7C 05 80        <== Pointer
        3F FF 20 0B       <== Event Type
        00 00 00 01        <== Link ID
        0A 78 01 08       <== IP Address
        00 00 00 00        <== Context
        00 00 00 00        <== Padded Zeros
        00 00 00 00
        00 00 00 00
        00 00 00 00

0 Kudos
Message 19 of 21
(2,930 Views)

Hi NI crew,

 

Following this thread, I come to you since I believe I implement SRQ mechanism as you describe in this thread.

 

However, I still encounter 2 issues:

 

when my VXI11 client is calling the following method:

 

ViStatus status = viEnableEvent (m_instr, VI_EVENT_SERVICE_REQ, VI_QUEUE, VI_NULL);

 

Then my VXI11 servers "Device_Error *device_enable_srq_1( Device_EnableSrqParms enableSrqParms )" receive a handle value that match the expected cvontent:

 

00 00 16 20

08 00 FF 88

3F FF 20 0B // expected hard coded value

00 00 03 E8

AC 1D 0C 41 // VXI11 client IP @ is 172.29.12.65

00 00 00 00 // context

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // padded zeros.

 

First issue, however, the handle length is not 40, but some random value ...

 

Then, My VXI11 server receives this "device_enable_srq_1" call, store the handle and cast it in a SRQ_Data structure as follows:

 

typedef struct _SRQ_Data
{
int i32ProcId;
int i32Pointer;
int i32EventType; //NI-VISA hard coded this value to 0x3FFF200B
int i32LinkId;
int i32IpAddr;
int i32Context;
char acZero[16]; // size of SRQ data is 40 bytes so 16 = 40 - 24 (the size of the 6 integers above)
} SRQ_Data;

 

then I set each integer in network endianess (htonl( XXX )

 

and finally send that 40 byrte long payload through the socket based INTR channel.

 

But on the VXI11 client side, the SRQ event is not detected, although I can see the TCP packet leaving the VXI11 server, and also arriving in the VXI11 client side. 

 

but I always get "status = viWaitOnEvent (m_instr, VI_EVENT_SERVICE_REQ, timeout, &etype, &ehandle);"

 

time out ...

 

If you have any hint from similar previous experience, Id love to hear it

 

thanks for your support

 

Franck

 

 

 

0 Kudos
Message 20 of 21
(2,715 Views)