How to Use CAN on Torizon OS
Introduction
In this article, we will show how to setup one or more CAN networks to be accessed in a containerized application in Torizon OS.
This article complies with the Typographic Conventions for Torizon Documentation
Prerequisites
- A Toradex SoM with Torizon OS installed
- Check if your SoM has a pin assignment for exposing the CAN signals.
- Knowledge of Device Tree Overlay on Torizon.
- Make sure to Configure the Build Environment for Torizon Containers
CAN Support on Torizon
The following Kernel modules are ready to use:
- can: CAN protocol module.
- can-dev: Standard library for CAN drivers.
- can-raw: Offers access to the CAN bus via the BSD socket API.
- can-bcm: Broadcast Manager module, offers content filtering, timeout monitoring, sending of RTR frames, and cyclic CAN messages without permanent user interaction.
- can-j1939: Available since our BSP 5, giving support for the CAN J1939 standard.
- can-gw: CAN gateway module, used to route CAN frames.
- vcan: Virtual Local CAN interface.
CAN Interfaces
Check if your module has CAN interfaces enabled at Kernel Support on CAN (Linux) article. If not, enable it by using Device Tree Overlays on Torizon OS.
Check if the interface is present by executing the command:
# ip link show can0
4: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
link/can
CAN Communication Using Containers
Create the container for interfacing with CAN. Create a Dockerfile with the content below.
DockerfileARG IMAGE_ARCH=arm64v8
# Use the parameter below for Arm 32 bits (like iMX6 and iMX7)
# ARG IMAGE_ARCH=arm32v7
FROM torizon/$IMAGE_ARCH-debian-base:3-bookworm
WORKDIR /home/torizon
RUN apt-get -y update && apt-get install -y \
nano \
python3 \
python3-pip \
python3-setuptools \
git \
iproute2 \
can-utils \
python3-can \
&& apt-get clean && apt-get autoremove && rm -rf /var/lib/apt/lists/*As you have observed, the definition of our custom container image has the following packages:
- iproute2: Which is necessary for configuring, enabling, and disabling the CAN network interfaces.
- can-utils: A set of Linux command-line utilities for debugging CAN network.
- Python3-CAN: A wrapper of SocketCAN for Python3.
- git: If you want to clone example projects/libraries to interact with CAN
- Plus, other useful tools as nano, to edit files within the container.
The most important packages are
iproute2
, which allows you to configure the CAN interface, andcan-utils
, which allows us to send and receive CAN messages using the terminal.Build the container in the host computer:
$ docker build -t can-torizon-sample .
Compress the container in a
*.tar
file so you can send it to your target development board:$ docker save -o can-torizon-sample.tar can-torizon-sample
$ scp can-torizon-sample.tar torizon@X.X.X.X:/home/torizon/Load your container directly from the tar file:
# docker load -i can-torizon-sample.tar
Check if the image is in the system:
# docker image ls
verdin-imx8mm-06612136:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
can-torizon-sample latest 5ea7a31bf664 About an hour ago 203MBRun the container
$ docker run -it --rm --name=can-test --net=host --cap-add="NET_ADMIN" \
-v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
can-torizon-sample
The key aspect behind the setup and usage of CAN on containers with Torizon OS is the usage of the following flags when running your container:
- --net=host : This will make Docker to uses the host's network stack for the container.
- --cap-add=NET_ADMIN : For interacting with the network stack, this allow to modify the network interfaces.
Once within the container console, you'll have to configure the CAN Network. This process is much similar to the setup of CAN on Linux. We'll set only one CAN interface. But depending on your CoM, you may have more CAN interfaces available.
When inside the container, configure the CAN0 interface with a bitrate of 500000 bps:
## ip link set can0 type can bitrate 500000
Bring the interface up:
## ip link set can0 up
Check if the interface is set and ready:
## ip link show can0
3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
link/can
Now you can start using applications that may connect to the CAN Network, or simply use the can-utils for testing.
For programming a Linux application in C/C++, you can use the SocketCAN API. There is also a wrapper for it in Python.
Simple testing with can-utils
One way to test if everything is OK with your CAN communication, you can do the following:
Use the
cansend <interface> <message>
to send CAN messages on a given interface. Like for example:## cansend can0 123#deadbeef
Use the
candump <interface>
command to start listening to incoming CAN messages on a given interface. If everything worked fine, a CAN message "DEADBEEF" with ID 123 on CAN will be prompted on the terminal.## candump can0
can0 123 [4] DE AD BE EF
You can read more about can-utils on its project page.
Extra Resources
- Nov/2020 - Reading Vehicle OBD-II data through CAN within a containerized application in Embedded Linux: article at CNX-Software about how to create a containerized application with TorizonCore 5 in order to read OBD-II through CAN interface using Python