Automotive and Embedded Networks

cancel
Showing results for 
Search instead for 
Did you mean: 

How to send reliable via ncWrite on an NI USB-8473s?

Hello!

 

For a project we are using NI USB-8473s adapters talking to an embedded platform with baudrate 1MB. We access the bus by a C program using the Frame API for C.

When we are sending data with high load (such as SDO blocktransfers) we are experiencing that some messages (perhaps 1 out of 10000) passed to ncWrite are not sent, though ncWrite returns Zero even for these particular frames.

NC_ATTR_WRITE_Q_LEN is 50, which should never be reached because we wait for a CAN-response after sending max. 32 messages (and increasing it didn't help).

 

As a workaround we are calling a ncWaitForState with NC_ST_WRITE_SUCCESS as DesiredState after each ncWrite. This fixes the problem but slows down the bus by a factor 8 (time between two 8-byte-DLC messages rises from 125us to 1ms).

 

Is there a way to send all messages reliable, but with full speed at 1MB?

 

Thank you in advance for your help!

 

0 Kudos
Message 1 of 9
(5,409 Views)

Hi kringe,

 

could you please post the code you implemented for that?

 

Best regards,

Melanie

Best regards,
Melanie Eisfeld
Senior Applications Engineer, National Instruments Germany
Certified LabVIEW Developer
Certified TestStand Architect
0 Kudos
Message 2 of 9
(5,391 Views)

Of course!

 

Initialization:

AttrIdList[0] =         NC_ATTR_BAUD_RATE;
AttrValueList[0] = 1000000;
AttrIdList[1] =         NC_ATTR_START_ON_OPEN;
AttrValueList[1] =      NC_TRUE;
AttrIdList[2] =         NC_ATTR_READ_Q_LEN;
AttrValueList[2] =      150;
AttrIdList[3] =         NC_ATTR_WRITE_Q_LEN;
AttrValueList[3] =      50;
AttrIdList[4] =         NC_ATTR_CAN_COMP_STD;
AttrValueList[4] =      0;
AttrIdList[5] =         NC_ATTR_CAN_MASK_STD;
AttrValueList[5] =      NC_CAN_MASK_STD_DONTCARE;
AttrIdList[6] =         NC_ATTR_CAN_COMP_XTD;
AttrValueList[6] =      0;
AttrIdList[7] =         NC_ATTR_CAN_MASK_XTD;
AttrValueList[7] =      NC_CAN_MASK_XTD_DONTCARE;

tStatus = fpncConfig("CAN0", 8, AttrIdList, AttrValueList);
if(tStatus < 0)
{
  return false;
}

tStatus = fpncOpenObject("CAN0", &tCanHandle);
if(tStatus < 0)
{
  return false;
}

ucErrorState = ERROR_NONE;

 

 

For each tx-message:

 

/* send one message */
tStatus = fpncWrite(tCanHandle, sizeof(tTxBuf), (void*)&tTxBuf);

/* on error sending failed, so return here */
if(tStatus < 0)
{
  ucErrorState = ERROR_TX;
  return;
}

tStatus = fpncWaitForState(tCanHandle, NC_ST_WRITE_SUCCESS, 50, &tState);
if(tStatus < 0)
{
  ucErrorState = ERROR_WAIT_TX;
}
else
{
  /* transmission successful -> CAN is ok */
  ucErrorState = ERROR_NONE;
}

 

The fp-calls are function-pointers to the corresponding API-Functions retrieved by GetProcAddress from nican.dll.

With fpncWaitForState everything is fine but slow, without I'm loosing some messages. Some printf-debugging prooved, that the lost messages were passed to fpncWrite and the function returned 0, but they never appeared on bus (we monitored this by another adapter using CANoe).

0 Kudos
Message 3 of 9
(5,388 Views)

Hi kringe,

 

can you tell or post the code, how the code in the second frame is called? Is it in a loop or in a callback, what are the conditions, it is called?

 

Best,

Melanie

Best regards,
Melanie Eisfeld
Senior Applications Engineer, National Instruments Germany
Certified LabVIEW Developer
Certified TestStand Architect
0 Kudos
Message 4 of 9
(5,381 Views)

The call is done in a loop. The init-code is called once after starting the application. Afterwards the application updates cyclic a CANopen-stack in an own task, which sends requests and processes the received responses. Each time the stack wants to send a message, the transmit-code is called in an own function where message to be transmitted is passed as parameter (NCTYPE_CAN_FRAME tTxBuf). At one cycle the stack won't send more than 32 messages because we have to wait for responses from the peer on CAN before we send more. So a transmit queue of 50 messages should be enough.

 

What I don't understand is, why ncWrite returns 0 but we see no message on bus. If there is an internal error or an overflow I think it should return an error or warning so we can handle it (e.g. by sending the message later on).

0 Kudos
Message 5 of 9
(5,376 Views)

Hi kringe,

 

thank you for describing the application in detail. I did some research on your information and found, this is an already reported issue with the driver.

 

What happens in the background is, the ncWrite ignores frames, if it is called to fast again. The wait function solves this issue, because it waits for every frame to be sent correctly.

 

However, there is no version for fix specified for this behavior. I added this request to the list of reports, so the priority is set higher.

 

Best regards,

Melanie

Best regards,
Melanie Eisfeld
Senior Applications Engineer, National Instruments Germany
Certified LabVIEW Developer
Certified TestStand Architect
Message 6 of 9
(5,365 Views)

Thank you very much for your help! I will look out for driver updates.

 

If there is a faster workaround than ncWaitForState this is also appreciated:)

 

Best Regards!

0 Kudos
Message 7 of 9
(5,358 Views)

Hi kringe,

 

thank you for your reply.

 

A solution you can try out is to read back messages from the bus and see, if one is lost. If so, you can continue sending at the lost message. It depends a lot on your hardware and sending rate, if this solution can be faster, but you can give it a try.

 

Best regards,

Melanie

Best regards,
Melanie Eisfeld
Senior Applications Engineer, National Instruments Germany
Certified LabVIEW Developer
Certified TestStand Architect
0 Kudos
Message 8 of 9
(5,342 Views)

Ok thank you! I will give it a try when I find the time.

0 Kudos
Message 9 of 9
(5,328 Views)