From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Automotive and Embedded Networks

cancel
Showing results for 
Search instead for 
Did you mean: 

CAN FD Read and Write frame using C API

Solved!
Go to solution

 

 

 

//following code snippet from nixnet.h file

#define  nxInternal_PadPayload(paylod) \
            ( (u16)(paylod) ? (( (u16)(paylod) + 7) & 0x07F8) : 8)

#define  nxFrameFixed_t(payld) \
            struct { \
               nxTimestamp_t       Timestamp; \
               u32                 Identifier; \
               u8                  Type; \
               u8                  Flags; \
               u8                  Info; \
               u8                  PayloadLength; \
               u8                  Payload[ nxInternal_PadPayload(payld) ]; \
            }

// -----------------------------------------------------------------------------
// If you are using CVI version 2009 or earlier, you may see a compile error for
// this line. Upgrade to CVI version 2010 or later for the fix, disable the
// "Build with C99 extensions" compiler option in the "Build Options" dialog of
// CVI or edit your copy of the header file to resolve the error.
// -----------------------------------------------------------------------------
typedef nxFrameFixed_t(8) nxFrameCAN_t;
typedef nxFrameFixed_t(8) nxFrameLIN_t;
typedef nxFrameFixed_t(1) nxFrameVar_t;

 

Even though "nxFrameVar_t" restrict the payload array to 8 you suggest just jam in whatever my payload length is? (that doen't look like a good way to handle variable length)

 

 

 

   u8 l_MyBuffer[512];
   nxFrameVar_t * l_MyFramePtr;
   u32 l_NumBytes;


//Snippet for ReadFrame
{
   g_Status = nxReadFrame (g_SessionRef,l_MyBuffer,sizeof(l_MyBuffer),0,&l_NumBytes);

      
   l_MyFramePtr = (nxFrameVar_t *)(l_MyBuffer);

      // myFramePtr iterates to each frame. When it increments
      // past the number of bytes returned, we reached the end.
      while ( ((u8 *)(l_MyFramePtr) - (u8 *)l_MyBuffer) < l_NumBytes)
      {
         // print timestamp, ID and payload
         PrintTimestamp(&l_MyFramePtr->Timestamp);
         printf("%s\t", g_timeString);
         printf("%d\t ",l_MyFramePtr->Identifier);
         for(i=0;i<l_MyFramePtr->PayloadLength;i++)
         {
            printf("%d ",l_MyFramePtr->Payload[i]); 
         }
         printf("\n");

         // Go to next variable-payload frame.
         l_MyFramePtr = nxFrameIterate(l_MyFramePtr);
      }
}

//Snippet for Write frame
{
        l_MyFramePtr=(nxFrameVar_t*)l_MyBuffer;

        //Here we set each of the frames parameters.
        //There are ways to programmatically get these parameters using 
        //the objects properties
        l_MyFramePtr->Timestamp=0;
        l_MyFramePtr->Flags=0;
        l_MyFramePtr->Identifier=1; 
        l_MyFramePtr->Type=nxFrameType_CAN_Data;
        l_MyFramePtr->PayloadLength=16;
        for(j=0;j<16;j++)
        {
            l_MyFramePtr->Payload[j]=j;
        }

        l_MyFramePtr = nxFrameIterate(l_MyFramePtr);
        l_MyNumberOfBytesForFrames = ((u8 *)l_MyFramePtr - (u8 *)l_MyBuffer);


        g_Status = nxWriteFrame(g_SessionRef,l_MyBuffer,
        l_MyNumberOfBytesForFrames,10);	

}

 

 

 

 

 

 

0 Kudos
Message 11 of 20
(5,511 Views)

The fact that it is padded to 8 is odd, but the way that C does variable length arrays is exactly that way. Typically you would define something like:

 

typedef struct myVarLengthArray

{

   int size;

   myDataType pVarArray[1];

} myVarLengthArray;

 

(note: C99 allows you to use [0] for variable length, but almost all compilers support [1] since C doesn't enforce overindexed arrays)

 

To use it, you would do somehting like:

char pMyArray[kMySize];

myVarLengthArray pArray = (myVarLengthArray *)pMyArray;

 

Now, you can use pArray how as the struct with the first 4 bytes being 'size', and kMySize-4 being used for the pVarArray. Or, if this is a longer array, you can set it as needed. For example, it could be (shown in big endian to be easier):

 

// Size              Data              Size              Data    Size                 Data   .. (etc)

00000004     01020304    00000002   0102      00000001     FF

 

In this case, you need to know how to traverse the array of variable length arrays since each element is of variable lenght. Other programming languages may do it differently, but this is how you would do it in C.

Message 12 of 20
(5,505 Views)

Thanks GPIB_Guru for elaborating on variable array length. The earlier approach for using "nxFrrameVar_t" struct and jamming in variable data into the payload array also works.

 

One issue I am running in to now is for Read Frame timeout parameter. When I pass parameter greater than "0" I get "-1074384886" error, by definition of this error if I increase my timeout I still get this error. 

Also, when I look at the NI I/O trace log entry for "nxReadFrame" call I see that the buffer has right value and the number of bytes are also correct.

 

 

g_Status = nxReadFrame (g_SessionRef,l_MyBuffer,sizeof(l_MyBuffer),0.005,&l_NumBytes); 

 

 

Any thoughts on this issue?

0 Kudos
Message 13 of 20
(5,474 Views)

Could you attach the I/O trace log? Preferably, configure I/O trace to log directly to a file (vs. logging in the screen and saving it).

0 Kudos
Message 14 of 20
(5,452 Views)

Attached is NI I/O trace file with create session of  ":can_fd:", data 4 bytes (00 00 00 28), variable buffer length 512.

 

 

Line #17  "> 17. nxReadFrame (0x00000002, {0xD4F1B594,0x01D110E0,...}, 512, 0.005, 24)
> Process ID: 0x000027EC Thread ID: 0x00001CBC
> Start Time: 13:56:40.174 Call Duration 00:00:00.006
> Status: -1074384886 (0xBFF6300A)

 

 

Note: Also same setup works if I set the buffer length equal to the length of data. For example : if 4 byte data then my buffer should be 24 byte

 

Line #39. nxReadFrame (0x00000002, {0x361A29E2,0x01D110F4,...}, 24, 0.005, 24)
Process ID: 0x00002188 Thread ID: 0x00001B30
Start Time: 16:15:23.615 Call Duration 00:00:00.006
Status: 0 (0x0)

 

0 Kudos
Message 15 of 20
(5,450 Views)
Solution
Accepted by topic author mahajan24

I will admit I am a bit rusty -

 

I am looking at the 4byteData_512Buffer file first.

1) Looking at the nxReadState calls, it appears that you are reading the nxState_CANComm  state and it is returning a 0, which seems reasonable (error active, nothing else set).

2) Looking at your nxReadFrame calls, the timeout is really small - it is in seconds and your timeout is 5ms. This is okay, assuming that 512 bytes is available. In 4-byte frames, this would mean that you would need to receive 22 frames (at 24 bytes/frame) before you would not get a timeout.

