SocketCAN auf WSL: USB CAN Adapter unter Windows nutzen

Embedded Systems Software

Diese Woche eine Praxisnotiz für Entwickler, die von der IT Abteilung mit einem Windows® Rechner zwangsverheiratet wurden und ihre Hardware-in-the-Loop (HIL) Bench Skripte trotzdem bequem lokal entwickeln und vorab testen wollen, bevor sie auf dem eigentlichen Linux® HIL deployen: SocketCAN unter WSL2 funktioniert. Der Linux Kernel will neu gebaut sein, aber dann läuft die komplette SocketCAN Toolchain lokal auf dem Windows Host, identisch zur Zielplattform.

Den produktiven HIL würde ich damit ausdrücklich nicht ablösen wollen. Die USB-Kette über usbipd-win ist für den Dauerbetrieb zu wackelig. Aber als Entwicklungs- und Vortest-Umgebung, mit derselben Toolchain wie auf dem Ziel, ist es Gold wert.

SocketCAN, kurz

SocketCAN ist seit rund 2008 Teil des Linux Kernels und behandelt CAN Busse wie jedes andere Netzwerk-Interface: can0, vcan0, ip link, tcpdump, sauberes Socket-API in C oder Python. Das can-utils Paket (github.com/linux-can/can-utils →) bringt candump, cansend, cangen, canplayer, cangw mit, alles in dem Stil, der einem von tcpdump und iproute2 vertraut ist. Wer schon einmal Wireshark auf CAN angeworfen hat, weiss wie angenehm sich der Bus aus dieser Perspektive lesen lässt.

Adapter Landschaft

Was beim Recherchieren überrascht hat: die Breite an unterstützter Hardware. Aus dem Kopf abgegrast:

Praktisch jeder Adapter, den man auf den einschlägigen Embedded Shops findet, hat einen passenden Linux Treiber. Bei der Auswahl lohnt sich ein kurzer Blick in drivers/net/can/usb/ im Kernel Source, dann weiss man sicher Bescheid.

Was man dabei ignorieren kann: viele Hersteller liefern zusätzlich eigene Linux Treiber als Download mit, weil das unter Windows der Normalfall ist. Unter Linux braucht man die in der Regel nicht. Die Mainline Treiber im Kernel decken die Geräte bereits ab, sind gepflegt, integrieren sich sauber in SocketCAN und kommen ohne DKMS Frickelei aus. Die Hersteller Pakete sind meist nur die Folge der Windows Gewohnheit, für jedes Gerät einen eigenen Treiber auszuliefern.

WSL2: usbipd-win und ein eigener Kernel

Konkret getestet mit Ubuntu unter WSL2. Die zwei Hürden:

1. USB Passthrough. Standardmässig sieht WSL2 keine USB Geräte. Mit dem Microsoft Open Source Tool usbipd-win lassen sich USB Devices an die WSL Instanz durchreichen. In einer Admin PowerShell auf dem Windows Host:

usbipd list
usbipd bind --busid 4-1            # einmalig pro Gerät, als Admin
usbipd attach --wsl --busid 4-1

In WSL erscheint das Gerät anschliessend in lsusb.

Wichtig: der Passthrough ist exklusiv. Solange das Gerät an WSL attached ist, sieht Windows es nicht mehr. Wer es zwischendurch wieder unter Windows nutzen will, muss usbipd detach --busid 4-1 aufrufen, dann taucht es im Windows Gerätemanager wieder auf.

2. CAN im Kernel. Der mitgelieferte WSL2 Kernel hat die CAN Module standardmässig nicht aktiv. modprobe can schlägt fehl, die Treiber sind schlicht nicht gebaut. Also: WSL Kernel Source von Microsoft auschecken, Config anpassen, bauen, .wslconfig auf den neuen Kernel zeigen lassen, neu starten.

In der WSL Shell:

# Build Essentials
sudo apt install -y build-essential flex bison libssl-dev libelf-dev bc dwarves

# WSL Kernel Source von GitHub ziehen
git clone --depth 1 https://github.com/microsoft/WSL2-Linux Kernel.git
cd WSL2-Linux Kernel

# Default Config übernehmen, dann CAN Optionen aktivieren
cp Microsoft/config-wsl .config
make menuconfig

Im menuconfig mindestens diese Optionen einschalten:

CONFIG_CAN=y
CONFIG_CAN_RAW=y
CONFIG_CAN_BCM=y
CONFIG_CAN_VCAN=y
CONFIG_CAN_GS_USB=y    # oder CONFIG_CAN_PEAK_USB / CONFIG_CAN_KVASER_USB / ...

Dann bauen und installieren:

make -j$(nproc)
make modules -j$(nproc)
sudo make modules_install

# bzImage auf den Windows Host kopieren
mkdir -p /mnt/c/Users/$USER/kernel
cp arch/x86/boot/bzImage /mnt/c/Users/$USER/kernel/

Auf dem Windows Host die .wslconfig (typischerweise %USERPROFILE%\.wslconfig) auf den neuen Kernel zeigen lassen:

[wsl2]
kernel=C:\\Users\\<user>\\kernel\\bzImage

Und WSL neu starten, in einer Windows PowerShell:

wsl --shutdown

Klingt nach Aufwand, ist aber Routinearbeit: Anleitung folgen, Kernel ist in unter einer Stunde gebaut. Danach läuft alles wie auf einem nativen Linux:

sudo ip link set can0 up type can bitrate 500000
candump can0

Fertig.

Was das praktisch bringt

Für Bench Skripte, die später auf einem Linux HIL laufen, ist das ein angenehmer Tag: dieselbe Toolchain auf dem Entwickler Laptop wie auf dem HIL.

Nebenbei: alte USB RS232 Dongles unter Windows 11

Derselbe usbipd-win Trick rettet auch die alten USB RS232 Dongles, deren Hersteller Treiber unter Windows 11 nicht mehr funktionieren (der Klassiker ist hier der Prolific PL2303, dem Microsoft das Treibersupport entzogen hat). Per usbipd attach an WSL durchgereicht, kennt der Linux Kernel die FTDI und Prolific Chips seit Ewigkeiten von Haus aus. Der Dongle erscheint in WSL als /dev/ttyUSB0 und tut, was er soll. minicom, screen oder pyserial sprechen normal mit ihm.

Voraussetzung dabei: das Gegenstück, also die Software, die mit dem Dongle redet, läuft auf der Linux Seite. Ein Windows-Tool, das den seriellen Port erwartet, profitiert davon nicht, denn der Passthrough ist exklusiv.

Schlüsselwörter: SocketCAN, WSL2, usbipd-win, CAN Adapter Linux, can-utils, Linux Kernel bauen, CAN unter Windows nutzen, Hardware in the Loop, PEAK PCAN, Kvaser USB, Embedded CAN Toolchain Beratung, Embedded Consulting Schweiz

CAN auf einem neuen Embedded Projekt einplanen, oder eine bestehende Toolchain ablösen? Wir helfen bei Auswahl der Adapter, Aufbau der Test-Pipeline und Integration in CI, von der Linux Host Seite bis zum eingebetteten Target.

Kontaktieren Sie uns →