MCP2518 SPI-CAN integration with nrf52840

Hi,

I am using nrf52840 on a custom board. I have a MCP2518 to which I wish to communicate through the SPI interface. I changed the dts file accordingly and added the bindings and finally got it to build. The problem is I cannot access the SPI bus. My custom driver is based on the mc2518 driver that is part of NRF Connectv2.2.0 . I have modified it and removed everything except the initialization part where it checks if the devices and bus is ready. I have not started using that however. I cannot get an instance of the MCP2518 because the initialization fails. The failure point is where it checks whether the SPI bus is ready. Exactly this same position as described in this post. It seems like that question is inactive now. So I though I would raise this question here. I hope it is alright.

There are a few additional observations too. If i do device_is_ready() on the SPI bus instance from main() of my application, it returns success. However, if I do the same check in my custom driver module, right before the above failure point, I get failure. I dont know if this bit of info helps and I dont know why it behaves differently.

I would very much appreciate it if anyone could help.

device ; nrf52840

NCS v2.2.0

trying to interface mcp2518fd

Parents
  • Okay. Did a little digging and found something.

    By default CONFIG_CAN_INIT_PRIORITY is set to 50 and CONFIG_SPI_INIT_PRIORITY is set to 70.

    Using these default values, CAN maybe initializing before SPI and thus, cannot find SPI bus during its initialization phase, buT later SPI becomes active and hence can be accessed from main().

    In counter CAN example that I used as reference (included in NRF connect 2.2.0), CONFIG_CAN_INIT_PRIORITY is explicitly set to 80. Using the same logic as before, this time CAN initialized after SPI. So no problems were observed in the example.

    The solution is obvious. Use CONFIG_CAN_INIT_PRIORITY numerically greater than CONFIG_SPI_INIT_PRIOIRTY so that SPI initializes first. But the problem is, whenever I attempt that I run into this error.

    So effectively, I do not have any solutions even though I have a lot of findings.

    Can someone help me with the issue ? I do not know if my observations are relevant to the issue, but I would really appreciate any help.

    Thank you

  • Hi,

     

    The mcp2515 driver sets up a gpio callback, and can be the culprit of the assert.

    What is the state of the GPIO driver at this point?

     

    Have you tried entering debug mode, and placing a breakpoint at this assert line to see where it came from?

     

    Kind regards,

    Håkon

  • Hi, 

    sorry for the late reply. I was out of office. I did not try working in the debug mode. But this seems like a logical explanation. I will check this out on Monday and let you know about the result.

    Thank you

  • Hi,

     

    That sounds good. Please share stack traces, so we can see where the function call originated from.

    Hope you have a great weekend!

     

    Kind regards,

    Håkon

  • Hi,

    I debugged the issue as you said. And you were right about the GPIO callback. I had commented out parts of callback function which made it useless and so,, the device kept on rebooting. Once I restored that, ithe device is now stable. Thank you for your input. But now, I have an issue with the mcp2518.

    Even though I can now successfully boot, when I try to check whether the device is up using device_is_ready() from the main (), it returns an error.

    This was the original issue and that is when I debugged and found out that the SPI bus was not active during CAN device initialization process. I thought if I fixed that, my CAN device would be active. But now even after the SPI bus issue is solved, I still cannot access the CAN device from main().

    Any idea why this might be happening ?

Reply
  • Hi,

    I debugged the issue as you said. And you were right about the GPIO callback. I had commented out parts of callback function which made it useless and so,, the device kept on rebooting. Once I restored that, ithe device is now stable. Thank you for your input. But now, I have an issue with the mcp2518.

    Even though I can now successfully boot, when I try to check whether the device is up using device_is_ready() from the main (), it returns an error.

    This was the original issue and that is when I debugged and found out that the SPI bus was not active during CAN device initialization process. I thought if I fixed that, my CAN device would be active. But now even after the SPI bus issue is solved, I still cannot access the CAN device from main().

    Any idea why this might be happening ?

