Apalis T30 CAN Bus implementation under C# - Problem / Does not work at all

Hello,

Please help me to solve the puzzle with CAN Bus implementation under Apalis T30. It does not work at all.
I use it with WEC2013 and implementing my code using C#
I am also using latest available library for CAN/GPIO etc. TdxAllLibraries.dll and TdxAllLibraries.cs files both available and attached to project.

What I have done:

Apalis T30
Custom carrier board
Everything connected. WEC2013 running. Able to deploy and run code from VS2015

What I do:

Apalis T30 does not have native CAN controllers. Instead two MPC2515 installed on Apalis PCB and connected via SPI to main chip.
We assume that we need to initialize CAN as SPI1 or SPI2.

My code:

//Assign variable
            bool result = false;
            uint res = 0;

            IntPtr CAN_handle = new IntPtr(0);



            gpio.uIo _canRx = new gpio.uIo((ushort)12, (ushort)gpio.tIoType.ioApalisPin);
            gpio.uIo _canTx = new gpio.uIo((ushort)14, (ushort)gpio.tIoType.ioApalisPin);
            //gpio.uIo _canIntrp = new gpio.uIo((ushort)19, (ushort)gpio.tIoType.ioApalisPin);
            IntPtr _gpio;
                        


            _gpio = gpio.Gpio_Init(null);

            if (_gpio == null)
            {
                Debug.WriteLine("GPIO Init Failed");
            }

            if (!gpio.Gpio_Open(_gpio))
            {
                Debug.WriteLine("GPIO Open Failed");
            }
            

            //Initialize CAN bus
            CAN_handle = can_teg.TegCan_Init("SPI1");
                        
            if (CAN_handle == null)
                Debug.WriteLine("Error. No CAN Handle");

                        
            can_teg.TegCan_SetConfigInt(CAN_handle, "ioRx", _canRx.GenericDefinition, TdxCommon.ParamStorageType.StoreToRegistry);
            can_teg.TegCan_SetConfigInt(CAN_handle, "ioTx", _canTx.GenericDefinition, TdxCommon.ParamStorageType.StoreToRegistry);
            can_teg.TegCan_SetConfigInt(CAN_handle, "BitRateHz", 100000, TdxCommon.ParamStorageType.StoreVolatile);
            can_teg.TegCan_SetConfigInt(CAN_handle, "FilterID", 0x00, TdxCommon.ParamStorageType.StoreVolatile);
            can_teg.TegCan_SetConfigInt(CAN_handle, "FilterMask", 0x00, TdxCommon.ParamStorageType.StoreVolatile);
            can_teg.TegCan_SetConfigString(CAN_handle, "FilterFrameFormat", "None", TdxCommon.ParamStorageType.StoreVolatile);
            can_teg.TegCan_SetConfigString(CAN_handle, "FilterRemote", "none", TdxCommon.ParamStorageType.StoreVolatile);
            //can_teg.TegCan_SetConfigInt(CAN_handle, "ioInterrupt", _canIntrp.GenericDefinition, TdxCommon.ParamStorageType.StoreVolatile);
            //can_teg.TegCan_SetConfigInt(CAN_handle, "IstPriority", 0x10, TdxCommon.ParamStorageType.StoreVolatile);
            can_teg.TegCan_SetConfigInt(CAN_handle, "Timeout", 1000, TdxCommon.ParamStorageType.StoreVolatile);

   
            //Open CAN line
            result = can_teg.TegCan_Open(CAN_handle);
            
            Debug.WriteLine("CAN Init Result: " + result.ToString());
            
            
            uint result2 = can_teg.TegCan_GetConfigInt(CAN_handle, "BusStatus", ref res);
            Debug.WriteLine("Bus status: " + res.ToString());
            

            StringBuilder sb = new StringBuilder("", 50);
            can_teg.TegCan_GetConfigString(CAN_handle, "Implementation", sb, 20);

            Debug.WriteLine("Bus implementation: " + sb.ToString());

My problem:

I am able to get CAN Handle for SPI1 CAN using initial command to CAN_Init(SPI1)
At this point handle is available.
Next I am configuring my CAN as per Toradex help file for CAN library. I am setting all parameters required for configuration prior calling CAN_Open.
Next I am calling CAN_Open and always getting FALSE. I can not get CAN_Open to return TRUE despite trying everything possible.
With the same time I am getting BusStatus as: ‘2’ - which means No transmission or receipt of messages is possible. Finally I am getting Implementation as ‘Mcp2515’ which is correct and according to expectations.

