Table of Contents

CAN interface

Example available on GitHub. Check liteboard CAN example.

CAN interface is a message-oriented multi-master serial communications protocol which efficiently supports distributed realtime control.

liteSOM contains two CAN modules compatible with CAN 2.0B protocol specification. CAN Physical layer is defined by ISO 11898 therefore to connect liteSOM to CAN bus it is required to use external CAN Bus Transceiver like SN65HVD230 used on on RS485/CAN extension board.

Device Tree

can1: flexcan@02090000 {
    compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
    reg = <0x02090000 0x4000>;
    interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6UL_CLK_CAN1_IPG>,
             <&clks IMX6UL_CLK_CAN1_SERIAL>;
    clock-names = "ipg", "per";
    status = "disabled";
};

can2: flexcan@02094000 {
    compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
    reg = <0x02094000 0x4000>;
    interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6UL_CLK_CAN2_IPG>,
             <&clks IMX6UL_CLK_CAN2_SERIAL>;
    clock-names = "ipg", "per";
    status = "disabled";
};

Generic configuration for both FLEXCAN modules is defined by imx6ul.dtsi file.

To enable linux CAN driver please build your kernel with CONFIG_CAN_FLEXCAN enabled.

-> Networking support
  -> CAN bus subsystem support
    -> CAN Device Drivers
      -> Platform CAN drivers with Netlink support
        -> Support for Freescale FLEXCAN based chips

This option will activate FLEXCAN driver.

Documentation for this driver you can find in fsl-flexcan.txt file.

&iomuxc {
    pinctrl-names = "default";
    pinctrl_flexcan1: flexcan1grp{
        fsl,pins = <
            MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX  0x1b020
            MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX  0x1b020
        >;
    };
};

&can1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_flexcan1>;
    status = "okay";
};

i.MX6UL IOMUX Controller configuration required to connect liteboard with RS485/CAN extension board is defined by can1 node in imx6ul-can.dts file.

SocketCAN

Linux supports CAN interface via SocketCAN.

A […] protocol family […] implemented which provides a socket interface to user space applications and which builds upon the Linux network layer, enabling use all of the provided queueing functionality. A device driver for CAN controller hardware registers itself with the Linux network layer as a network device, so that CAN frames from the controller can be passed up to the network layer and on to the CAN protocol family module and also vice-versa. Also, the protocol family module provides an API for transport protocol modules to register, so that any number of transport protocols can be loaded or unloaded dynamically. In fact, the can core module alone does not provide any protocol and cannot be used without loading at least one additional protocol module. Multiple sockets can be opened at the same time, on different or the same protocol module and they can listen/send frames on different or the same CAN IDs. Several sockets listening on the same interface for frames with the same CAN ID are all passed the same received matching CAN frames. An application wishing to communicate using a specific transport protocol, e.g. ISO-TP, just selects that protocol when opening the socket, and then can read and write application data byte streams, without having to deal with CAN-IDs, frames, etc.

SocketCAN is defined on top of the network layer therefore it can be automatically configured via /etc/network/interfaces file

auto can0
iface can0 inet manual
        pre-up /sbin/ip link set can0 type can bitrate 125000
        up /sbin/ifconfig can0 up
        down /sbin/ifconfig can0 down

or configured in the runtime by the following commands:

CAN bus info

SocketCAN provides to the userspace various information about current CAN bus status.

SocketCAN version

# cat /proc/net/can/version 
rev 20120528 abi 9

CAN status

# ifconfig can0
can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          UP RUNNING NOARP  MTU:16  Metric:1
          RX packets:1 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:1 overruns:0 carrier:1
          collisions:0 txqueuelen:10 
          RX bytes:8 (8.0 B)  TX bytes:0 (0.0 B)
          Interrupt:19
# ip -details link show can0
2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0 
          bitrate 461538 sample-point 0.846 
          tq 166 prop-seg 5 phase-seg1 5 phase-seg2 2 sjw 1
          flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
          clock 30000000

CAN statistics

# cat /proc/net/can/stats

        2 transmitted frames (TXF)
        1 received frames (RXF)
        0 matched frames (RXMF)

        0 % total match ratio (RXMR)
        0 frames/s total tx rate (TXR)
        0 frames/s total rx rate (RXR)

        0 % current match ratio (CRXMR)
        0 frames/s current tx rate (CTXR)
        0 frames/s current rx rate (CRXR)

        0 % max match ratio (MRXMR)
        1 frames/s max tx rate (MTXR)
        1 frames/s max rx rate (MRXR)

        0 current receive list entries (CRCV)
        0 maximum receive list entries (MRCV)

can-utils

Buildroot allows you to build various tools developed by can-utils project.

To compile can-utils package please enable BR2_PACKAGE_CAN_UTILS option located in

-> Target packages
  -> Networking applications
    -> can-utils

To check description about all implemented by can-utils applications please read project README file.

Below you can find few examples with frequently used commands.

CAN sniffer

# candump -x can0
can0  TX - -  1000101F   [0] 
can0  RX - -  10B05002   [8]  00 00 00 00 00 00 00 00
can0  RX - -  10B05001   [8]  00 00 00 00 00 00 00 00
can0  RX - -  10B05004   [8]  82 85 00 00 80 00 00 00
can0  RX - -  10B0F002   [8]  00 00 00 00 00 00 00 00
can0  RX - -  10B0F001   [8]  00 00 00 00 00 00 00 00
can0  RX - -  10B0F004   [8]  87 85 00 00 80 00 00 00
can0  RX - -  10B19002   [8]  00 00 00 00 00 00 00 00
can0  RX - -  10B19001   [8]  00 00 00 00 00 00 00 00
can0  RX - -  10B19004   [8]  8C 85 00 00 A3 00 00 00

CAN sender

To send 0 length data frame to the node with address 1000101F you can use following command

cansend can0 1000101F#

To send remote frame to the node with address 1000101F you can use following command

cansend can0 1000101F#R

CAN bus load test

To test CAN bus load performance you can use following command

canbusload can0@125000 -r -t -b -c

C/C++ API

In case when you want to develop your own application to access CAN bus via SocketCAN please check Section 4 in SocketCAN readme file.

In most cases access to the CAN bus looks like access to the linux network interface . Please check pseudo-code example presented below.

int s;
struct sockaddr_can addr;
struct ifreq ifr;

/*
 * Open connection with CAN bus
 */
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);

strcpy(ifr.ifr_name, "can0" );
ioctl(s, SIOCGIFINDEX, &ifr);

addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;

bind(s, (struct sockaddr *)&addr, sizeof(addr));

/*
 * build CAN data frame
 */
struct can_frame frame;
frame.can_id = node_id | CAN_EFF_FLAG;  // node id + extended frame format
frame.can_dlc = 6;                      // data frame length 
frame.data[0] = 0x11;                   // data frame first byte
frame.data[1] = 0x22;
frame.data[2] = 0x33;
frame.data[3] = 0x44;
frame.data[4] = 0x55;
frame.data[5] = 0x66;                   // data frame last byte

/*
 * send data frame via CAN bus
 */
write(s, &frame, sizeof(frame));

Python API

Via Buildroot BR2_PACKAGE_PYTHON_CAN option located in

-> Target packages
  -> Interpreter languages and scripting
    -> External python modules
      -> python-can

you can build python-can Python3 package.

Please read python-can documentation to check how to access CAN from python based application.