2415467_en-US

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

2415467_en-US

2415467_en-US

2-CH CAN HAT with FRDM-IMX93

Enabling a 2-Channel CAN HAT (MCP2515) on the NXP i.MX93 FRDM Board


This article documents the process of adding hardware support for a 2-Channel CAN HAT from WaveShare using dual Microchip MCP2515 controllers over SPI on the NXP i.MX93 FRDM evaluation board.

By default, the board exposes native FlexCAN interfaces, but utilizing a popular Raspberry Pi-compatible CAN HAT requires customizing the Linux device tree and kernel configuration.


Prerequisites


Hardware: NXP i.MX93 FRDM board, 2-Channel CAN HAT.

Software: NXP Linux BSP (Tested in 6.18.y).

Toolchain: Toolchain obtained from Yocto (Refer to the 4.5.12 How to build U-Boot and Kernel in standalone environment from i.MX Linux User's Guide).


Step 1: Modify the Device Tree


We need to edit the main board device tree file arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts to configure the SPI master, add the dual MCP2515 nodes, assign interrupt pins, and disable conflicting native interfaces.

The key changes:


  • Power Regulators: Ensured the expansion connectors (VEXP_3V3 and VEXP_5V) correctly pull up and preserve state using pinctrl-assert-gpios.
  • Fixed Clock: Defined an external 16MHz clock element required by the MCP2515 crystal oscillators.
  • FlexCAN Deactivation: Disabled conflicting native flexcan2 nodes sharing pins.
  • LPSPI3 Configuration: Replaced the default spidev dummy node with two microchip,mcp2515 nodes, adding two distinct Chip Select (CS) pins (GPIO2_IO08 and GPIO2_IO07) and mapping the respective hardware interrupts (GPIO2_IO23 and GPIO2_IO25).

Device Tree Git Diff:

diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
index 18afe964e020..7b3af73f144f 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
@@ -134,6 +134,7 @@ reg_vexp_3v3: regulator-vexp-3v3 {
                compatible = "regulator-fixed";
                regulator-name = "VEXP_3V3";
                gpio = <&pcal6524 2 GPIO_ACTIVE_HIGH>;
+               pinctrl-assert-gpios = <&pcal6524 2 GPIO_ACTIVE_HIGH>;
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                enable-active-high;
@@ -144,6 +145,7 @@ reg_vexp_5v: regulator-vexp-5v {
                compatible = "regulator-fixed";
                regulator-name = "VEXP_5V";
                gpio = <&pcal6524 8 GPIO_ACTIVE_HIGH>;
+               pinctrl-assert-gpios = <&pcal6524 8 GPIO_ACTIVE_HIGH>;
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
                enable-active-high;
@@ -269,6 +271,15 @@ K3: user_btn2 {
                        interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
                };
        };
+
+       clocks {
+               clk16m: clk16m {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <16000000>;
+                       clock-output-names = "clk16m";
+               };
+       };
 };
 
 &adc1 {
@@ -292,7 +303,7 @@ &flexcan2 {
        pinctrl-0 = <&pinctrl_flexcan2>;
        pinctrl-1 = <&pinctrl_flexcan2_sleep>;
        xceiver-supply = <&reg_can2_stby>;
-       status = "okay";
+       status = "disabled";
 };
 
 &mu1 {
@@ -620,15 +631,29 @@ typec1_dr_sw: endpoint {
 &lpspi3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_lpspi3>;
-       cs-gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
-       pinctrl-assert-gpios = <&pcal6408 0 GPIO_ACTIVE_HIGH>;
+       cs-gpios = <&gpio2 8 GPIO_ACTIVE_LOW>, <&gpio2 7 GPIO_ACTIVE_LOW>;
+       pinctrl-assert-gpios = <&pcal6408 0 GPIO_ACTIVE_LOW>;
        status = "okay";
 
-       spidev0: spi@0 {
+       can0: can@0 {
+               compatible = "microchip,mcp2515";
                reg = <0>;
-               compatible = "lwn,bk4";
-               spi-max-frequency = <1000000>;
+               clocks = <&clk16m>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+               spi-max-frequency = <10000000>;
        };
+
+       can1: can@1 {
+               compatible = "microchip,mcp2515";
+               reg = <1>;
+               clocks = <&clk16m>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+               spi-max-frequency = <10000000>;
+       };
+
+
 };
 
 &lpuart1 { /* console */
@@ -894,9 +919,12 @@ MX93_PAD_GPIO_IO29__LPI2C3_SCL                     0x40000b9e
        pinctrl_lpspi3: lpspi3grp {
                fsl,pins = <
                        MX93_PAD_GPIO_IO08__GPIO2_IO08      0x39e
+                       MX93_PAD_GPIO_IO07__GPIO2_IO07      0x39e
                        MX93_PAD_GPIO_IO09__LPSPI3_SIN      0x39e
                        MX93_PAD_GPIO_IO10__LPSPI3_SOUT     0x39e
                        MX93_PAD_GPIO_IO11__LPSPI3_SCK      0x39e
+                       MX93_PAD_GPIO_IO23__GPIO2_IO23      0x39e
+                       MX93_PAD_GPIO_IO25__GPIO2_IO25      0x39e
                >;
        };

After modifying the file, compile your device tree blobs (.dtb) and deploy them to your target boot partition.

You can refer to the below post to know the process:

How to compile Linux Kernel Image and device tree using Yocto SDK.


Step 2: Enable Kernel Driver Support


The MCP251x driver must be enabled within the Linux kernel configuration framework. Run the configuration tool:

user@host:~/linux-imx$ make menuconfig

Navigate through the menu to enable the driver either statically ([*]) or as a module ([M]

  • [*] Networking support
    • <*> CAN bus subsystem support
      • <*> Raw CAN Protocol (raw access with CAN-ID filtering) 
      • <*> Broadcast Manager CAN Protocol (with content filtering)
      • <*> CAN Gateway/Router (with netlink configuration)

And:

  • Device Drivers
    • [*] Network device support
      • <*> CAN Device Drivers
        • CAN SPI interfaces
          • <*> Microchip MCP251x and MCP25625 SPI CAN controllers
          • <*> Microchip MCP251xFD SPI CAN controllers

Save your configuration and compile your kernel/modules.


Step 3: Initialize and Test Interfaces


Once the board boots with the new device tree and kernel, you should see two new network interfaces listed under ip link show (can0 and can1).

Manuel_Salas_0-1790114307590.pngManuel_Salas_0-1790114307590.png


Now, you can setup the CAN interfaces:

$ sudo ip link set can0 up type can bitrate 1000000
$ sudo ip link set can1 up type can bitrate 1000000
$ sudo ifconfig can0 txqueuelen 65536
$ sudo ifconfig can1 txqueuelen 65536

Connect the HAT in loopback:

Manuel_Salas_5-1790114793732.pngManuel_Salas_5-1790114793732.png



From Interface can0:

candump can0

From interface can1:

cansend can1 000#11.22.33.44

Manuel_Salas_1-1790114548204.pngManuel_Salas_1-1790114548204.pngManuel_Salas_2-1790114560757.pngManuel_Salas_2-1790114560757.png


Manuel_Salas_3-1790114583087.pngManuel_Salas_3-1790114583087.png



Hope this can be helpful.


Best regards,

Salas.





i.MX93
Tags (1)
No ratings
Version history
Last update:
Tuesday
Updated by: