CLR_E_NULL_REFERENCE - Can Bus during receive event

Hi,

I finally got my CAN setup to start sending messages. (Ended up being the MCP2551 transceivers not playing nice).

I have two transceivers setup on the board. I can send messages no problem. This occurs no matter what speed I set in bitrate.

But when the DataReceivedEvent fires its throwing the following exception.

(Let me know if I need to throw up a schematic. But its very basic, two transceivers on the board, termination. Typical 2 node CAN set up. I have verified the data on the bus with a logic analyzer. )

Here is the exception:

>>> can_DataReceivedEvent <<< Chl 2
    #### Exception System.NullReferenceException - CLR_E_NULL_REFERENCE (3) ####
    #### Message: 
    #### MFConsoleApplication1.Program::canTwo_DataReceivedEvent [IP: 0011] ####
    #### GHI.Premium.Hardware.CANDataReceivedEventHandler::Invoke [IP: 0000] ####
    #### GHI.Premium.Hardware.CAN::nativeEventDispatcher_OnInterrupt [IP: 003f] ####
    #### GHI.Premium.System.InternalEvent::nativeEventDispatcher_OnInterrupt [IP: 0025] ####
A first chance exception of type 'System.NullReferenceException' occurred in MFConsoleApplication1.exe
An unhandled exception of type 'System.NullReferenceException' occurred in MFConsoleApplication1.exe

And my current code.

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

namespace MFConsoleApplication1
{
    public class Program
    {
        private static CAN.Message[] msgList;

        public static void Main()
        {
            //First lets set date/time
            Utility.SetLocalTime(new DateTime(2013, 09, 15, 08, 55, 00));

            uint bitRate = GetBitRateConfig_120MHZ(Bitrate.BITRATE_500k);

            CAN can = new CAN(CAN.Channel.Channel_1, bitRate);

            CAN canTwo = new CAN(CAN.Channel.Channel_2, bitRate);

            //canTwo.Reset();

            can.DataReceivedEvent += can_DataReceivedEvent;
            can.ErrorReceivedEvent += can_ErrorReceivedEvent;

            canTwo.DataReceivedEvent += canTwo_DataReceivedEvent;
            canTwo.ErrorReceivedEvent += canTwo_ErrorReceivedEvent;

            int clock = 1;

            CAN.Message sendMessage = new CAN.Message();

            
            sendMessage.ArbID = 0x7E5;

            sendMessage.Data[0] = (byte)clock;
            sendMessage.Data[1] = 0x78;
            sendMessage.Data[2] = 0x5F;
            sendMessage.Data[3] = 0xFF;
            sendMessage.Data[4] = 0x3B;
            sendMessage.Data[5] = 0x00;
            sendMessage.Data[6] = 0x00;
            sendMessage.Data[7] = 0x4C;

            if (clock == int.MaxValue - 1)
                clock = 0;

            clock ++;

            CAN.Message[] messages = new[] {sendMessage};

            while (true)
            {

                int numberMessagesPosted = can.PostMessages(messages, 0, messages.Length);
                Debug.Print("Number of messages posted: "+numberMessagesPosted);
                var test = can.TransmitErrorCount;

                if (test > 1)
                    Debug.Print(test.ToString());

                Thread.Sleep(500);
            }
        }

        static void canTwo_ErrorReceivedEvent(CAN sender, CANErrorReceivedEventArgs args)
        {
            Debug.Print(">>> can_ErrorReceivedEvent <<< Chl 2");

            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;
            }
        }

        static void canTwo_DataReceivedEvent(CAN sender, CANDataReceivedEventArgs args)
        {
            Debug.Print(">>> can_DataReceivedEvent <<< Chl 2");
            msgList = new CAN.Message[500];            

            // read as many messages as possible
            int count = sender.GetMessages(msgList, 0, msgList.Length);
            for (int i = 0; i < count; i++)
            {
                string m = ("Data: " + msgList[i].Data[0].ToString("X") + " " + msgList[i].Data[1].ToString("X") + " " + msgList[i].Data[2].ToString("X") + " " + msgList[i].Data[3].ToString("X") + " "
                            + msgList[i].Data[3].ToString("X") + " " + msgList[i].Data[4].ToString("X") + " " + msgList[i].Data[5].ToString("X") + " " + msgList[i].Data[6].ToString("X") + " "
                            + msgList[i].Data[7].ToString("X"));
                Debug.Print("MSG: ID = " + msgList[i].ArbID + "DATA: " + m + "  at time = " + msgList[i].TimeStamp);
            }
        }