Children
  • Hi,

     

    How is your overlay for the chosen "zephyr,canbus" and the spi-overlay for the mcp-IC?

    Are you able to post any logs? You can for instance use SeggerRTT for logging if you do not have uart output.

    I would strongly recommend that you connect a logic analyzer to the SPI pins to your mcp-IC, to see how the communication looks.

     

    Kind regards,

    Håkon

  • Hi,

    This is the relevant part of my overlay file.

    spi_can:&spi0 {
        compatible = "nordic,nrf-spi";
        status = "okay";
        cs-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; /* D10 */
        pinctrl-0 = <&spi0_default>;
        pinctrl-1 = <&spi0_sleep>;
        pinctrl-names = "default", "sleep";
    };

    &spi_can {
        status = "okay";
        cs-gpios = < &gpio0 18 GPIO_ACTIVE_LOW >;

        mcp2518: can@0 {
            compatible = "microchip,mcp2518";
            spi-max-frequency = <1000000>;
            status = "okay";
            reg = <0x0>;
            int-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
            osc-freq = <20000000>;
            bus-speed = <125000>;
            sjw = <1>;
            sample-point = <875>;

            can-transceiver {
                max-bitrate = <8000000>;
            };
        };
    };

    &pinctrl {
        status = "okay";
        uart0_default: uart0_default {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 6)>,
                    <NRF_PSEL(UART_RX, 0, 8)>;
            };
        };
        uart0_sleep: uart0_sleep {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 6)>,
                    <NRF_PSEL(UART_RX, 0, 8)>;
                low-power-enable;
            };
        };
        spi0_default: spi0-default {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 0, 19)>,
                    <NRF_PSEL(SPIM_MISO, 0, 21)>,
                    <NRF_PSEL(SPIM_MOSI, 0, 23)>;
            };
        };
        spi0_sleep: spi0-sleep {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 0, 19)>,
                    <NRF_PSEL(SPIM_MISO, 0, 21)>,
                    <NRF_PSEL(SPIM_MOSI, 0, 23)>;
            };
        };
    };

    I do not have any logs to post. There is nothing worth while from the UART console. I will have a look with the analyzer and try to find if there is something going on.

  • This line:

    compatible = "nordic,nrf-spi";

     

    Should be:

    compatible = "nordic,nrf-spim";

    The only scenario where you want to use "nordic,nrf-spi" is for nRF52832, to avoid errata 58:

    https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev3/ERR/nRF52832/Rev3/latest/anomaly_832_58.html#anomaly_832_58

     

    The CAN sample is looking for a device compatibility for "zephyr,canbus". This seems to be missing on your end.

    You should add a root for the chosen canbus device in your .overlay:

    / {
        chosen {
            zephyr,canbus = &mcp2518;
        };
    };

     

    Kind regards,

    Håkon

  • Hi,

    Sorry for the misdirecting you with the chosen {} part. I have defined all this in my dts for the custom board and i have the 'chosen' node there.

    chosen {
            zephyr,sram = &sram0;
            zephyr,flash = &flash0;
            zephyr,code-partition = &slot0_partition;
            zephyr,shell-uart = &uart0;
            zephyr,console = &uart0;
            zephyr,spi = &mcp2518;  
            zephyr,spi0 = &spi0;    
        };

    I guess that is all good there then. right ?

    I changed the line to compatible = "nordic,nrf-spim"; as you suggested. But it did not solve my problem. Is there some option I need to set ?

    Currently I have CONFIG_CAN and CONFIG_SPI enabled in prj.conf. if I disable either of them, I get error while compiling.

    So i guess I need them. Anything else you think I am missing here ?

  • Hi,

     

    The zephyr,canbus device is not chosen. Could you try adding this to your "chosen" list?

    zephyr,canbus = &mcp2518;

     

    Kind regards,

    Håkon

Related