Search by Tags

CAN (Linux)

 

Compare with Revision




Subscribe for this article updates

CAN requires two hardware components being a CAN controller as well as a CAN transceiver. The first component acts on the data-link layer and allows to send and receive CAN datagrams.

Our Colibri Evaluation boards have external CAN controllers (MCP2515 (on V3.x) or SJA1000 (on V2.1)) connected through SPI resp. the parallel bus. The former is supported by all Colibri modules. Colibri VFxx and iMX6 modules support in addition to the external CAN controller MCP2515 two FlexCAN controllers provided by the SoC.

The Apalis modules have two on-module CAN controllers. The Apalis T30 implement them with two MCP2515 CAN controllers while the Apalis iMX6 uses the SoC internal FlexCAN CAN controllers.

The second component, the CAN transceiver, is external and makes sure electrical specification (the physical layer) is met. CAN transceivers are available on the Colibri Evaluation Board (1 x MCP2551T) as well as on the Apalis Evaluation Board (2 x MCP2551T).

On the software side, the Linux kernel provides CAN through the SocketCAN layer, which makes use of the network socket API to communicate with devices on the CAN bus. For a short introduction to the SocketCAN layer please refer to the slides of Marc Kleine-Budde.

Prerequisites

On Colibri modules, CAN is not a standard pin mux and therefore not supported by our default image. Hence, for Colibri iMX6/T20/T30/VFxx V2.x images, the kernel and/or the device tree needs to be configured and recompiled (see Build U-Boot and Linux Kernel from Source Code).

On Apalis iMX6/T30 the CAN controllers have dedicated pins. Our Apalis standard image provide a kernel and if applicable a device tree configured for CAN.

Kernel Support for CAN in General (Colibri)

For all Colibri modules, the CAN subsystem needs to be enabled to use a CAN controller below:

  • CONFIG_CAN
  • CONFIG_CAN_RAW
  • CONFIG_CAN_BCM
  • CONFIG_CAN_DEV (depending on kernel version)

Kernel Support Colibri iMX6

For Colibri iMX6 its recommended to use the internal CAN controller rather than an external SPI connected controller if compatibility to other Colibri module types is not needed. Refer to this hardware related article.

Colibri iMX6 modules use device tree enabled kernels with the drivers for FlexCAN and (in newer kernels) MCP251x enabled in our default configuration. The drivers have to be enabled and configured in the device tree.

FlexCAN on Colibri iMX6

To use the FlexCAN1 controller on pins 63/55 add a &can1 node with a property status set to okay and remove the &pinctrl_gpio_2 from the pinctrl-0 property of the iomuxc node in arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts.

To use the FlexCAN2 controller on pins 188/178 add a &can2 node with a property status set to okay and remove the &pinctrl_weim_gpio_6 from the pinctrl-0 property of the iomuxc node in arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts.

Note: Kernel versions prior to 4.1. used a node reference &flexcan1, while starting with 4.1 the node reference is called &can1.

With the Colibri Evalution board V3.2 the CAN transceiver can be isolated from the MCP251x CAN controller with the jumpers JP4/JP5. Remove the jumpers and use jumper wires to route the FlexCAN RX/TX signals to the CAN transceiver.

e.g. for FlexCAN1:

diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
index 9c28a0e45fd0..a470c4e31dec 100644
--- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
@@ -101,6 +101,10 @@
        };
 };
 