        private static void can_ErrorReceivedEvent(CAN sender, CANErrorReceivedEventArgs args)
        {
            Debug.Print(">>> can_ErrorReceivedEvent <<< Chl 1");

            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;
            }
        }

        private static void can_DataReceivedEvent(CAN sender, CANDataReceivedEventArgs args)
        {
            Debug.Print(">>> can_DataReceivedEvent <<< Chl 1");
            msgList = new CAN.Message[500];
            // read as many messages as possible
            int count = sender.GetMessages(msgList, 0, msgList.Length); 
            for (int i = 0; i < count; i++)
            {
                string m = ("Data: " + msgList[i].Data[0].ToString("X") + " " + msgList[i].Data[1].ToString("X") + " " + msgList[i].Data[2].ToString("X") + " " + msgList[i].Data[3].ToString("X") + " "
                            + msgList[i].Data[3].ToString("X") + " " + msgList[i].Data[4].ToString("X") + " " + msgList[i].Data[5].ToString("X") + " " + msgList[i].Data[6].ToString("X") + " "
                            + msgList[i].Data[7].ToString("X"));
                Debug.Print("MSG: ID = " + msgList[i].ArbID + "DATA: " + m + "  at time = " + msgList[i].TimeStamp);
            }
        }


        public enum Bitrate
        {
            NONE = 0,
            BITRATE_125k = 125000,
            BITRATE_250k = 250000,
            BITRATE_500k = 500000,
            BITRATE_1000k = 1000000,
        }

        /// <summary>
        /// Returns a bitrate for the internal CAN driver
        /// </summary>
        /// <param name="bitrate">Bitrate</param>
        /// <returns>CAN driver bitrate for LPC17XX</returns>
        public static uint GetBitRateConfig_120MHZ(Bitrate bitrate)
        {
            int t1 = 0;
            int t2 = 0;
            int brp = 0;

            switch (bitrate)
            {
                case Bitrate.BITRATE_125k:
                    brp = 20;
                    t1 = 16 - 1;
                    t2 = 8;
                    break;

                case Bitrate.BITRATE_250k:
                    brp = 10;
                    t1 = 16 - 1;
                    t2 = 8;
                    break;

                case Bitrate.BITRATE_500k:
                    brp = 5;
                    t1 = 16 - 1;
                    t2 = 8;
                    break;

                case Bitrate.BITRATE_1000k:
                    brp = 5;
                    t1 = 8 - 1;
                    t2 = 4;
                    break;
            }

            return (uint) (((t2 - 1) << 20) | ((t1 - 1) << 16) | ((brp - 1) << 0));
        }
    }
}

I don’t see where you allocate your msgList. It is null and when you try to get Length property you got the null reference exception.

It pasted old code. I updated it. I am instantiating a new CAN.Message list.

It appears the exception is getting thrown from unmanaged code? or CLR exception?

-Matt

What line throws the exception?

int count = sender.GetMessages(msgList, 0, msgList.Length); 

Is where the exception is thrown. (sender has a value btw)

-Matt

Check if sender is null.

It does have a value. (sender != null)

Here is the exception break in VS

An unhandled exception of type 'System.NullReferenceException' occurred in GHI.Premium.Hardware.dll

I turned off “Just My Code” and enabled all exceptions, it broke at the following line in the GHI.Premium.Hardware.CAN class

public extern int GetMessages(Message[] msg, int offset, int count);

And msgList is definitely not null?

100% sure! Here is a screen grab of all the values in scope and the exception

Looks like it is something for GHI to verify.

Architect is out.

Thanks for looking Architect!

GHI?? Help! :slight_smile:

-Matt

looking into it

Solved.

I made the assumption that the GetMessages method instantiated the individual CanMessages in the array.

Changing my code to the following fixes the issue.

int count = 0;
            // read as many messages as possible

            int recCount = sender.ReceivedMessagesCount;
            msgList = new CAN.Message[recCount];

            for(int i =0; i < msgList.Length; i++)
            {
                msgList[i] = new CAN.Message();
            }
            
            count = sender.GetMessages(msgList, 0, msgList.Length); 

Thanks very much for looking into it!

-Matt

That makes total sense! Completely missed that :slight_smile: