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.

TM4C1231H6PM: CAN Bus Module Help

Part Number: TM4C1231H6PM


Here’s the problem I’m having with the TIVA’s CAN Bus module:

Currently, I setup one of the message objects in the CAN Bus module to receive CAN packets with a specific ID. These packets come in burst: 3 packets are sent successively as fast as the sender could send them, one burst every 3 seconds. I found that my software is not able to move every packets out of the buffer fast enough so that some packets get overwritten, which leads to problems in our system.

I’ve read the documentation for the TIVA’s CAN module carefully and repeatedly, but it is still unclear to me how I could create a FIFO buffer to store the packets. It seems the message objects cannot be configured to behave like a regular FIFO. But maybe I’m missing something here.

  • Hi Mike,
    Did you just setup one message object or three message objects. To form a FIFO, you will need to setup the three message objects with the identical ID and ID mask. The first two message objects will need to be specified for FIFO. See below example which forms a three-entry FIFO.

    //
    // Configure a receive object.
    //
    sMsgObjectRx.ulMsgID = (0x400);
    sMsgObjectRx.ulMsgIDMask = 0x7f8;
    sMsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER | MSG_OBJ_FIFO;
    //
    // The first two message objects have the MSG_OBJ_FIFO set to indicate
    // that they are part of a FIFO.
    //
    CANMessageSet(CAN0_BASE, 1, &sMsgObjectRx, MSG_OBJ_TYPE_RX);
    CANMessageSet(CAN0_BASE, 2, &sMsgObjectRx, MSG_OBJ_TYPE_RX);
    //
    // Last message object does not have the MSG_OBJ_FIFO set to indicate that
    // this is the last message.
    //
    sMsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER;
    CANMessageSet(CAN0_BASE, 3, &sMsgObjectRx, MSG_OBJ_TYPE_RX);
  • Hi Charles,

    May I note that my firm finds both, Mike Xia's skillfully worded post - and your "in depth" guiding response - simply terrific.

    May we ask if the method you describe is modeled (somewhere) - and if so - where may "mere mortals" go - to absorb further (deep) detail?
  • Hi cb1,

     Last year we had a CAN FIFO issue in another MCU family. My colleagues and I spent some time trying to understand the issue. So I still remember how the CAN FIFO works. :-)

     The FIFO setup is described in the datasheet. I understand that if you had prior knowledge on the FIFO setup, reading the datasheet will click quickly. For someone who is new to using CAN FIFO, it may not be so obvious reading the description the first time. Below is the excerpt from the datasheet under the section "Configuration of a FIFO Buffer". Again, a simple diagram would have made the understanding easier.

     "...To concatenate two or more message objects into a FIFO buffer, the identifiers and masks (if used) of these message objects have to be programmed to matching values. Due to the implicit priority of the message objects, the message object with the lowest message object number is the first message object in a FIFO buffer. The EOB bit of all message objects of a FIFO buffer except the last one must be cleared. The EOB bit of the last message object of a FIFO buffer is set, indicating it is the last entry in the buffer."

      There is also an example shown in the Driverlib User guide but it is illustrated for 4-entry FIFO. 

  • Thank you, Charles. Either we "missed" that - or it is not present w/in the "4C123 manual" - our only resident, "MCU of interest"
    Perhaps the diagram you note (should) receive consideration - as (even) a, "careful & repeated" read - failed to glean full understanding.

    It "would" prove of interest & value to many - if Mike Xia would be kind enough to implement this "fix" - and then report (here) his findings...

    Thanks again.

  • cb1, I'm pretty sure I've seen it in the datasheet. It's also mentioned in the TIVAWare manual. Although I don't think either go on in great detail.

    Robert
  • Thanks Robert - and (only) now do I, "SEE." Indeed - even the lowly "4C123" w/in MCU Manual Section, 17.3.11.1 "Configuration of a FIFO" reads, "word for word" - exactly as Charles listed - and you've just confirmed!

    Noted is the 17 pages of "CAN Functional Description" - shared among 16 areas of segmented description - with this specific issue residing as Number "ELEVEN" in the listing. I'm reasonably certain that at one/some point I read that section - but had ZERO Recall...
  • You don't remember the 400 odd pages word for word? I'm shocked! Shocked I tells you. Shocked!

    Seriously, unless you had need of the functionality in mind when reading it, it'd be easy to skim over.

    Robert
  • All right Robert - some "secrets" must be maintained!     Now - when we hoist Sails for "Halifax" (from Maine) and crack "cb1 designed" electronic compass indicates "South" - and "Unruly, all gurl (fetching yet little skilled) crüe" (scream) their protest - then (and only then) are you entitled to "SHOCK!"

    Indeed it (must) be that I, "skimmed over" - and not blood alcohol level - declining brain cells - nor crüe's nautical garb - caused such over-sight.   (Shocked, indeed)

  • Hi Charles,

    Thanks for the answer. I actually sent the original question directly to Mike, and he was kind enough to repost it in the forum for me.

    The example you gave shows how to set up a CAN FIFO using the driver, which is great. In the example, you concatenated 3 message objects to make a FIFO. When one or more packets arrive, which message object will generate interrupts and has the next received packet if the MSG_OBJ_RX_INT_ENABLE flag is set? The example in the driver documentation sets up a FIFO like the code above, and then keeps looking for packet from message object #1 in a while loop. Does it mean the message object with the lowest ID serves as the head of the FIFO so that an interrupt handler should only handle interrupt from the message object with the lowest ID?

    It would be very helpful if you can point me to an example program demonstrating how to use the CAN FIFO through interrupts.

    Sean
  • Sean,

    What's your baud rate? Can you share the body of your receive interrupt code? I'm not seeing issues with this on my setup and I'm wondering if you have a bottleneck in your receive.

    Robert

  • I'm using 1 Mbps.

    My interrupt handler does not remove data from the message object. Instead, it schedules a task to get the data later. I have many other interrupts in my software that also schedule tasks into the task queue, and the tasks are handle in the order in which they are scheduled. So there are delays in the retrieving the packets. Obvious, I could do some redesign to try to service the packets in the ISR, but a FIFO would be a much better solution.

    Sean
  • OK, that explains your bottleneck.

    zcircswm02 said:
    My interrupt handler does not remove data from the message object. Instead, it schedules a task to get the data later.

    This is, IMO, a bad idea.

    zcircswm02 said:
    Obvious, I could do some redesign to try to service the packets in the ISR,

    So would this

    zcircswm02 said:
    but a FIFO would be a much better solution.

    I think this is a patch that negates much of the advantage of the CAN mailbox setup.

    Might I suggest a pair of different approaches

    • Use one mailbox per message and keep your current non-interrupt approach. The value in the message mailbox will be the latest value sent
    • If there are not enough mailboxes use a S/W queue and in the interrupt copy from the mailbox(es) to the queue. this is easy to change the FIFO size to accommodate later message changes. It also matches your current control flow.

    Robert

    Keep in mind that CAN does not guarantee you will not get duplicate messages and sooner or later messages will be lost. Your protocol should be able to handle both cases. Duplicate messages are more common than missed on a good network.

  • Hi Sean,
    Please take advice from Robert as he has more experience with the FIFO. From my perspective, I will generate interrupt based on the last msg object of the FIFO. Once in the ISR I will read from message objects (only if the corresponding NEWDAT bit is set) from the lowest index to the index that contains the EOB bit. In my opinion, the FIFO mode is a bit tricky. You need to take into account if you are reading the FIFO and at the same time another frame is received. The new frame will be placed in the lowest index message object that has the NEWDAT bit cleared. You can potentially miss the new data if the time for the CPU to read the FIFO takes longer than the next new frame to come.

    Another question is if your incoming must be received in order? According to the datasheet, the order of the received messages in the FIFO is not guaranteed. Please see the datasheet for more detail and also refer to the Figure 17-3. Message Objects in a FIFO Buffer flowchart.
  • Nah, Charles. My biggest expertise in the FIFO so far is realizing I don't need it.

    I'm only running at 500kbs but I do have multiple boards transmitting simultaneously and I've not seen a loss. Whether that still holds true at 1Mbps is another question. It's only after having used all the mailboxes I'd consider switching to the FIFO though. And I'd probably look at rewriting parts of the TIVAWare library first. As I recall it looked fairly inefficient.

    Robert
  • So it seems the CAN FIFO is not really a FIFO in the traditional sense. I'm very curious about the use case for this particular design choice that TI has taken.

    In any case, it doesn't look like using this CAN FIFO is the solution for my problem. I think I'll have to remove the CAN packet when in the ISR into a queue in order to minimize the chance of packets getting overwritten.

    Thanks to everyone who offered help!

    Sean
  • Hi,
    The CAN module is an IP we purchased from 3-rd party. You may find similar IP used by other semiconductor vendors. I agree the CAN FIFO is not implemented same way as other IP like UART or SSI. I think the reason is that it will be too costly to implement a true FIFO for each message object.