CAN (ISO 11898) bus support 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. The second component, the CAN transceiver, is external to the module and makes sure the electrical specification (the physical layer) is met. CAN transceivers are available on the Apalis and Colibri Evaluation Boards (2x resp. 1x MCP2551T).
The Apalis module family provides two mandatory on-module CAN controllers available in its standard pinout. Additional CAN controllers may be available as alternate functions (e.g. Apalis iMX8/iMX8X have 3 integrated CAN controllers). The Apalis iMX6/iMX8/iMX8X use the SoC internal FlexCAN CAN controllers, the Apalis T30 implements them with two MCP2515 CAN controllers and the Apalis TK1 integrates a separate Kinetis K20 microcontroller used amongst others for CAN.
The Colibri iMX6/iMX7/VFxx modules support two FlexCAN controllers provided by the SoC available as alternate functions while the Colibri iMX8X supports even three of them. 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.
The Verdin modules have up to two on-module CAN controllers on Reserved pins, learn more about what it means on the Verdin Family Specification. The Verdin iMX8M Mini implements them with up to two MCP2518FD CAN controllers while the Verdin iMX8M Plus implements them with FlexCAN controllers available on the SoC.
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 Marc Kleine-Budde document.
Several different high-level communication protocols can run on top of the CAN bus stack. Some examples are:
TorizonCore, our Industrial Linux Platform, is based in our Board Support Packages. So, for the compatible modules with Torizon, the support is as expected as the BSP.
When the CAN functionality is not enabled, you shall enable it using the Device Tree Overlays for TorizonCore, enabling the required features for the desired CAN interface.
You can find detailed instructions in our article How to Use CAN on TorizonCore, which present a step-by-step guide showing the configuration of the Container parameters, setup of a given CAN interface, and finalizing with an example of an application with our Torizon Extension for Visual Studio Code.
For the setup of CAN in our Reference Images for Yocto Project, you can find detailed instructions in the sections below for each of our Computer-on-Modules.
On the Apalis family, CAN is enabled by default in our BSP. That means that the kernel and, if applicable, a device tree are provided.
On Apalis iMX6/iMX8/iMX8X/T30 the CAN controllers have dedicated pins.
On Apalis TK1, CAN is provided by the separate on-module Kinetis K20 microcontroller.
NXP based Colibri modules have CAN support built-in or configured as a module by default. Once the device tree is set up to use a CAN device, the modules will get loaded automatically. However, on Colibri modules, CAN is not a standard pin mux, and therefore the corresponding pin allocation for CAN pins is not set by our default image in most of the cases. Hence, for Colibri iMX6/T20/T30/VFxx V2.x images, the kernel and/or the device tree need to be configured and recompiled (see Build U-Boot and Linux Kernel from Source Code) to support the Carrier Board CAN controller or if applicable the SoC CAN controller.
For Tegra based Colibri modules, the CAN subsystem needs to be enabled to use a CAN controller, see the 'Kernel Support Colibri T20/T30' chapter below.
For Colibri iMX6 it's 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.
To use the FlexCAN1 controller on pins 63/55 add a &can1 node with a property status set to okay, remove the &pinctrl_gpio_2 from the pinctrl-0 property of the iomuxc node in arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
and change the pinmux of the respective pins.
To use the FlexCAN2 controller on pins 188/178 add a &can2 node with a property status set to okay, 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
and change the pinmux of the respective pins.
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 Evaluation 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.
The following changes have to be done to get both can1 and can2 working:
diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dtsindex 85f88dc28434..e1b5c95d5a5e 100644--- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts+++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts@@ -97,6 +97,14 @@};};+&can1 {+ status = "okay";+};++&can2 {+ status = "okay";+};+/* Colibri SPI */&ecspi4 {status = "okay";@@ -167,10 +175,9 @@pinctrl-0 = <&pinctrl_weim_gpio_1 &pinctrl_weim_gpio_2&pinctrl_weim_gpio_3 &pinctrl_weim_gpio_4- &pinctrl_weim_gpio_5 &pinctrl_weim_gpio_6+ &pinctrl_weim_gpio_5&pinctrl_csi_gpio_1&pinctrl_gpio_1- &pinctrl_gpio_2&pinctrl_usbh_oc_1 &pinctrl_usbc_id_1>;diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/imx6qdl-colibri.dtsiindex 4172f5c68e8d..a63552b9676e 100644--- a/arch/arm/boot/dts/imx6qdl-colibri.dtsi+++ b/arch/arm/boot/dts/imx6qdl-colibri.dtsi@@ -447,14 +447,14 @@pinctrl_flexcan1: flexcan1grp {fsl,pins = <- MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x80000000- MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x80000000+ MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0+ MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0>;};pinctrl_flexcan2: flexcan2grp {fsl,pins = <- MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x80000000- MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x80000000+ MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b0+ MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b0>;};};@@ -474,8 +474,8 @@};pinctrl_gpio_2: gpio-2 {fsl,pins = <- MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0- MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0+ // MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0+ // MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0>;};};
Since 2.6 Beta2 release MCP251x is enabled by default instead of spidev and the required dummy clock is already defined in the device tree.
Test if the driver is already enabled in the kernel.
root@colibri-imx6:~# zcat /proc/config.gz | grep CONFIG_CAN_MCP251XCONFIG_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.dtsindex 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 0spidev0: 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 {
For Colibri iMX6ULL its recommended to use the internal CAN controller rather than an external SPI connected MCP251x controller if compatibility to other Colibri module types is not needed. Refer to this hardware related article. Colibri iMX6ULL modules use device tree enabled kernels with the drivers for FlexCAN built as a kernel module.
By default, FlexCAN pins are configured as GPIOs and changes in the device tree have to be done. Make sure their respective nodes are set as status = "okay"
.
FlexCAN1 controller uses SO-DIMM pins 55/63 by default and those pins are configured as GPIOs through the &pinctrl_hog_7
node. Make sure that &pinctrl_hog_7
is not being used in your device tree.
FlexCAN2 controller uses SO-DIMM pins 188/178 by default and those pins are configured as GPIOs through the &pinctrl_hog_3
node. Make sure that &pinctrl_hog_3
is not being used in your device tree.
With the Colibri Evaluation 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 (X3-A20 is CAN2 RX and X3-B12 is CAN2 TX).
Also, is recommended to disable the MCP2512 node if you are using FlexCAN interfaces.
The following snippet shows the changes to enable both FlexCAN controllers in their default pins for both Colibri iMX6ULL SKUs (WB and non-WB).
diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsiindex c462340b4b4c..a13fa58b7298 100644--- a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi+++ b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi@@ -101,7 +101,7 @@interrupt-parent = <&gpio2>;interrupts = <4 IRQ_TYPE_EDGE_FALLING>;spi-max-frequency = <10000000>;- status = "okay";+ status = "disabled";};spidev0: spidev@0 {@@ -112,7 +112,6 @@};};-#if 0&flexcan1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_flexcan1>;@@ -124,7 +123,6 @@pinctrl-0 = <&pinctrl_flexcan2>;status = "okay";};-#endif&i2c1 {pinctrl-names = "default", "gpio";
diff --git a/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi b/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsiindex 2ea2758de3b8..d8754fca90eb 100644--- a/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi+++ b/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi@@ -11,8 +11,8 @@&iomuxc {pinctrl-names = "default";- pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2 &pinctrl_hog_3- &pinctrl_hog_4 &pinctrl_hog_5 &pinctrl_hog_6 &pinctrl_hog_7>;+ pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2+ &pinctrl_hog_4 &pinctrl_hog_5 &pinctrl_hog_6>;};&iomuxc_snvs {
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsiindex 5d98763b1677..4f219fffa60d 100644--- a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi@@ -24,8 +24,8 @@&iomuxc {pinctrl-names = "default";- pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2 &pinctrl_hog_3- &pinctrl_hog_4 &pinctrl_hog_5 &pinctrl_hog_7>;+ pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2+ &pinctrl_hog_4 &pinctrl_hog_5>;};
For Colibri iMX7 its recommended to use the internal CAN controller rather than an external SPI connected MCP251x controller if compatibility to other Colibri module types is not needed.
Refer to this hardware related article. Colibri iMX7 modules use device tree enabled kernels with the drivers for FlexCAN built as a kernel module.
To use the FlexCAN2 controller on SO-DIMM pins 188/178 add a &flexcan2 node with a property status set to okay and remove the &pinctrl_gpio_4 from the pinctrl-0 property of the iomuxc node in arch/arm/boot/dts/imx7-colibri.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 the jumpers and use jumper wires to route the FlexCAN RX/TX signals to the CAN transceiver (X3-A20 is CAN2 RX and X3-B12 is CAN2 TX).
diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsiindex eeaceefdc7c4..261fe632ab08 100644--- a/arch/arm/boot/dts/imx7-colibri.dtsi+++ b/arch/arm/boot/dts/imx7-colibri.dtsi@@ -129,6 +129,12 @@fsl,magic-packet;};+&flexcan2 {+ pinctrl-names = "default";+ pinctrl-0 = <&pinctrl_flexcan2>;+ status = "okay";+};+&gpmi {pinctrl-names = "default";pinctrl-0 = <&pinctrl_gpmi_nand>;@@ -346,7 +352,7 @@&iomuxc {pinctrl-names = "default";- pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4 &pinctrl_gpio5>;+ pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio5>;pinctrl_gpio1: gpio1-grp {fsl,pins = <
For Colibri iMX8X, the CAN interface that is located at pin 63/55 is compatible with the Colibri iMX6, the Colibri iMX6ULL, the Colibri iMX7, as well as the Colibri VFxx modules. Therefore, whenever only one CAN interface is required, it is recommended to use the one available at pin 63/55. Additionally, the CAN interface on pin 34/32 is compatible with the Colibri iMX6ULL, but not with the rest of the Colibri modules.
Refer to this hardware related article. Colibri iMX8X modules use device tree enabled kernels with the drivers for FlexCAN built as a kernel module.
The kernel needs to be recompiled with the following kernel options enabled:
And, depending on the Evaluation Board revision, the CAN controller driver:
For 3.x
or
For 2.x
By using this configuration, the platform data for the SPI resp. parallel bus integration is automatically enabled. See also the CAN integration commit on git.toradex.com.
For Colibri VFxx it is 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.
This not device tree enabled kernel must be recompiled with the following kernel configurations enabled:
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.
To use the CAN0 controller on pins 196/194 add a can0 node with a property status set to okay, change the property status of the i2c0 node to disabled on 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
and remove the two GPIO pad configurations for the pins PTB16/17 in arch/arm/boot/dts/vf-colibri.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.dtsiindex dc70304..cb805c9 100644--- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi@@ -88,6 +88,15 @@status = "okay";};+&can0 {+ status = "okay";+};++&can1 {+ status = "okay";+};++&dcu0 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_dcu0_1>;@@ -133,7 +142,7 @@};&i2c0 {- status = "okay";+ status = "disabled";/* Atmel maxtouch controller */atmel_mxt_ts: atmel_mxt_ts@4a {diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsiindex 7d11341..88ae981 100644--- a/arch/arm/boot/dts/vf-colibri.dtsi+++ b/arch/arm/boot/dts/vf-colibri.dtsi@@ -276,8 +276,8 @@VF610_PAD_PTA31__GPIO_21 0x22edVF610_PAD_PTB6__GPIO_28 0x22edVF610_PAD_PTB7__GPIO_29 0x22ed- VF610_PAD_PTB16__GPIO_38 0x22ed- VF610_PAD_PTB17__GPIO_39 0x22edVF610_PAD_PTB18__GPIO_40 0x22edVF610_PAD_PTB21__GPIO_43 0x22edVF610_PAD_PTB22__GPIO_44 0x22ed
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.dtsiindex 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";};};
For using CAN with Verdin iMX8M Mini, please remember that the module does not have a native CAN Controller, which, in turn, requires the usage of an external CAN Controller through SPI port (normally).
Additional information can be found both at Controller Area Network (CAN) and SPI Sections at Verdin iMX8M Mini Datasheets.
With that in mind, you can use CAN on Verdin iMX8M Mini with the following approaches:
The Verdin iMX8M Mini DualLite 1GB and Verdin iMX8M Mini DualLite 1GB WB IT are provided without CAN Controllers on the CoM itself.
So, to use one or more external SPI CAN Controllers with them, you can use the "always" compatible SPI pins for the Verdin Family, exposed through the ECSPI2 signals at the edge connector.
These models without CAN Controllers assembled on CoM will have the ECSPI3 signals exposed in the edge connector, which you can use as well.
You can use a CAN Controller like the MCP2518, and similarly as presented in the fsl-imx8mm-verdin.dtsi device-tree file, which you can find in our Linux sources, you can assign a CAN Controller as shown below:
// You can use ecspi2 or ecspi3 in the SKUs without CAN Controller on CoM &ecspi3 { #address-cells = <1>; #size-cells = <0>; cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>, <&gpio1 5 GPIO_ACTIVE_LOW>; /* This property is required, even if marked as obsolete in the doku */ fsl,spi-num-chipselects = <2>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi3>; status = "okay"; can1: can@0 { compatible = "microchip,mcp2517fd"; clocks = <&clk20m>; gpio-controller; interrupt-parent = <&gpio1>; interrupts = <6 IRQ_TYPE_EDGE_FALLING>; microchip,clock-allways-on; microchip,clock-out-div = <1>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can1_int>; reg = <0>; spi-max-frequency = <2000000>; }; };
This is the default configuration for the SKUs of Verdin iMX8M Mini Quad 2GB WB IT and Verdin iMX8M Mini Quad 2GB IT.
Its CAN interface is already enabled by default in our Linux BSPs.
In case you want to add another SPI CAN Controller, the ECSPI3 signals, used for the embedded CAN Controller present in the CoM, are not exposed in the edge connector. So you can't use them to interface with your additional CAN Controller.
That said, a quick solution for the usage of one additional external SPI CAN Controllers is to connect it to the "always" compatible SPI pins for the Verdin Family, exposed through the ECSPI2 signals at edge connector.
And to setup this CAN controller SPI interface, you can use a similar approach for the Device-Tree as shown above for ECSPI2, for example.
The Verdin iMX8M Mini CoM is ready to hold up to 2 CAN Controllers assembled on the CoM itself. This configuration needs to be discussed with Sales for the Build-to-order.
Due to product changes on Verdin i.MX8M Mini 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.
The i.MX 8M Plus SoC features two Flexible Controller Area Network (FlexCAN) interfaces.
Both of them are available and enabled by default as Verdin Reserved interfaces, and therefore compatible with other Verdin modules. It doesn't mean all Verdin modules will come with 2x CAN interfaces. It means that, if a Verdin module comes with up to 2x interfaces, they will be available on the same pins.
Depending on the SoC version, the CAN interface supports the CAN Flexible Data Rate (CAN FD). Please check section 1.4.3 on Verdin iMX8M Plus datasheet for more information on which CAN version is supported by the selected Verdin iMX8M Plus module.
Select the version of your OS from the tabs below. If you don't know the version you are using, run the command cat /etc/os-release
or cat /etc/issue
on the board.
The CAN utilities are pre-installed on the Reference Minimal Image and the Reference Multimedia Image.
Note that the canutils come in two flavors, 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 Toradex reference image comes with the can-utils
fork, make sure to read the can-utils README, as we only provide a basic introduction on this article.
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 0x88cansend can1 -e -i 0x1F334455 0x11 0x22 0x33 0x44 0x55 0x55 0x77 0x88
while the Linux-CAN project's equivalent would be:
cansend can1 01F#1122334455667788cansend can1 01F334455#1122334455667788
The following examples are shown in the Linux-CAN format.
A good usage explanation of CAN specific settings can be retrieved using this help command:
# ip link set can0 type can helpUsage: ip link set DEVICE type can[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1phase-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 bitrate. Besides that, the interface needs to start using the up command:
ip link set can0 type can bitrate 500000ip 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 can02: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10link/can promiscuity 0can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1clock 83368421
The CAN utilities are pre-installed on the Console Image.
Note that the canutils come in two flavors, 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 Toradex reference image comes with the can-utils
fork, make sure to read the can-utils README, as we only provide a basic introduction on this article.
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 0x88cansend can1 -e -i 0x1F334455 0x11 0x22 0x33 0x44 0x55 0x55 0x77 0x88
while the Linux-CAN project's equivalent would be:
cansend can1 01F#1122334455667788cansend can1 01F334455#1122334455667788
The following examples are shown in the Linux-CAN format.
A good usage explanation of CAN specific settings can be retrieved using this help command:
# ip link set can0 type can helpUsage: ip link set DEVICE type can[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1phase-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 bitrate. Besides that, the interface needs to start using the up command:
ip link set can0 type can bitrate 500000ip 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 can02: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10link/can promiscuity 0can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1clock 83368421
The CAN utilities are pre-installed on Apalis iMX6/T30 and Colibri iMX7/iMX6/VFxx modules.
For all other modules, one needs to install the CAN utilities plus the native IP route 2 utility (e.g. not BusyBox based) as follows:
For recent Images:
opkg updateopkg 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.
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 0x88cansend can1 -e -i 0x1F334455 0x11 0x22 0x33 0x44 0x55 0x55 0x77 0x88
while the Linux-CAN project's equivalent would be:
cansend can1 01F#1122334455667788cansend can1 01F334455#1122334455667788
The following examples are shown in the Linux-CAN format.
A good usage explanation of CAN specific settings can be retrieved using this help command:
# ip link set can0 type can helpUsage: ip link set DEVICE type can[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1phase-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 bitrate. Besides that, the interface needs to start using the up command:
ip link set can0 type can bitrate 500000ip 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 can02: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10link/can promiscuity 0can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1clock 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).
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 125000root@colibri-t20:~# ifconfig can0 up[ 2616.560726] Wake5 for irq=192[ 2616.579120] mcp251x spi3.0: CNF: 0x03 0xb5 0x01root@colibri-t20:~# cat /proc/interrupts | grep mcp251x192: 0 0 GPIO mcp251xroot@colibri-t20:~# candump can0interface = can0, family = 29, type = 3, proto = 1<0x001> [1] 01<0x001> [1] 01^Croot@colibri-t20:~# cansend can0 1F334455#1122334455667788interface = can0, family = 29, type = 3, proto = 1root@colibri-t20:~# cansend can0 1F334455#1122334455667788interface = can0, family = 29, type = 3, proto = 1root@colibri-t20:~# cat /proc/interrupts | grep mcp251x192: 4 0 GPIO mcp251xroot@colibri-t20:~# ip -details -statistics link show can02: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN qlen 10link/cancan state ERROR-ACTIVE restart-ms 0bitrate 125000 sample-point 0.875tq 500 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1clock 8000000re-started bus-errors arbit-lost error-warn error-pass bus-off0 0 0 0 0 0RX: bytes packets errors dropped overrun mcast2 2 0 0 0 0TX: bytes packets errors dropped carrier collsns2 2 0 0 0 0
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=0x1croot@colibri_t20:~# ifconfig can0 up[ 938.335586] Wake5 for irq=192root@colibri_t20:~# cat /proc/interrupts | grep can192: 0 0 GPIO can0root@colibri_t20:~# candump can0interface = can0, family = 29, type = 3, proto = 1<0x001> [1] 01<0x001> [1] 01^Croot@colibri_t20:~# cansend can0 1F334455#1122334455667788interface = can0, family = 29, type = 3, proto = 1root@colibri_t20:~# cansend can0 1F334455#1122334455667788interface = can0, family = 29, type = 3, proto = 1root@colibri_t20:~# cat /proc/interrupts | grep can192: 4 0 GPIO can0root@colibri_t20:~# ip -details -statistics link show can02: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN qlen 10link/cancan state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0bitrate 125000 sample-point 0.875tq 500 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1clock 12000000re-started bus-errors arbit-lost error-warn error-pass bus-off0 0 0 0 0 0RX: bytes packets errors dropped overrun mcast2 2 0 0 0 0TX: bytes packets errors dropped carrier collsns2 2 0 0 0 0
If you decide to enable custom can interfaces - for example, additional CAN through SPI controllers or the i.MX FlexCAN - it may happen that the interfaces are enumerated in a random order with every boot.
To make it possible to use the can interfaces correctly, you can create udev rules. This section covers an example on how to do it, assuming all interfaces are already enabled and working.
Find out the names of the can interfaces:
# ip link
You will see can0
, can1
up-to canX
being X the number of interfaces enabled. Get the udev information for each of them:
# udevadm info -a -p $(udevadm info -q path -p /sys/class/net/can0)
Create a rules file at /etc/udev/rules.d/. Here is an example with 3 CAN interfaces, being them:
And here is the file based on properties found on the previous command:
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 name is always the same with ip link
after a few reboots.