cancel
Showing results for 
Search instead for 
Did you mean: 

Receiving Can Messages. 70% of network traffic missing

Just Matt
Associate III
Posted on January 28, 2014 at 20:18

Hi,

I'm using a STM32F407VGT mcu. Also with the latest DSP lib pack from ST. The network has 2 nodes, and I'm attempting to capture the traffic between the nodes. 500kbps 75% SP. 30% bus load. One node queries the other for some data, the responding node sends 145 CAN Messages over the network. (I am using a 3rd party tool to capture the traffic) My following code only picks up 31 of those messages, and its sporadic. It does always catch the first Message correctly. (Then it endlessly loops) Here is my code, I call this code right after a query is made to a node. Is this the right way to approach this situation? All feedback welcome :)

CanRxMsg rxMessage;
CanRxMsg rxMessageArray[144];
int
loopCount = 0;
int
receiveCount = 144;
while
(loopCount < receiveCount)
{
if
(CAN_MessagePending(CANx, CAN_FIFO0) > 0)
{ 
//Receive the Message
CAN_Receive(CANx, CAN_FIFO0, &rxMessage);
rxMessageArray[loopCount] = rxMessage;
loopCount++;
}
}

#can #can
11 REPLIES 11
carl2399
Associate II
Posted on February 05, 2014 at 07:24

I had a look at the data sheet for the STM32F10x family (which is at hand), although I don't believe the STM32F4xx is any sort of downgrade on that.

It has two receive FIFOs, each of which can store 3 complete packets!

Let's go worst case, and see what happens:

Speed: 1Mbps

Utilisation: 100%

Packet Length: 1 byte of data. (Anything less would be a bit useless).

The number of bits required to make a minimum packet is 55bits. So, you would expect to see a packet every 55 microseconds (~18000 packets per second). On the up-side, you have the full 55 microseconds to get this packet out of the FIFO. In the case of the F4 that's 55 microseconds at 168MHz or 9240 clocks. This is HEAPS to get the data out of the CAN peripheral and into a RAM based FIFO. I've done task switching on the F4 at 1M task switches per second! 

Your situation is more leisurely, being half the baud rate. Also I assume that their is more data per packet than just a single byte. Both these items will reduce the number of packets that require servicing.

While your CAN bus is only 30% utilised, I assume that what you meant to say is that 30% of the time it is 100% utilised and the other 70% is 0% utilised.

One thing worth checking for in your code (and also the STM32 library code) is that you're not accidentally resetting the FIFO every time you process a packet. For example: are you sending out some sort of ''ACK'' response that is resetting all the FIFO's as part of its process. It may be that the problem is not in any of the code you've shown us so far. Specifically check possible assignments to Bit 15 of the CANx->MCR register.

BTW I've never had issues with losing packets on a 1Mbps CAN bus, and I don't bother with using the filters.

jpeacock2399
Associate II
Posted on February 05, 2014 at 16:19

Check the CAN_RFxR registers, FOVR flag to determine if your FIFO is being overrun.  If it's set that explains why you are losing messages.  Messages are arriving faster than they can be processed.

In my CANopen application the CAN RX interrupts drain the incoming message FIFOs into one in-memory queue that's large enough to handle a burst of TPDO messages from several nodes after a SYNC (somewhat similar to what you are doing).  A completion task is unblocked as soon as messages are posted to the queue.  The completion task extracts each message in time sequence from the queue and processes the data. 

This separates data collection from processing time.  All the messages in a burst are captured in a FIFO type buffer and can be processed at leisure during the time between data collection points when the CAN bus is mostly idle.

I also use filters to direct incoming messages into both RX FIFOs.  This doubles the hardware buffering and reduces interrupt overhead on the controller.  During an RX interrupt I collect up to three messages from the hardware FIFO at one time instead of an interrupt per message...one third the overhead.

An added benefit from split RX FIFOs is that higher priority messages (such as the CANopen SYNC or NMT-EC heartbeat) can be directed to one FIFO, which in turn inserts the messages at thehead of the message queue so they are processed at high priority.  This is especially important if you're messages contain safety related data (such as CANopen SRDO or GFC messages) that must be processed as soon as possible.

I do the same thing for outgoing messages.  The TX interrupt drains a queue of pending messages so that the application can post large numbers of messages (such as the TPDO burst after a SYNC) without any delays waiting for an empty TX mailbox.

DMA isn't really useful with CAN messages because data is often processed out of sequence, that's why the dual RX FIFO structure is used instead of a DMA channel.

   Jack Peacock