This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EK-TM4C123GXL: CAN FIFO Mode

Part Number: EK-TM4C123GXL

Hi All !

I have a working CANOpen stack for which I have developed the TIva driver. I'm running it on TIVA Launchpad (TM4C123G) However, currently this is working without using Tiva hardware FIFO.

I wanted to implement HW buffers, but I wasn't able to find a good example. The configuration of the FIFO is clear - that's ok, but the correct handling of the interrupt is

somewhat confusing to me.

If I understand correctly...you get a CAN interrupt for every FIFO member object reception. But then what's the point 

placing the FIFO reading inside the interrupt routine ? ( as seen at page 1059 of the datasheet : Figure 17-3. Message Objects in a FIFO Buffer )

If you get an interrupt for every FIFO member, and you read it immediately, the FIFO has no chance to fill up.

The above algorithm clearly shows reading the message inside the ISR.

It makes no sense for me, but obviously I''m missing something here...

If you place the FIFO read into your main loop, or you time it with a another timer, the FIFO has a chance to fill up...but then what's the point having IRQ

for every FIFO member ( you can read the FIFO member status outside the ISR also ).

Thanks for the answers.

  • There are several ways to use the CAN FIFO mode. If you enable receive interrupts for each message object in the FIFO, you can tolerate having interrupts disabled for a longer time before missing a message. (To me, having an interrupt routine so long that two or more CAN messages would be received in that time period is a very long interrupt routine.)

    Since receive interrupts can be configured for each message object, you can simply enable the receive interrupt on only the last message object, the one with EOB set. This can be handy when you know that a particular ID (or range of IDs) always come in a group and you don't want to process the messages until the last one of the group has been received.

    One caution about FIFO mode, if you are reading the messages from the FIFO while another message comes in, the messages are not guaranteed to be stored in order.
  • Hi Bob !

    Thanks for your answer. I am facing different issue though :

    I have to have a "general" FIFO that can fill the gaps when the MCU can't process CAN messages fast enough. 

    If I set up the interrupt only for the last item in FIFO, then I might not get the FIFO content if the sender is stop sending messages before the FIFO fills up.

    You will never get the IRQ for the last FIFO member.

    Ti's example in the datasheet is confusing for me, and I can't find any other good example. 

    If you have an IRQ for every member of the FIFO, and you read it every time in ISR, then it is not a buffer anymore. It will always contain only one item.

    The only way out from this I can imagine is :

    1. Have IRQ for every FIFO member

    2. Keep track how many FIFO elements are used up ( inside the ISR, using the FIFO member IRQ's you get). This way the ISR can be fast and short.

    3. in main() : - read the FIFO periodically, or as fast as your application let you - and of course free it up as you're reading it.

       - this way the FIFO can serve its function ( fill up when the read out is slow, and be almost empty when it is fast )

    My problem with my own idea is : every info I have points to doing it the other way : reading the FIFO in ISR - including Ti's example flow chart.

    As I said before, that's why I think I'm missing some vital info here how the FIFO really works. I'm not so egoist to think I'm right and everyone else is wrong :)

  • Hi Attila,
    I don't think you are missing anything. The FIFO mode as implemented may work well in the two use cases I have mentioned above, but it is not well suited for your use case (which is a common one). The method you propose, to use an interrupt on the reception of each frame to set a flag, and then in your main task loop checking that flag and emptying the FIFO, will work if the order of the received messages is not important. If the order is important, you probably should use a single message mailbox and upon getting a receive interrupt copying the data to a circular buffer in RAM and incrementing your FIFO head pointer. Then in your main loop, when the head pointer does not match the tail pointer, you can process the data off of your circular buffer, incrementing the tail pointer as each item is processed.
  • Hi Bob !
    Thank you again ! That's what I needed. So the CAN FIFO is even more unusual than any FIFO I saw before - it's not even a true FIFO - but that's OK as long as you don't try to use it differently. I just couldn't get a clear proof of my view anywhere yet.
    Since the CANOpen stack itself has its own software FIFO, I think I will keep it simple and use a single mailbox. I don't know yet though that it would be fast enough to reach some decent CAN bit rates (1Mbit) without issues. TIme and testing will tell.

    Still thing though that Ti's own Tivaware example is quite misleading for an average user. The datasheet does not improve that either. It took me about 2 weeks and your support to finally grasp the true nature of this buffer - and I'm not a beginner in these things. You don't miss much, just a more detailed commenting and/or more detailed description - or adding some more common use cases to examples.
    Ti's quality of documentation is still on top by the way.

    Thanks for the support.