CAN (Linux)
Introduction
CAN (Controller Area Network) is a robust communication protocol widely used in automotive and industrial systems to enable reliable data exchange between multiple units over a single differential pair (two-wire) bus.
This article will guide you on how to use the Controller Area Network (CAN) interface on Toradex's System on Modules (SoMs).
Keep in mind that Torizon OS is preferred for using the CAN interface due to its ease of use and smoother application development experience. For using CAN with Torizon, refer to How to Use CAN on Torizon OS.
Communicating with a CAN bus (ISO 11898) requires two hardware components: a CAN controller and a CAN transceiver.
- CAN Controller: Sends and receives CAN datagrams, acting on the data-link layer. The Controller connects to the Transceiver through the CAN RX/TX signals.
- CAN Transceiver: Transceives the datagrams to and from the Controller to the Bus, acting on the physical layer. Connects to the Controller through the CAN RX/TX signals. Connects to the Bus through the CANH/CANL differential pair.
Most Toradex System on Modules (SoMs) include a built-in CAN Controller, and some Carrier Boards include CAN Transceivers. For specific instructions for modules without CAN Controllers, refer to the CAN Interface Setup section.
On the software side, the Linux kernel provides CAN networking 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 Linux Kernel Documentation.
CAN Interface Setup
Some modules require additional configuration and setup to use the CAN interface on Toradex Reference Images. This section will show you how to apply the configuration for each of these modules.
The CAN buses are enabled by default and do not need additional configuration for most Toradex SoMs. Refer to the tabs below for reference on the modules that require specific setup. If your device is not listed, proceed to the CAN Utilities section.
The i.MX 8M Mini SoC does not have a native CAN controller, but some of the Verdin iMX8M Mini variants include an MCP2518 CAN Controller, controlled through an SPI port. For further information, refer to the Verdin iMX8M Mini Datasheet.
You can use CAN on Verdin iMX8M Mini through the following approaches:
- With the assembled CAN Controller
- With two CAN Controllers assembled on the SoM
- With an external CAN Controller
With the Assembled CAN Controller
The configuration for the built-in MCP2518 CAN Controller is enabled by default in Toradex Linux BSPs, and is available in the Verdin iMX8M Mini variants that include the controller, which are listed below:
- Verdin iMX8M Mini Quad 2GB WB IT
- Verdin iMX8M Mini Quad 2GB IT
With Two CAN Controllers Assembled on the SoM
The Verdin iMX8M Mini SoM can accommodate up to 2 CAN controllers directly on the SoM itself. To acquire a SoM with this configuration, contact us for a Build-To-Order request.
With an External CAN Controller
If your Verdin iMX8M Mini does not have a built-in CAN Controller, you can use one or more external CAN Controllers connected to the SPI interfaces. For maximum compatibility across the Verdin Family, we recommend using the Always Compatible SPI pins for the Verdin Family, exposed through the ECSPI2 signals at the edge connector.
To enable your external CAN Controller, create a Device Tree Overlay configuring the ecspi2 node, and deploy it to your module. See below the CAN configuration for the Verdin iMX8M Mini CAN Controller from the imx8mm-verdin.dtsi device tree include file, you can use it as a model for configuring the ecspi2 node in your overlay.
The Verdin iMX8M Mini SoM edge connector does not expose the ECSPI3 signals used by the on-module MCP2518 CAN controller. As a result, you cannot use it to interface the ECSPI3 pins with an additional external CAN controller.
// You can use ecspi2 or ecspi3 in the SKUs without CAN Controller on SoM
/* On-module SPI */
&ecspi3 {
#address-cells = <1>;
#size-cells = <0>;
cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>, <&gpio4 19 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi3>, <&pinctrl_tpm_spi_cs>;
status = "okay";
/* Verdin CAN_1 */
can1: can@0 {
compatible = "microchip,mcp251xfd";
clocks = <&clk40m>;
interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_can1_int>;
reg = <0>;
spi-max-frequency = <8500000>;
};
...
};
How to change CAN clock source
Due to product changes on Verdin i.MX8M Mini 2GB Quad 0055 and 0059, the CAN clock source changed from 20MHz to 40MHz. So, the projects using CAN protocol since BSP 5.7.0_devel_202205 may stop working properly. A workaround to avoid this problem is to change the CAN clock from 40MHz to 20MHz using BSP Layers and Reference Images for Yocto Project Software.
The following patch should work to change the clock-frequency of clk40m node, which is the node that describes the CAN clock source. Copy and the following .patch, and then use Yocto project layers to build an image for your project.imx8mm-verdin-clock-fix.patch
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
index d03e33a..a5ac27c 100755
--- a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
@@ -35,7 +35,7 @@
clk40m: oscillator {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <40000000>;
+ clock-frequency = <20000000>;
};
gpio-keys {
CAN is not a standard pin mux in the Colibri family. You can use CAN on Colibri modules through the following approaches:
-
Connect a CAN Controller externally to the Colibri SPI interface (Enabled by default with no additional configuration). Our images provide and enable the driver for the MCP251x CAN controller by default (
CONFIG_CAN_MCP251X). The Colibri Evaluation Board already includes the MCP251x controller. To check the MCP251x driver in your system, run the command below:# zcat /proc/config.gz | grep CONFIG_CAN_MCP251X
CONFIG_CAN_MCP251X=y -
Enable the internal CAN controllers manually by editing your module's Device Tree, as shown below.
To use the internal CAN controller rather than an external SPI connected controller, follow the steps below:
-
Create a Device Tree Overlay as shown below:
/dts-v1/;
/plugin/;
/{
compatible = "toradex,colibri-imx8x";
};
/* Optional on SODIMM 55/63 */
&can1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan2>;
status = "okay";
}; -
Deploy and Enable the overlay in your device
-
If you are using the Colibri Evaluation Board, remove jumpers
JP4/JP5and connect the FlexCAN RX/TX signals to the X38 header. This will connect the signals to the CAN transceiver, bypassing the MCP251x CAN controller.
CAN is not a standard pin mux in the Colibri family. But you can still use CAN in Colibri modules with the following methods:
-
Connect a CAN Controller externally to the Colibri SPI interface (Enabled by default with no additional configuration). Our images provide and enable the driver for the MCP251x CAN controller by default (
CONFIG_CAN_MCP251X). The Colibri Evaluation Board already includes the MCP251x controller. To check the MCP251x driver in your system, run the command below:# zcat /proc/config.gz | grep CONFIG_CAN_MCP251X
CONFIG_CAN_MCP251X=y -
Enable the internal CAN controllers manually by editing your module's Device Tree, as shown below.
To use the internal CAN controller rather than an external SPI connected controller, follow the steps below:
-
In the kernel source code, open the
imx7-colibri.dtsidevice tree include file: -
Enable the FlexCAN1 (pins 55/63) and/or FlexCAN2 (pins 178/188) interfaces in the device tree:
&flexcan1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "okay";
};
&flexcan2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "okay";
};
/* Remove pinctrl_gpio4 if you enable flexcan2 */
&iomuxc {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4>;
+ pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3>;
... -
If you are using the Colibri Evaluation Board, remove jumpers
JP4/JP5and connect the FlexCAN RX/TX signals to the X38 header. This will connect the signals to the CAN transceiver, bypassing the MCP251x CAN controller.
CAN is not a standard pin mux in the Colibri family. But you can still use CAN in Colibri modules with the following methods:
-
Connect a CAN Controller externally to the Colibri SPI interface (Enabled by default with no additional configuration). Our images provide and enable the driver for the MCP251x CAN controller by default (
CONFIG_CAN_MCP251X). The Colibri Evaluation Board already includes the MCP251x controller. To check the MCP251x driver in your system, run the command below:# zcat /proc/config.gz | grep CONFIG_CAN_MCP251X
CONFIG_CAN_MCP251X=y -
Enable the internal CAN controllers manually by editing your module's Device Tree, as shown below.
To use the internal CAN controller rather than an external SPI connected controller, follow the steps below:
-
In the kernel source code, open the
imx6ull-colibri.dtsidevice tree include file: -
Enable the FlexCAN1 (pins 55/63) and/or FlexCAN2 (pins 178/188) interfaces in the device tree:
arch/arm/boot/dts/nxp/imx/imx6ull-colibri.dtsi&can1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan1>;
- status = "disabled";
+ status = "okay";
};
&can2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan2>;
- status = "disabled";
+ status = "okay";
};infoMake sure that
&pinctrl_7and&pinctrl_3nodes are not being used in your device tree. -
If you are using the Colibri Evaluation Board, remove jumpers
JP4/JP5and connect the FlexCAN RX/TX signals to the X38 header. This will connect the signals to the CAN transceiver, bypassing the MCP251x CAN controller.
CAN is not a standard pin mux in the Colibri family. But you can still use CAN in Colibri modules with the following methods:
-
Connect a CAN Controller externally to the Colibri SPI interface (Enabled by default with no additional configuration). Our images provide and enable the driver for the MCP251x CAN controller by default (
CONFIG_CAN_MCP251X). The Colibri Evaluation Board already includes the MCP251x controller. To check the MCP251x driver in your system, run the command below:# zcat /proc/config.gz | grep CONFIG_CAN_MCP251X
CONFIG_CAN_MCP251X=y -
Enable the internal CAN controllers manually by editing your module's Device Tree, as shown below.
To use the internal CAN controller rather than an external SPI connected controller, follow the steps below:
-
In the kernel source code, open the
imx6qdl-colibri.dtsidevice tree include file: -
Enable the FlexCAN1 (pins 55/63) and/or FlexCAN2 (pins 178/188) interfaces in the device tree:
arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi/* Optional on SODIMM 55/63 */
&can1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan1>;
- status = "disabled";
+ status = "okay";
};
/* Optional on SODIMM 178/188 */
&can2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan2>;
- status = "disabled";
+ status = "okay";
}; -
If you are using the Colibri Evaluation Board, remove jumpers
JP4/JP5and connect the FlexCAN RX/TX signals to the X38 header. This will connect the signals to the CAN transceiver, bypassing the MCP251x CAN controller.
CAN Utilities
Toradex Reference Images include the can-utils package from the Linux-CAN project for controlling your module's CAN interface.
can-utils is a fork of Pengutronix's canutils, which you can optionally build into your image and use as an alternative.
To control the CAN interfaces of your device with can-utils, follow the steps below. The example shown here controls the can0 interface on a Verdin iMX8M Plus.
-
List the CAN networks available in your system using the
ipcommand. Some Toradex modules have alternate names to help you identify the corresponding CAN signals on your board. In the output shown below, thecan0interface corresponds to theCAN_1signals on the Verdin iMX8M Plus. If the alternate name is not specified, search for thecan<x>node in your module's Device Tree.# ip addr show type can4: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10
link/can
altname verdin-can1
5: can1: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10
link/can
altname verdin-can2 -
Configure and start the CAN network for the interface you wish to use. The example below sets the bitrate to 500000 and activates bus error reporting. The bitrate depends on the CAN bus your module is connected to. For further configuration options, run
ip link set can0 type can help.# ip link set can0 up type can bitrate 500000 berr-reporting on -
Confirm that the network is up with the command below. You should see
ERROR-ACTIVEin the output, indicating that the network is active.# ip -details link show can04: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0
can <BERR-REPORTING> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
bitrate 500000 sample-point 0.875
tq 25 prop-seg 37 phase-seg1 32 phase-seg2 10 sjw 5 brp 1
flexcan: tseg1 2..96 tseg2 2..32 sjw 1..16 brp 1..1024 brp_inc 1
flexcan: dtseg1 2..39 dtseg2 2..8 dsjw 1..4 dbrp 1..1024 dbrp_inc 1
clock 40000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 ...
altname verdin-can1 -
Run the command below to send the payload
1122334455667788, with01Fas the ID.# cansend can1 01F#1122334455667788 -
Run the command below to monitor the traffic in the CAN bus:
# candump can0:0,#FFFFFFFF
Custom CAN Interface Names
If you enable custom can interfaces - for example, additional CAN through SPI controllers or the i.MX FlexCAN - the interfaces may be enumerated in a random order with every boot.
You can create udev rules to configure the CAN interfaces and set standard names, as shown below:
-
Identify the names of the available CAN interfaces:
# ip link -
Get the udev information for the CAN interfaces with
udevadm. The command below shows the information forcan0.# udevadm info -a -p $(udevadm info -q path -p /sys/class/net/can0) -
Based on the properties extracted in the previous step, create a rules file at
/etc/udev/rules.d/. The example below configures 3 CAN interfaces:- CAN0: MCP251x through SPI
- CAN1: i.MX FlexCAN 1
- CAN2: i.MX FlexCAN 2
11-custom-can.rulesKERNELS=="spi0.0", SUBSYSTEMS=="spi", DRIVERS=="mcp251x", ACTION=="add", NAME="CAN0"
KERNELS=="2090000.can", ACTION=="add", NAME="CAN1"
KERNELS=="2094000.can", ACTION=="add", NAME="CAN2" -
Reload the udev rules and reboot:
# udevadm control --reload-rules
# reboot -
Confirm that the interface names are always the same with
ip link.
CAN FD
Some Toradex SoMs and carrier boards support CAN FD, which can reach transfer rates of up to 8 Mbps. Note that CAN FD is backward-compatible with standard CAN.
To enable CAN FD, use the fd and dbitrate options with the ip link set command from the basic usage instructions. The following arguments configure the transfer bitrates:
bitrate 500000sets the CAN transfer rate to be 500 kbps.dbitrate 2000000sets the CAN transfer rate to be 2 Mbps. This configuration will only be applied if the device is connected to a CAN FD bus.
# ip link set can0 up type can bitrate 500000 dbitrate 2000000 fd on
To send CAN FD frames, add an extra # between ID and payload in the cansend command, as shown below. For further information, refer to cansend's manpage.
# cansend can0 123##0112233445566778899AABBCCDDEEFF00
For more information about CAN FD, check the following references: