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.

TMS570LS3137 CAN Receive Problem

Other Parts Discussed in Thread: HALCOGEN

Dear community members,

I have a peculiar problem I'm not sure how I should go around to debug it. I am currently using the Hercules to interface with 2 other Freescale Kinetis boards. The Kinetis boards are responsible for sending out CAN messages to Hercules.

On Hercules, I am running FreeRTOS, of which I have created tasks which runs periodically and preempts using its OS API - vTaskDelayUntil(). In particular, the CAN task which does the processing of the message receive is running on a period of 40ms. My CAN message receive on Hercules runs on the interrupt method; for every CAN message received, the interrupt is triggered which then calls the canMessageNotification who then provides a semaphore for the CAN task to run.

I've setup the Hercules through Halcogen 04.06.00 to run in two ways. I've first tried to have a single message object for each CAN message ID. Then I tried having a FIFO buffer for each of the CAN message IDs with a buffer size of 4. For both configurations, I have set the EOB bit on the message objects.

The problem I am encountering is that the system runs for a period of time before it gets stuck within the CAN task when it calls for "while(!canIsRxMessageArrived(canREG1, canMESSAGE_BOX10));". For some reason, it is always returning a 0 when a CAN message under that ID should have been received which is why the function was called in the first place. I verified that the CAN interrupts are still coming through for the other message IDs but the system is stuck @ the while loop when it returns to the CAN task.

How should I go about to solve this problem?

Any help would be greatly appreciated and thank you for reading such a lengthy post.

Best regards,

Daniel

  • Daniel,

    What does this code check:
    while(!canIsRxMessageArrived(canREG1, canMESSAGE_BOX10));

    What is done in that function call?

    And, you said this while loop is in some task level code, but you still are seeing interrupts from the CAN is that correct?

    Do you have any bus monitor where you can see that the message ID from mailbox 10 is actually on the bus?
    [Rather than just assuming that it is sent correctly by the Kinetis?]

    Last are there any error flags set in the CAN controller ? Always look for any status information that the hardware gives you and that is different when this condition occurs.

    Those are things I'd start checking.

    -Anthony
  • Hi Anthony,

    Thank you for your help.

    That code is used for "Gets Rx message box reception status" and "Checks to see if the Rx message box has pending Rx data, returns
    * 0 is flag not set otherwise will return the Tx request flag itself." as taken from the comments written in the halcogen generated code. This method of receiving CAN message data is actually in the example code that TI has provided.

    Yes i still do receive interrupts from the CAN.

    I do have a CAN bus analyzer that does show that the CAN messages are being sent out.

    Actually, if I run the CAN task faster, this problem does not occur at all. However I believe the periodicity of the task shouldn't affect how the CAN messages are being received. At the very least, some CAN messages gets missed as it gets overwritten by the newer incoming messages.

    As for checking for error flags, are you suggesting that i utilise this "uint32 canGetErrorLevel(canBASE_t *node)" to check for errors during runtime? If not how should i go about doing that?

    Thanks again!

    Regards,
    Daniel
  • If I understand your system, you use the interrupt that calls the function canMessageNotification() to set a semaphore. Then in the main loop you check the semaphore and call a task to read the CAN data. In that task, sometimes you get stuck in:

     while(!canIsRxMessageArrived(canREG1, canMESSAGE_BOX10));

    Do you clear the semaphore before you read the CAN data? If so, then if a second CAN frame comes between the time you cleared the semaphore and when you actually read the data, the semaphore will be set again by the interrupt routine. Then when you read the data, you actually get the new frame data. When you return from that task, you immediately see that the semaphore got set again, and try to read again. This is where you would get stuck because there is no new message, you already read it.

  • Hi Bob,

    You've understood my system correctly. That scenario you've mentioned seems possible since the burst of CAN messages are coming in at quite a high rate (every 6ms) but I'm already having the CAN task to run every 0.4ms and it still gets stuck unless is set to to 0.2ms. 

    But if so, how would you suggest so I could resolve this issue? Would increasing the CAN FIFO buffer be of any use?

    Thank you so much for your help!

    Best regards,
    Daniel 

  • If the CAN message comes every 6ms and you are checking for the message every 0.4ms, then you should never have this problem. Maybe the first thing to do is check that you really can check for the CAN message every 0.4ms. Perhaps if in the 0.4ms task you could toggle an I/O pin. Then with a scope that has a fancy trigger you can trigger when there is more than 1ms gap between pulses.

    Now suppose in FreeRTOS you cannot service the task every 6ms. Using the FIFO mode should allow you to go longer without losing any data. In FIFO mode, using 4 message boxes, the first three should have EOB=0 and the fourth one with EOB=1. Then you should check for new data in any of the four message boxes. Do you ever have more than one valid new message in the FIFO? (Note that the FIFO mode does not always put the new messages in the order they were received. If order is important, this may not be a good solution.) With this setting you run the risk of the semaphore being given a second time by the DCAN ISR after your task was unblocked but before you read all of the data. One solution would be to simply not return from the task when canIsRxMessageArrived() returns FALSE instead of looping there, assuming you already read the new data the last time you executed this task.