EMX CAN bug

Hi everyone,

I was trying to search for solution in the forums, but since the search function isn’t working, I’m posting my issue on a new thread.

So I have a laser with many CAN controllers which transmit ~600 CAN messages per second, if combined. EMX has to catch all that so obviously I need a large buffer. I use 10000:



//Initialize CAN
_can = new CAN(CAN.Channel.Channel_1, (((8 - 1) << 20) | ((15 - 1) << 16) | ((3 - 1) << 0)), 10000);

// create a message list of 10000 messages
_msgList = new CAN.Message[10000];
for (var i = 0; i < _msgList.Length; i++) {
   _msgList[i] = new CAN.Message();
}

// subscribe to events
_can.DataReceivedEvent += CanDataReceivedEventHandler;
_can.ErrorReceivedEvent += CanErrorReceivedEventHandler;


The trick is, when the program runs after reset, DataReceivedEvent is not raised until EMX CAN input buffer is full and ErrorReceivedEvent (with CAN.Error.RXOver) is rased. From the moment ErrorReceivedEvent is raised for the first time, everything works just fine.

That really bugs me, because, during manufacturing, testing, development and debugging, many CAN devices are disconnected and the CAN message flow may be as low as 30 per second; then it takes minutes for the CAN buffer to overflow, and I don’t get any incoming CAN messages until that happens. And people, forced to wait two minutes until the board starts working, wish me a lot of things, that are not exactly… pleasant :slight_smile:

The only workaround I discovered is to disconnect CAN cable from EMX while it boots, and reconnect it once the program is up and running. But that’s not really an option, isn’t it?

So… any comments?..

Try to make a reset (_canHandle.Reset()) of the CAN controller as soon you have init it.

I actually do that, just forgot to paste that line here. Doesn’t help.

Is this 4.1 or 4.2?

Behaviour is the same for both.

However, I found another workaround (for both 4.1 and 4.2). If I call GetMessages() method just after creation of the CAN object, it works fine:

//Initialize CAN
_can = new CAN(CAN.Channel.Channel_1, (((8 - 1) << 20) | ((15 - 1) << 16) | ((3 - 1) << 0)), 10000);
 
// create a message list of 10000 messages
_msgList = new CAN.Message[10000];
for (var i = 0; i < _msgList.Length; i++) {
   _msgList[i] = new CAN.Message();
}
 
// subscribe to events
_can.DataReceivedEvent += CanDataReceivedEventHandler;
_can.ErrorReceivedEvent += CanErrorReceivedEventHandler;

_can.GetMessages(_msgList, 0, _msgList.Length)

I guess this call to GetMessages() resets and puts to good state something internally.

Sometimes the mode of CAN controller is not in normal mode or listen. So I use a custom made Mode property to be able to set it to either “config, listen or nomal”


    public enum Mode
    {
        Normal = 0x00,
        Sleep = 0x01,
        Loopback = 0x02,
        Listen = 0x03,
        Config = 0x04,
    }

        public Mode Mode
        {
            get
            {
                Register mode;

                mode = new Register(CANXMOD + (((uint)_channel) - 1) * 0x4000);

                switch (mode.Read())
                {
                    case 0x10:
                        return CAN.Mode.Normal;

                    case 0x01:
                        return CAN.Mode.Config;

                    case 0x02:
                        return CAN.Mode.Listen;

                    default:
                        return CAN.Mode.Normal;
                }
            }

            set
            {
                Register mode;

                mode = new Register(CANXMOD + (((uint)_channel) - 1) * 0x4000);

                switch (value)
                {
                    case CAN.Mode.Normal:
                        mode.Write(0x00);
                        _rsPin.Write(false);
                        break;

                    case CAN.Mode.Config:
                        mode.Write(0x01);
                        _rsPin.Write(true);
                        break;

                    case CAN.Mode.Listen:
                        mode.Write(0x02);
                        _rsPin.Write(true);
                        break;
                }
            }
        }

_rsPin is the slope control of the CAN tranciever and _channel is the GHI CAN channel.

Rearange your code like this could solve your problem.


// create a message list of 10000 messages
_msgList = new CAN.Message[10000];
for (var i = 0; i < _msgList.Length; i++) {
   _msgList[i] = new CAN.Message();
}
 
//Initialize CAN
_can = new CAN(CAN.Channel.Channel_1, (((8 - 1) << 20) | ((15 - 1) << 16) | ((3 - 1) << 0)), 10000);
 
//the time spend here between init and subsription: if the buffer get's flooded here no datareceived event is raised

// subscribe to events
_can.DataReceivedEvent += CanDataReceivedEventHandler;
_can.ErrorReceivedEvent += CanErrorReceivedEventHandler;

Works! :slight_smile:

I just followed the example in the wiki Home - GHI Electronics I guess it needs some corrections, too…

Wiki code is also in the correct order now :wink:

Thank you very much

So… This is not a bug? Ok then, I’ll add a section to the wiki about it…