+&can1 {
+       status = "okay";
+};
+
 /* Colibri SPI */
 &ecspi4 {
        status = "okay";
@@ -182,7 +186,6 @@
                     &pinctrl_weim_gpio_5 &pinctrl_weim_gpio_6
                     &pinctrl_csi_gpio_1
                     &pinctrl_gpio_1
-                    &pinctrl_gpio_2
                     &pinctrl_usbh_oc_1 &pinctrl_usbc_id_1>;
 
        gpio {

MPC251x on Colibri iMX6

Since 2.6 Beta2 release MCP251x is enabled by default instead of spidev and the required dummy clock is already defined in device tree.

Test if the driver is already enabled in the kernel.

root@colibri-imx6:~# zcat /proc/config.gz | grep CONFIG_CAN_MCP251X
CONFIG_CAN_MCP251X=y

If not enable it and recompile the kernel. Use the latest kernel sources as we had to backport the following commits: git cherry-pick -x 1ddff7d ae5d589 b1ef05a 369566e 05780d9 21629e1 66606aa.

The following changes are needed for the device-tree: - the spidev device must be removed and replaced with the mcp251x device. - a dummy clock must be defined so the driver knows we use a 16 MHz quartz. - the interrupt pin is already defined as gpio with pinctrl_gpio_1 so we don’t have to pinmux this separately. e.g.:

diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
index e2b8e9e..f823e47 100644
--- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
@@ -94,15 +94,39 @@
    status = "okay";
 };
 
+/ {
+   clocks {
+       /* fixed crystal dedicated to mpc251x */
+       clk16m: clk@1 {
+           compatible = "fixed-clock";
+           reg=<1>;
+           #clock-cells = <0>;
+           clock-frequency = <16000000>;
+           clock-output-names = "clk16m";
+       };
+   };
+};
+
 /* Colibri SPI */
 &ecspi4 {
    status = "okay";
 
+#if 0
    spidev0: spidev@1 {
        compatible = "spidev";
        reg = <0>;
        spi-max-frequency = <50000000>;
    };
+#else
+   can0: can@1 {
+       compatible = "microchip,mcp2515";
+       reg = <0>;
+       clocks = <&clk16m>;
+       interrupt-parent = <&gpio3>;
+       interrupts = <27 0x2>;
+       spi-max-frequency = <10000000>;
+   };
+#endif
 };
 
 &hdmi_audio {

Kernel Support Colibri VFxx

For Colibri VFxx its recommended to use the internal CAN controller rather than an external SPI connected controller if compatibility to other Colibri module types is not needed. Refer to this hardware related article.

Kernel 3.0

This not device tree enabled kernel must be recompiled with the following kernel configurations enabled:

  • CONFIG_HAVE_CAN_FLEXCAN
  • CONFIG_CAN_FLEXCAN

Kernel 3.18 and later

These device tree enabled kernels have the drivers for FlexCAN and MCP251x enabled in our default configuration. The drivers have to be enabled and configured in the device tree.

FlexCAN on Colibri VF

To use the CAN0 controller on pins 196/194 add a can0 node with a property status set to okay and change the property status of the i2c0 node to disabled to arch/arm/boot/dts/vf-colibri-eval-v3.dtsi.

To use the CAN1 controller on pins 63/55 add a can1 node with a property status set to okay to arch/arm/boot/dts/vf-colibri-eval-v3.dtsi.

With the Colibri Evaluation board V3.2 the CAN transceiver can be isolated from the MCP251x CAN controller with the jumpers JP4/JP5. Remove them and use jumper wires to route the FlexCAN RX/TX signals to the CAN transceiver.

e.g.:

diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
index 9864b21..8fc0a22 100644
--- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
@@ -77,6 +77,14 @@
        status  = "okay";
 };
 
+&can0 {
+       status = "okay";
+};
+
+&can1 {
+       status = "okay";
+};
+
 &dcu0 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_dcu0_1>;
@@ -219,7 +227,7 @@
 };
 
 &i2c0 {
-       status = "okay";
+       status = "disabled";
 
        /* TouchRevolution Fusion 7 and 10 multi-touch controller */
        touch: touchrevf0710a@10 {

MPC251x on Colibri VF

Change the status of the mcp2515can node to okay and add a status property to the spidev1 node which is disabled.

e.g.:

diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
index 9864b21..b699fc8 100644
--- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
@@ -194,13 +194,14 @@
                spi-max-frequency = <10000000>;
                interrupt-parent = <&gpio1>;
                interrupts = <11 GPIO_ACTIVE_LOW>;
-               status = "disabled";
+               status = "okay";
        };
 
        spidev1: dspi@0 {
                compatible = "spidev";
                reg = <0>;
                spi-max-frequency = <50000000>;
+               status = "disabled";
        };
 };
 

