11-24-2015 09:45 AM
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!
11-25-2015 07:39 AM
Hi kringe,
could you please post the code you implemented for that?
Best regards,
Melanie
11-25-2015 09:16 AM - edited 11-25-2015 09:17 AM
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).
11-25-2015 09:23 AM
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
11-25-2015 09:37 AM
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).
11-25-2015 10:37 AM
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
11-25-2015 01:07 PM
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!
11-26-2015 02:03 AM
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
11-27-2015 05:08 AM
Ok thank you! I will give it a try when I find the time.