3) Looking at line 17, you are getting the timeout (because only 1 frame was written/received), but if you look at the *NumberOfBytesReturned field, you see 24, indicating that you did receive one frame.

 

In general, which it doesn't appear to be documented well, if you get a timeout that may not always be fatal. It means that you asked for N bytes withing M seconds. If you don't get that number of bytes, you get a timeout error. However, after M seconds, if P bytes were received, they will be returned. So, you can essentially note that a timeout error may be a warning if NumberOfBytesReturned is non-zero and treat those frames as valid.

 

If you plan to run with a small timeout (5ms), you may just run with no timeout (0) and just check the NumberOfBytesReturned field to see whether a frame was received or not. Although, I guess it doesn't matter. You can run with the timeout to slow down your program (so you don't just poll in a tight loop), but just realize that the timeout indicates that ALL of the requested data wasn't received, but some of it may be. If so, clear the error and process the frame.

 

------------------

 

Looking at the 24Buffer file, there is one write on line 37. The next read (line 39) returns the frame with no error. This is because you asked for 24 bytes and you received 24 bytes.

 

------

 

Hope this helps.

 

 

 

Message 16 of 20
(5,443 Views)

This certainly help me understand the reason for timeout.

 

So as my program polls continously for "nxReadFrame" and expects complete frame. So to handle this should I be setting my timeout to 0 and keep check on number of return bytes? Does setting timeout to 0 also makes sure complete frame is returned?

 

 

 

0 Kudos
Message 17 of 20
(5,436 Views)

 I think complete frames are always returned, but honestly, I am not certain. Perhaps someone else who knows could pipe in.

0 Kudos
Message 18 of 20
(5,432 Views)

Did you set the l_pFrame->PayloadLength = 64; ? As seen in below example:

//in globals.h 
nxFrameVar_t* l_pFrame;

//in main.c
// Get a pointer to the first frame's memory
l_pFrame = (nxFrameVar_t*)l_Buffer;


// Set each of the first frame's parameters (skipping the payload for now).
// There are ways to programmatically get these parameters
// using the objects properties. Here we hardcode them.
l_pFrame->Timestamp = 0;
l_pFrame->Flags = 0;
l_pFrame->Identifier = 5; //decimal arbitration id
l_pFrame->Type = nxFrameType_CAN_Data;
l_pFrame->PayloadLength = 64; //num of data bytes

// Iterate the pointer to the next frame
l_pFrame= nxFrameIterate(l_pFrame);

// Set the second frame's parameters (skipping the payload for now).
l_pFrame->Timestamp = 0;
l_pFrame->Flags = 0;
l_pFrame->Identifier = 6; //decimal arbitration id
l_pFrame->Type = nxFrameType_CAN_Data;
l_pFrame->PayloadLength = 64; //num of data bytes

// Get the actual size of the buffer used
l_pFrame= nxFrameIterate(l_pFrame);
l_NumberOfBytesForFrames = (u32)((u8*)l_pFrame - (u8*)l_Buffer);

 

0 Kudos
Message 19 of 20
(1,937 Views)

Hi Durkabaero,

This a a really old thread where I had issues setting up my drivers for CAN FD. I'm past this issue and some suggestions from GPIB_Guru helped.

0 Kudos
Message 20 of 20
(1,920 Views)