Kernel Support Colibri T20/T30

Depending on the Evaluation Board revision, the CAN controller driver:

For 3.x

  • CONFIG_CAN_MCP251X

or

For 2.x

  • CONFIG_CAN_SJA1000
  • CONFIG_CAN_SJA1000_PLATFORM

By using this configurations, the platform data for the SPI resp. parallel bus integration is automatically enabled. See also the CAN integration commit on git.toradex.com.

CAN Utilities

The CAN utilities are pre-installed on Apalis iMX6/T30 and Colibri iMX6/VFxx modules.

For all other modules, one need to install the CAN utilities plus the native IP route 2 utility (e.g. not BusyBox based) as follows:
For recent Images:

root@colibri_t30:~# opkg update
root@colibri_t30:~# opkg install canutils iproute2

For older images the required ipk packages can be built with OpenEmbedded or can be found on http://developer.toradex.com/files/toradex-dev/uploads/media/Colibri/Linux/Extra/.

For V1.x Images, the ipk packages are available from feeds for Colibri T20 as well.

root@colibri_t20:~# opkg install canutils iproute2

Note that the canutils come in two flavours, one provided by Pengutronix and a fork thereof, currently hosted at https://github.com/linux-can. Both can be built with openembedded, the former with 'bitbake canutils' and the later with 'bitbake can-utils'.

The syntax of the cansend command is different between the two. Pengutronix uses for standard / extended frame format:

cansend can1 -i 0x1F   0x11 0x22 0x33 0x44 0x55 0x55 0x77 0x88
cansend can1 -e -i 0x1F334455   0x11 0x22 0x33 0x44 0x55 0x55 0x77 0x88

while the Linux-CAN project's equivalent would be:

cansend can1 1F#1122334455667788
cansend can1 1F334455#1122334455667788

The following examples are shown in the Linux-CAN format.

Configuration/Testing

Configure

A good usage explanation of CAN specific settings can be retrieved using this help command:

