Did you know? Initializing CAN interfaces with systemd-networkd
End of January systemd 250 was added to Debian bullseye backports. With a lots of new features and fixes now comes the possibility to set the timing of CAN bus interfaces with systemd-networkd. In this blogpost I will take a look at why this helps us maintain our embedded Linux labs.
Why CAN in our labs?
At Pengutronix we run a lot of labs where we can remote control embedded Linux devices. We use these labs for interactive development and continuous testing. If you want to have a closer look at our lab infrastructure you should take a look at my talk from ELC 2021 or into our blogpost about remote working.
tl;dr: Our labs are build around a 19" server rack, an Ethernet switch, a mains power switch, a fanless x64 mini-server, and lots of USB hubs and USB devices.
One thing we learned over the years: Do not use USB if you want your embedded Linux lab to be reliable. So we started to reduce the number of USB devices where possible. Whereever we need GPIOs (for example to control the boot mode or reset of a device under test) we nowadays use the CAN-based LXA IOBus in our labs.
So reducing the number of USB devices comes at the price of maintaining a new bus in our labs.
The old way
Until now configuring this bus was a mishmash of systemd-networkd and some additional commands. networkd renamed the network device to a well-known name and set up the bitrate:
cfi@rlabA-srv:~$ cat /etc/systemd/network/80_can0-iobus.link # This file is managed by ptx-admin-ansible. Changes will be overwritten. [Match] OriginalName=can0 [Link] Name=can0_iobus cfi@rlabA-srv:~$ cat /etc/systemd/network/80_can0-iobus.network # This file is managed by ptx-admin-ansible. Changes will be overwritten. [Match] Name=can0_iobus [CAN] BitRate=100000 FDMode=False RestartSec=10s
But: Timing on a CAN bus is defined by a lot more parameters than just the bitrate. Other important parameters are:
- Sampling Point: The point in time inside a bit on the bus at which the value of the bit is determined.
- Time Quanta: The length of a sub-bit. Usually given in nanoseconds.
- Synchronization Jump Width: The number of time quanta the clocks of sending and receiving node are allowed to deviate. Especially important if some nodes on the bus derive their clock from a trimmed RC-oscillator rather than a crystal.
Since we want to set a specific sampling point and synchronization jump width for the LXA IOBus we had to set these parameters after systemd-networkd has already set up our interface. This was cumbersome done as ExecStartPre-statements in the LXA IOBus Server service-unit:
cfi@rlabA-srv:~$ cat /etc/systemd/system/lxa-iobus.service # This file is managed by ptx-admin-ansible. Changes will be overwritten. [Unit] Description=LXA iobus Server After=network.target [Service] Type=simple ExecStartPre=/bin/mkdir -p /var/cache/lxa-iobus ExecStartPre=/bin/ip l set can0_iobus down ExecStart=/bin/ip link set can0_iobus type can tq 500 prop-seg 9 phase-seg1 5 phase-seg2 5 sjw 4 ExecStartPre=/bin/ip l set can0_iobus up ExecStart=/usr/ptx-venvs/lxa-iobus/bin/lxa-iobus-server -l WARN --lss-address-cache-file /var/cache/lxa-iobus/lss-cache --host "*" can0_iobus Environment="PYTHONUNBUFFERED=1" Restart=always RestartSec=30 [Install] WantedBy=multi-user.target
While writing this blogpost I even realized that setting the detailed timing in the lxa-iobus.service -unit overrides the bitrate set in the .network -file. So consolidating this seems a good idea 😀.
The new way
Taking a look into the documentation we can change our .network file as follows:
cfi@rlabA-srv:~$ cat /etc/systemd/network/80_can0-iobus.network [Match] Name=can0_iobus [CAN] TimeQuantaNSec=500 PropagationSegment=9 PhaseBufferSegment1=5 PhaseBufferSegment2=2 SyncJumpWidth=4 RestartSec=10
Note that you can only define the bitrate or the detailed timing parameters since defining both would be overdetermined. In this case we define the detailed timing parameters. We can control the actual bitrate using:
cfi@rlabA-srv:~$ ip -detail link show dev can0_iobus 5: can0_iobus: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10 link/can promiscuity 0 minmtu 0 maxmtu 0 can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 10000 bitrate 100000 sample-point 0.750 tq 500 prop-seg 9 phase-seg1 5 phase-seg2 5 sjw 4 peak_canfd: tseg1 1..256 tseg2 1..128 sjw 1..128 brp 1..1024 brp-inc 1 peak_canfd: dtseg1 1..32 dtseg2 1..16 dsjw 1..16 dbrp 1..1024 dbrp-inc 1 clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
This week, we started our series of YouTube labgrid tutorials. In the next few weeks we will publish more video tutorials showing you labgrid's features and giving you handy tips and tricks.
Etwas über dreieinhalb Jahre sind seit unserer letzten Produktankündigung vergangen, seitdem haben wir viele Normen gelesen, Dinge über Webshops und den Alltag der Elektronikfertigung gelernt und still und heimlich an neuen Produkten getüftelt. Heute möchte ich das LXA IOBus-System vorstellen, bestehend aus einem CAN-basierten Kommunikationsprotokoll, einem zugehörigen Gateway-Server und einer neuen Klasse an Linux Automation GmbH Produkten. Zwei dieser neuen Produkte sind der Ethernet-Mux und das 4DO-3DI-3AI Input/Output-Board.
This week Linux Automation has released a CAN-FD version of the low-cost USB-to-CAN interface candleLight: the candleLight FD. And as the candleLight the candleLight FD is Open Hardware. Check the KiCad project on Github.
Have you ever experienced an otherwise fine product that is missing just the one feature you need for your application?
So you went and got yourself one of our fancy rocket-penguin branded CandleLight dongles or, being the die hard hacker you are, went and soldered one up in your toaster oven labeled "not food safe". What's next then? How do you use this thing? Let's answer these question by grabbing a Raspberry Pi and exploring some of the possibilities.