Toradex support! Please help with this. It is unbelievable that CAN bus is not supported on this board.
Your CAN_Demo.c which I have and use as reference is poorly written. Especially configuration part.
I downloaded this sample CAN_Demo.c from your website just yesterday. It is likely latest version but it has all config block as ‘//’ and I have no idea if I need to use all config variables which I send or not.
I tried all possible combinations but always! getting FALSE on CAN Open.
Obviously I was not able to move forward on that since CAN_Open is initial command which needs to be passed.

Thanks,
Vlad

I attempted to run CAN_Demo project from Toradex on my Apalis T30. It does not work and also comes out with same error - Can not open CAN.

I verified records in registry for CAN. Picture below shows my findings.

Are there anything should be activated, enabled or installed for Apalis T30 CAN bus to work ? Maybe driver or some settings in the registry ? I understand that Apalis T30 does not have native CAN thus using SPI version of MPC CAN controller. So I guess SPI must work. In my case looks like it may be the SPI who does not work ?

Hello Support team!
Any thoughts on my problem with your Apalis T30 CAN bus please?
Am I correct that I am trying to CAN_Init(SPI1) or should it be CAN1?
I can not find clear answer in your documentation and the sample project for CAN.c demo is a bit poorly written. By the way this demo code does not work on my board and returns FALSE on attempt to open CAN.

Dear @vinzer,

Are you using our carrier board or custom carrier board?

You need to use CAN1 or CAN2 for the CAN_Init internally we mapped to respective SPI port name as shown in below

 // On Apalis T30 CAN1 and CAN2 are mapped on SPI6 and SPI4 as we have on module MCP2515 Controllers
    if (Cop_GetFormFactor() == FormFactor_Apalis)
    {
        if(_wcsnicmp(pCan->hdr.portName, L"CAN1", 4) == 0)
            mappedPortName = L"SPI6";
        else if (_wcsnicmp(pCan->hdr.portName, L"CAN2", 4) == 0)
            mappedPortName = L"SPI4";
    }

After CAN_Ini, call CAN_open and test with default parameters to confirm the hardware setup is proper.

Please see the default parameters details below. Also, you can get from the documentation.

  pCan->param_BitRateHz      = 500000; // 500KHz
    pCan->param_FilterFrameFormat = FilterFrameFormat_None; // Don't  filter any frame format
    pCan->param_FilterRemote = FilterRemote_None;       // do not filter remote frame
    pCan->param_FilterID       = 0;                     // No ID to filter
    pCan->param_FilterMask     = 0;                     // receive all frames
    pCan->param_Timeout        = 1000;                  // CAN timeout 1 sec
    pCan->param_IoInterrupt.GenericDefinition = IOCOLIBRIPIN(73);      // Colibri Interrupt line.
    if (Cop_GetFormFactor() == FormFactor_Apalis)
    {
        if(pCan->canInterface==6)
            pCan->param_IoInterrupt.GenericDefinition = IOGPIO(178);
        else if(pCan->canInterface==4)
            pCan->param_IoInterrupt.GenericDefinition = IOGPIO(179);
    }

CAN_BusStatus return value 2 means BUS_OFF, it could be a chance that CAN transmission is started from the T30 but the receiver didn’t configure properly to receive the message.

Could you share details about the CAN receiver setup? Is that termination resistor connected between TX and RX? Did you already verify the receiver and CAN cable are working correctly?

Please, first test with a native application that will be in \libdemo\CANDemo application and then test with a C# application.

Still, if it not solving your problem, please share which library release you are using, let me quickly test with that and get back you.

Thank you.

Thank you for response.
All solved. Issue was in your wording in help file for TdxLibrariesDll.dll. You may want to add clear wording there in help file saying that “Despite Apalist T30 uses SPI based CAN bus you still need to initialize it with CAN word instead of SPI”.
According to your documentation variable ‘SPI’ in CAN_Init() used whenever board has no native CAN controller and uses SPI lines via MCP2551. This is fully true for T30 Apalis board. However because you added these MCP2515 on PCB, you decided that this is a native CAN and in your driver you expect ‘CAN’ instead of ‘SPI’ for CAN_Init. This confusing.

As soon as I put ‘CAN’ and made correct parameters (specifically the baudrate) settings CAN started to work perfectly.

Dear @vinzer,

Thank you for your reply and suggestion. Even you can use SPI4 or SPI6 port name in the Can_Init that will use on module CAN chip over SPI. Maybe I guess you have tried SPI1 instead of SPI6.

Please feel free to contact us if you need any supprt in the future!