G400 hangs due to possible bug in CAN

I run the exactly same code which is posted on this thread:

  1. I connect two boards: one is G400HDR, the second is our custom board.
  2. I reset both boards, they both are in idle state and waiting for button press.
  3. I press the button on one board. It starts transmitting, other board receives, all is going well.
  4. I press the button on the second board.
  5. Both boards are now sending and receiving.
  6. For a few seconds things are going normal, then the blinker LEDs begins blinking slower and slower, until one board hangs without any exceptiopns. Other stays perfectly responsive (probably because the traffic decreases).

On EMX and 4.2sdk we used to have the same problem if data arrrive too quickly and that processing is not enough fast, the board send buffer full message continuously… is there’s such message in your test?

No. It just stops working.

CAN stops or the board? If CAN then it maybe a bus off condition which is standard in CAN.

No, the whole board.

Ping will not get a reply?

Nope, FEZ Config doesn’t even see it.

@ Simon from Vilnius -

IN G400 side, can you try to add these code:

   can.PostMessages(msgList, cnt, 1);
                //Debug.Print("End send " + cnt);
                while (can.PostedMessagesSent == false)
                {
                    Debug.Print("Wait for sending the message...");
                    Thread.Sleep(10);
                }

I mean try to wait for PostMessages is done completely!

@ Simon from Vilnius -

tried it?

Tried. CAN communications stops, but both boards respond to ping. However, both boards soon are stuck in the while{} cycle. Looks like can.PostedMessagesSent is never set to true. So it just outputs “Wait for sending the message…” indefinitely.

@ Simon from Vilnius -

Are you sure your CAN device (not g400) is working well? Because g400 → g400, they are working fine, right?

I tried here for more than 20 mins, it is good.

It mays many msgs are coming so G400 can not send. how about if add some sleep in sender side?

They are both G400-based, running exactly the same application. I just have one G400HDR breakout board, other is custom-made.

That’s something to think about…

@ Simon from Vilnius -

Here is code what I did to test,
and attachment is what I config 2 G400 boards.
Can you try it?


using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHI.Premium.Hardware;

namespace G400_TestCAN
{
    public class Program
    {
     
        static InputPort button = new InputPort((Cpu.Pin)(4), false, Port.ResistorMode.PullUp);
        static OutputPort led = new OutputPort((Cpu.Pin)(3 * 32 + 3), true); // led pd3       
        static CAN.Message[] msgList;
        public static void Main()
        {
          
            // Create a message list of 1000 messages
            msgList = new CAN.Message[1000];
            for (int i = 0; i < msgList.Length; i++)
                msgList[i] = new CAN.Message();
            

            var brp = 6;
            var sjw = 1;
            var propag = 1;
            var phase1 = 7;
            var phase2 = 7;
            CAN can = new CAN(CAN.Channel.Channel_1, (uint)((brp << 16) + (sjw << 12) + (propag << 8) + (phase1 << 4) + (phase2 << 0)), 1000); //1Mbit
            // Subscribe to events
            can.DataReceivedEvent += new CANDataReceivedEventHandler(can_DataReceivedEvent);
            can.ErrorReceivedEvent += new CANErrorReceivedEventHandler(can_ErrorReceivedEvent);            
            int numberOfMessagesPosted;
            // G400 can receive message without pressing button
            while (button.Read())  
            {
                led.Write(true);
                Thread.Sleep(500);
                led.Write(false);
                Thread.Sleep(500);
            }
            Debug.Print("Start PostMessage");
            //for (int i = 0; i < 1000; i++)
            //{
            //    msgList[i].ArbID = 12;
            //    msgList[i].DLC = 8;
            //    msgList[i].Data[2] = (byte)(i & 0xFF);
            //}

            //while (true)
            //{
            //    //for (int i = 0; i < 100; i++)
            //    {
            //        can.PostMessages(msgList, 0, 1);
            //    }
            //    Thread.Sleep(1);
            //}

            int cnt = 0;
            while (cnt < 1000)
            {
                Thread.Sleep(1);
                // Send one message
                msgList[cnt].ArbID = (uint)(1 + cnt);
                // Send the 8 bytes for example
                msgList[cnt].Data[0] = 1;
                msgList[cnt].Data[1] = 1;
                msgList[cnt].Data[2] = 1;
                msgList[cnt].Data[3] = 1;
                msgList[cnt].Data[4] = 1;
                msgList[cnt].Data[5] = 1;
                msgList[cnt].Data[6] = 1;
                msgList[cnt].Data[7] = 1;

                msgList[cnt].DLC = 8;
                msgList[cnt].IsEID = false;
                msgList[cnt].IsRTR = false;
                //Debug.Print("Start send " + cnt);
                numberOfMessagesPosted = can.PostMessages(msgList, cnt, 1);
                //Debug.Print("End send " + cnt);
                while (can.PostedMessagesSent == false)
                {
                    Debug.Print("Wait for sending the message...");
                    Thread.Sleep(10);
                }

                cnt++;

                if (cnt == 999)
                    cnt = 0;
            }
            // Sleep forever
            Thread.Sleep(Timeout.Infinite);
        }
        static int countReceive = 0;
        static Boolean error = false;
        static void can_DataReceivedEvent(CAN sender, CANDataReceivedEventArgs args)
        {
            countReceive++;
            // Blink LED every 50ms if r
            led.Write((countReceive % 100 >= 50) && (error== false));          
            int count = sender.GetMessages(msgList, 0, msgList.Length);
            // Output text every one 1sec 
            //if (error == false && countReceive % 1000 == 0)
            //{
            //    Debug.Print("Still running " + countReceive);
            //}
            //for (int i = 0; i < count; i++)
            //{
            //    Debug.Print("MSG: ID = " + msgList[i].ArbID
            //        + " len = "
            //        + msgList[i].DLC
            //        + " data= "
            //        + msgList[i].Data[0] + "-"
            //        + msgList[i].Data[1] + "-"
            //        + msgList[i].Data[2] + "-"
            //        + msgList[i].Data[3] + "-"
            //        + msgList[i].Data[4] + "-"
            //        + msgList[i].Data[5] + "-"
            //        + msgList[i].Data[6] + "-"
            //        + msgList[i].Data[7]
            //        + ", 29 bits = " + msgList[i].IsEID
            //        + ", RTR =" + msgList[i].IsRTR
            //        + ", Time =" + msgList[i].TimeStamp
            //        );
            //}
        }

        static void can_ErrorReceivedEvent(CAN sender, CANErrorReceivedEventArgs args)
        {
            error = true;
            switch (args.Error)
            {
                case CAN.Error.Overrun:
                    Debug.Print("Overrun error. Message lost");
                    break;

                case CAN.Error.RXOver:
                    Debug.Print("RXOver error. Internal buffer is full. Message lost");
                    break;

                case CAN.Error.BusOff:
                    Debug.Print("BusOff error. Reset CAN controller.");
                    sender.Reset();
                    break;
            }
        }

    }
}


This exact example works fine. Lets modify it so it crashes :slight_smile:

@ Simon from Vilnius -

How did you modify?