10-26-2015 02:31 PM
//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); }
10-26-2015 03:07 PM
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.
10-27-2015 03:50 PM
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?
10-28-2015 07:19 AM
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).
10-28-2015 07:28 AM - edited 10-28-2015 07:35 AM
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)
10-28-2015 08:04 AM
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.
10-28-2015 09:01 AM
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?
10-28-2015 09:05 AM
I think complete frames are always returned, but honestly, I am not certain. Perhaps someone else who knows could pipe in.
03-31-2021 05:06 PM
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);
04-01-2021 12:48 PM
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.