# ip link set can0 type can help          
Usage: ip link set DEVICE type can
        [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | 
        [ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1
          phase-seg2 PHASE-SEG2 [ sjw SJW ] ]

        [ loopback { on | off } ]
        [ listen-only { on | off } ]
        [ triple-sampling { on | off } ]
        [ one-shot { on | off } ]
        [ berr-reporting { on | off } ]

        [ restart-ms TIME-MS ]
        [ restart ]

        Where: BITRATE       := { 1..1000000 }
               SAMPLE-POINT  := { 0.000..0.999 }
               TQ            := { NUMBER }
               PROP-SEG      := { 1..8 }
               PHASE-SEG1    := { 1..8 }
               PHASE-SEG2    := { 1..8 }
               SJW           := { 1..4 }
               RESTART-MS    := { 0 | NUMBER }

The most important configuration is the bitrate. Beside that, the interface needs to started using the up command:

ip link set can0 type can bitrate 500000
ip link set can0 up

One can also combine those commands:

ip link set can0 up type can bitrate 500000 berr-reporting on

A detailed CAN state can be retrieved using the -detail option:

# ip -details link show can0
2: can0:  mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0 
    flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
    clock 83368421

Note: There exists an incompatibility of sorts between the older L4T Linux kernel version our Tegra BSPs are based on and the newer iproute2-ss140804 from our V2.4 BSPs. Either downgrade to iproute2-ss131122 from our V2.3 BSPs or simply drop specifying a particular interface (e.g. use 'ip -details link show' instead).

Colibri EvalBoard V3.1a with built-in MCP2515 SPI CAN Controller

The following shows the bring-up of a Colibri EvalBoard V3.1a with its built-in MCP2515 SPI CAN controller connected to the Colibri T20's SPI bus:

[    4.904898] CAN device driver interface
[    4.932793] Colibri EvalBoard V3.1a/MECS Tellurium xPOD CAN Initialisation
[    4.979119] mcp251x spi3.0: probed

[    5.340662] can: controller area network core (rev 20090105 abi 8)
[    5.424355] can: raw protocol (rev 20090105)
[    5.434325] can: broadcast manager protocol (rev 20090105 t)

root@colibri-t20:~# ip link set can0 type can bitrate 125000
root@colibri-t20:~# ifconfig can0 up

[ 2616.560726] Wake5 for irq=192
[ 2616.579120] mcp251x spi3.0: CNF: 0x03 0xb5 0x01

root@colibri-t20:~# cat /proc/interrupts | grep mcp251x
192:          0          0      GPIO  mcp251x

root@colibri-t20:~# candump can0
interface = can0, family = 29, type = 3, proto = 1
<0x001> [1] 01
<0x001> [1] 01
^C

root@colibri-t20:~# cansend can0 1F334455#1122334455667788
interface = can0, family = 29, type = 3, proto = 1
root@colibri-t20:~# cansend can0 1F334455#1122334455667788
interface = can0, family = 29, type = 3, proto = 1

root@colibri-t20:~# cat /proc/interrupts | grep mcp251x
192:          4          0      GPIO  mcp251x

root@colibri-t20:~# ip -details -statistics link show can0
2: can0:  mtu 16 qdisc pfifo_fast state UNKNOWN qlen 10
    link/can
    can state ERROR-ACTIVE restart-ms 0
    bitrate 125000 sample-point 0.875
    tq 500 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
    mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
    clock 8000000
    re-started bus-errors arbit-lost error-warn error-pass bus-off
    0          0          0          0          0          0
    RX: bytes  packets  errors  dropped overrun mcast
    2          2        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    2          2        0       0       0       0

Colibri EvalBoard V2.1c with built-in SJA1000 CAN Controller on Parallel Bus

The following shows the bring-up of a Colibri EvalBoard V2.1c with its built-in SJA1000 CAN controller connected to the Colibri T20's GMI bus:

[    4.317941] CAN device driver interface
[    4.343046] sja1000 CAN netdevice driver
[    4.369867] sja1000_platform sja1000_platform.0: sja1000_platform device registered (reg_base=97800000, irq=192)

[    5.340662] can: controller area network core (rev 20090105 abi 8)
[    5.424355] can: raw protocol (rev 20090105)
[    5.434325] can: broadcast manager protocol (rev 20090105 t)

root@colibri_t20:~# ip link set can0 type can bitrate 125000

[  909.720112] sja1000_platform sja1000_platform.0: setting BTR0=0x05 BTR1=0x1c

root@colibri_t20:~# ifconfig can0 up

[  938.335586] Wake5 for irq=192

root@colibri_t20:~# cat /proc/interrupts | grep can

192:          0          0      GPIO  can0

root@colibri_t20:~# candump can0
interface = can0, family = 29, type = 3, proto = 1
<0x001> [1] 01
<0x001> [1] 01
^C

root@colibri_t20:~# cansend can0 1F334455#1122334455667788
interface = can0, family = 29, type = 3, proto = 1
root@colibri_t20:~# cansend can0 1F334455#1122334455667788
interface = can0, family = 29, type = 3, proto = 1

root@colibri_t20:~# cat /proc/interrupts | grep can
192:          4          0      GPIO  can0

root@colibri_t20:~# ip -details -statistics link show can0
2: can0:  mtu 16 qdisc pfifo_fast state UNKNOWN qlen 10
    link/can
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
    bitrate 125000 sample-point 0.875
    tq 500 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
    sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
    clock 12000000
    re-started bus-errors arbit-lost error-warn error-pass bus-off
    0          0          0          0          0          0
    RX: bytes  packets  errors  dropped overrun mcast
    2          2        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    2          2        0       0       0       0