Auf unserer Website setzen wir Cookies ein, um Ihnen den bestmöglichen Service zu bieten und unsere Website weiter verbessern zu können. Mit dem Button "Alle akzeptieren" stimmen Sie der Verwendung aller Cookies zu. Über "Auswahl akzeptieren" können Sie die verwendeten Cookies eingrenzen. Weitere Informationen und eine Option zum Widerruf Ihrer Auswahl finden Sie in unserer Datenschutzerklärung.

Notwendig:

Diese Cookies sind für die grundlegende Funktionalität notwendig. Dadurch können Sie sich auf unserer Website und im Forum anmelden oder Produkte mit unserem Online-Shop bestellen.

Statistik:

Mit diesen Cookies erheben wir anonymisiert Nutzungsdaten für unsere Website. So können wir beispielsweise sehen, welche Inhalte für unsere Besucher interessant sind und welche Auflösungen verwendet werden. Anhand der Informationen optimieren wir unsere Website, um Ihnen eine möglichst gute Benutzererfahrung bieten zu können.

Notwendig
Statistik

Mehr

Rust in PCAN-Basic: Eine speichersichere Systemprogrammiersprache erweitert die CAN-Toolbox

Die aktuelle Version der PCAN-Basic-API führt Rust-Unterstützung als Foreign-Function-Interface-(FFI)-Modul ein. Damit erhalten Rust-Entwickler direkten Zugriff auf die etablierte PCAN-Basic-API (ab Version 5.1).


Warum Rust für die CAN-Anwendungsentwicklung wichtig ist

Software für Fahrzeuge und Maschinen steht zunehmend unter dem Druck, schnell, zuverlässig, wartbar und sicher zu sein. Da Architekturen sich hin zu zonalen Designs entwickeln und immer mehr Entwicklungs-, Test-, Diagnose-, Logging-, Simulations- und Gateway-Logik auf Standard-PCs läuft, gewinnen die dafür verwendeten Programmiersprachen und APIs zunehmend an Bedeutung.
Speichersicherheitsfehler wie Pufferüberläufe, Use-after-free-Fehler, ungültige Zeigerzugriffe und Data Races können in Systemsoftware zu Abstürzen, unvorhersehbarem Verhalten und Sicherheitslücken führen. Klassische Systemsprachen wie C und C++ geben Entwicklern ein hohes Maß an Kontrolle und Performance, legen aber auch eine erhebliche Verantwortung auf die Entwickler und den umgebenden Entwicklungsprozess.

Rust begegnet dieser Herausforderung mit Ownership- und Borrowing-Regeln, die bereits zur Kompilierzeit geprüft werden. In sicherem Rust-Code verhindern diese Regeln viele Klassen von Speicher- und Nebenläufigkeitsfehlern, bevor das Programm überhaupt ausgeführt wird – und das ohne Garbage Collector. Rust macht eine Anwendung dadurch nicht automatisch funktional korrekt oder sicherheitszertifiziert, und FFI-Grenzen erfordern weiterhin besondere Sorgfalt. Dennoch kann Rust wichtige Implementierungsrisiken reduzieren und gleichzeitig native Performance sowie hardwarenahe, niedrigschwellige Kontrolle bieten.

Diese Kombination macht Rust zunehmend relevant für Automotive-Tools, Testsysteme, Diagnose, Datenerfassung, Gateways, Kommandozeilen-Utilities und andere Anwendungen, die mit CAN-Netzwerken kommunizieren. Mit PCAN-Basic 5.1 können Entwickler nun Rust nutzen, um über dasselbe etablierte API-Modell, das auch von anderen unterstützten Sprachen verwendet wird, auf PEAK-PC-CAN-Hardware zuzugreifen.

Abbildung 1: Rust bietet einen zusätzlichen Spracheinstieg in die etablierte PCAN-Basic-API und Treiberarchitektur.
 

Einführung in PCAN-Basic: die CAN-Entwicklungs-API

PCAN-Basic ist die API von PEAK für die Entwicklung von Anwendungen mit CAN CC, CAN FD und CAN XL. Sie stellt die Funktionen bereit, die für die Kommunikation mit PCAN-PC-Hardware benötigt werden, darunter Kanalinitialisierung, Bitraten-Konfiguration, Senden und Empfangen von Nachrichten, Statusabfragen, Hardware-Identifikation, Tracing und weitere Kanalparameter.

Die PCAN-Basic-Architektur besteht aus dem Gerätetreiber und einer Interface-Bibliothek, die den Zugriff auf die API-Funktionen bereitstellt. Das Produkt ist so konzipiert, dass Anwendungen mit begrenztem Aufwand zwischen den unterstützten Plattformen portiert werden können. Laut öffentlicher Produktinformation werden für PCAN-Basic allgemein Windows 11 und Windows 10 sowie Linux genannt. Die mit Version 5.1 angekündigte Rust-Unterstützung wird von PEAK als FFI-Modul mit Konsolenbeispielen dokumentiert; Entwickler sollten für die genauen Rust-Plattform- und Toolchain-Anforderungen ihres Zielsystems die aktuellen README-Dateien des Pakets und der Beispiele konsultieren.

PCAN-Basic unterstützt bereits eine breite Palette an Entwicklungssprachen, darunter C++, C#, C++/CLR, Pascal OO, VB.NET, Java sowie Python 2.x und 3.x. Version 4 führte die Unterstützung für CAN FD ein, Version 5 die Unterstützung für CAN XL, und Version 5.1 ergänzte das Rust-FFI-Modul sowie die Rust-Konsolenbeispiele. Wichtige Funktionen für Anwendungsentwickler umfassen:

  • CAN-CC-, CAN-FD- und CAN-XL-Kommunikation über protokollspezifische Initialisierungs-, Lese- und Schreibfunktionen.
  • Gleichzeitiger Betrieb mehrerer PEAK-Anwendungen und einer eigenen Anwendung auf einem physischen Kanal.
  • Bis zu 16 Kanäle je Hardwaretyp und unkomplizierter Wechsel zwischen den Kanälen.
  • Treiberseitige Empfangswarteschlangen, zeitgestempelter Empfang, Kanalstatusinformationen und konfigurierbare Empfangsereignisse.
  • Thread-sichere API-Nutzung für Multithreading-Anwendungen.
  • PCAN-Trace-Aufzeichnung sowie umfangreiche Parameter für Hardware-Identifikation, Empfangsverhalten, Logging und Tracing.

Produktseite PCAN-Basic

Die Grundlagen von Rust

Rust ist eine kompilierte Systemprogrammiersprache und keine Skriptsprache. Sie zielt auf viele der gleichen Anwendungsbereiche wie C und C++ ab, darunter Software, die vorhersehbare Performance, direkte Ressourcenkontrolle und enge Interaktion mit Betriebssystem- oder Hardware-APIs erfordert.

Ihr zentrales Merkmal ist das Ownership-Modell: Jeder Wert hat einen Eigentümer, und der Compiler prüft, wie Werte verschoben (moved), ausgeliehen (borrowed), geteilt und freigegeben werden. Lifetimes beschreiben die Beziehungen zwischen Referenzen, sodass ungültige Referenzen bereits zur Kompilierzeit abgelehnt werden können. Diese Prüfungen bieten in sicherem Rust starke Garantien und sind besonders in Multithreading-Programmen nützlich, wo Rusts Typsystem viele Data Races verhindern kann.
Die Fehlerbehandlung folgt einem ähnlich expliziten Ansatz: Operationen, die fehlschlagen können, geben in der Regel Result-Werte zurück, während optionale Werte über Option abgebildet werden. Das ermutigt den aufrufenden Code, Erfolg, Fehler und Abwesenheit von Werten bewusst zu behandeln, statt sich auf ungeprüfte Rückgabewerte oder implizite Exception-Pfade zu verlassen.

Rust bringt außerdem Cargo mit, sein Standard-Build-System und Paketmanager. Cargo verwaltet Builds, Abhängigkeiten, Tests, Beispiele und Dokumentation in einem einheitlichen Workflow. Für Teams, die es gewohnt sind, unterschiedliche Build-, Abhängigkeits- und Test-Tools rund um C oder C++ zusammenzustellen, kann diese integrierte Entwicklererfahrung einen erheblichen Produktivitätsgewinn bedeuten.

Offizielle Rust-Website

 

mod PCANBasic;
use crate::PCANBasic::*;
fn main() {
match Initialize(PCAN_USBBUS1, PCAN_BAUD_500K) {
Ok(_) => println!("PCAN-USB initialized successfully."),
Err(status) => println!("Error initializing PCAN-USB: {:?}", status)
}
}

 

Abbildung 2: Rust bietet in sicherem Code starke Sicherheitsgarantien. Aufrufe über eine FFI-Grenze hinweg müssen weiterhin dem nativen API-Vertrag entsprechen.
 


Was Rust-Unterstützung in PCAN-Basic bedeutet

PCAN-Basic 5.1 ergänzt Rust-Unterstützung als FFI-Modul. FFI ist der Mechanismus, der es Rust-Code erlaubt, Funktionen einer nativen Bibliothek aufzurufen. Praktisch bedeutet das: Die Rust-Schicht stellt einer Rust-Anwendung den bewährten PCAN-Basic-Funktionsumfang zur Verfügung, anstatt den PCAN-Treiber zu ersetzen oder die komplette API als eigenständigen, reinen Rust-Stack neu zu implementieren.
Diese Unterscheidung ist für die technische Einordnung wichtig. Entwickler gewinnen Rust-Sprachunterstützung, Rust-Projekt-Tooling und Rust-seitige Typprüfung rund um ihren Anwendungscode. Gleichzeitig müssen sie weiterhin die passende PCAN-Basic-Bibliothek und den passenden Gerätetreiber einsetzen, kompatible Hardware und Bitraten auswählen, jeden zurückgegebenen PCAN-Status prüfen und die Initialisierungs- und Aufräumregeln der API einhalten. Das Ergebnis ist eine praxisnahe Kombination: auf der einen Seite eine etablierte API und ein etablierter Treiber-Stack für den Hardwarezugriff, auf der anderen Seite eine moderne Systemsprache für die umgebende Anwendungslogik.


Vorteile für PCAN-Basic-Entwickler

Performance ohne Garbage Collector. Rust kompiliert zu nativem Code und eignet sich gut für dauerhafte Empfangsschleifen, hochfrequente Datenverarbeitung, Testautomatisierung, Protokoll-Tools und Kommandozeilen-Utilities, bei denen vorhersehbares Verhalten wichtig ist. Schutz vor häufigen Fehlern bereits zur Kompilierzeit. Sicheres Rust verhindert viele Muster ungültiger Speicherzugriffe und Data Races bereits vor der Ausführung. Das kann den Debugging-Aufwand verringern und die Wartbarkeit verbessern, ersetzt aber nicht Systemtests, Code-Reviews, statische Analyse oder Prozesse zur funktionalen Sicherheit. Explizite Status- und Fehlerbehandlung. PCAN-Basic-Operationen geben Statuswerte zurück. Rusts Result-orientierter Stil ermutigt Entwickler, diese Status in klare Erfolgs- und Fehlerpfade auf Anwendungsebene zu überführen.

Modernes Projekt-Tooling. Cargo bietet einen einheitlichen Weg, um zu bauen, zu testen, Beispiele auszuführen, Abhängigkeiten zu verwalten und Continuous Integration zu automatisieren.
Starkes Nebenläufigkeitsmodell. Rust eignet sich gut für Designs, die CAN-Empfang, Dekodierung, Logging, Benutzeroberfläche und Netzwerkweiterleitung in kontrollierte Threads oder asynchrone Tasks aufteilen. Einfachere Verteilung fokussierter Tools. Rust kann effiziente, eigenständige ausführbare Dateien erzeugen – für Fertigung, Service, Validierung, Flash-Unterstützung, Trace-Verarbeitung oder Engineering-Diagnose.

Diese Vorteile gehen mit einer Lernkurve einher. Ownership, Borrowing, Lifetimes und Trait-basierte Abstraktionen unterscheiden sich von C, C++, C# oder Python. Entwickler mit Erfahrung in der Systemprogrammierung sind gut positioniert, um Rust zu erlernen, aber Teams sollten Zeit für die Einarbeitung in die Sprache, Code-Review-Konventionen und sichere Wrapper um wiederkehrende FFI-Operationen einplanen.


Mit PCAN-Basic gelieferte Rust-Beispiele

Die Beispielübersicht spiegelt die meisten CAN-Anwendungen wider:

  • Suche nach einem verfügbaren Kanal.
  • Setzen und Auslesen von Hardware- und Kanalparametern.
  • Manuelles Lesen und Schreiben von Nachrichten.
  • Lesen von Nachrichten über einen dedizierten Thread.
  • Ereignisbasierte Benachrichtigung beim Nachrichtenempfang.
  • Erstellen einer PCAN-Trace-Datei.

Den maßgeblichen, aktuellen Quellcode erhalten Sie, indem Sie das neueste PCAN-Basic-Paket von der PEAK-PCAN-Basic-Seite herunterladen und die in Version 5.1 enthaltenen Rust-Konsolenbeispiele öffnen. Die Verwendung des mitgelieferten Beispiels ist dem Kopieren eines Blog-Ausschnitts vorzuziehen, da es das exakte Modul-Layout, die Konstanten, Datenstrukturen, die Linking-Konfiguration und die Fehlerbehandlung des veröffentlichten Pakets enthält.
 

Codebeispiel: der empfohlene erste PCAN-Basic-Rust-Workflow

Das folgende, verkürzte Beispiel zeigt den Anwendungsablauf, den ein Entwickler erwarten sollte. Es ist bewusst als workflow-orientierter Auszug dargestellt und nicht als direkt einsetzbarer Ersatz für das offizielle PEAK-Beispiel. Import-Pfade, Typnamen und Hilfsfunktionen müssen aus dem Rust-FFI-Modul des aktuellen PCAN-Basic-Pakets übernommen werden.

 

// Workflow excerpt - use the exact imports and declarations from the
// official Rust console sample supplied with PCAN-Basic 5.1.
fn main() {
// 1. Select or discover an available PCAN channel. // 2. Initialize it for the required protocol and bit rate: // CAN_Initialize(...) for CAN CC // CAN_InitializeFD(...) for CAN FD // CAN_InitializeXL(...) for CAN XL // 3. Check the returned TPCANStatus before continuing. // 4. Create the protocol-specific message structure. // 5. Transmit with CAN_Write, CAN_WriteFD, or CAN_WriteXL. // 6. Read until the receive queue reports PCAN_ERROR_QRCVEMPTY, // processing message data and the supplied receive timestamp. // 7. Query or format errors for diagnostics. // 8. Always release the channel with CAN_Uninitialize. }

 

Eine produktive Implementierung sollte diese native Aufrufsequenz in einer kleinen Rust-Abstraktion kapseln, die:

  • … den ausgewählten Kanal und Protokollmodus gemeinsam speichert, sodass Lese-/Schreibfunktionen für CAN CC, CAN FD und CAN XL nicht versehentlich vermischt werden können,
  • … jeden TPCANStatus in einen aussagekräftigen Rust-Fehlertyp umwandelt und den PEAK-Fehlertext im Log festhält,
  • … ein Guard-Objekt verwendet, dessen Drop-Implementierung den Kanal freigibt, während explizites Herunterfahren und Fehlerberichterstattung weiterhin möglich bleiben,
  • … Frame-IDs, Nachrichtentypen, DLC-/Datenlängen und Bitraten-Strings validiert, bevor die FFI-Grenze überschritten wird,
  • … die Empfangswarteschlange nach einer Benachrichtigung leert, da ein Ereignis lediglich signalisiert, dass Daten verfügbar sind, den API-Leseaufruf selbst aber nicht ersetzt,
    unsicheren Code eng auf die FFI-Aufrufe begrenzt hält und dem übrigen Programm sichere Methoden auf Anwendungsebene bereitstellt. 

Beispiel und Download: PCAN-Basic 
 

 

mod PCANBasic;
use crate::PCANBasic::*;
const BITRATE: TPCANBaudrate = PCAN_BAUD_500K;
const BITRATE_FD: &str = "\
f_clock_mhz=20, nom_brp=5, nom_tseg1=2, nom_tseg2=1, nom_sjw=1, \
data_brp=2, data_tseg1=3, data_tseg2=1, data_sjw=1";
const BITRATE_XL: &str = "\
f_clock=160000000, brp=1, nom_tseg1=255, nom_tseg2=64, nom_sjw=64, \
fd_tseg1=63, fd_tseg2=16, fd_sjw=16, fd_ssp_offset=0, \
xl_tseg1=10, xl_tseg2=9, xl_sjw=9, xl_ssp_offset=10, xl_error_signaling=1, xl_transceiver_mode_switch=0";
const MESSAGE: TPCANMsg = TPCANMsg { ID: 0x100, MSGTYPE: PCAN_MESSAGE_EXTENDED, LEN: 8, DATA: [0; 8] };
const MESSAGE_FD: TPCANMsgFD = TPCANMsgFD { ID: 0x100, MSGTYPE: PCAN_MESSAGE_FD | PCAN_MESSAGE_BRS, DLC: 15, DATA: [0; 64] };
const MESSAGE_XL: TPCANMsgXL = TPCANMsgXL { PID: 0x100, VCID: 0, AF: 0, RRS: 0, SEC: 0, SDT: 0, MSGTYPE: PCAN_MESSAGE_XL, DLC: 2047, DATA: [0; 2048] };

fn main() {
let parameters = format!("{}={}", LOOKUP_DEVICE_TYPE, "PCAN_USB");
let handle: TPCANHandle = match LookUpChannel(&parameters){
Ok(handle) => {
println!("Looked up channel");
handle
}
Err(status) => {
println!("Error looking up channel: {}", status);
return;
}
};

let features: u32 = match GetValueInt32(handle, PCAN_CHANNEL_FEATURES) {
Ok(features) => {
println!("Retrieved features");
features
}
Err(status) => {
println!("Error retrieving features: {}", status);
return;
}
};

let is_fd = (features & FEATURE_FD_CAPABLE as u32) == FEATURE_FD_CAPABLE as u32;
let is_xl = (features & FEATURE_XL_CAPABLE as u32) == FEATURE_XL_CAPABLE as u32;
let initialize_result = match (is_xl, is_fd) {
(true, _) => InitializeXL(handle, BITRATE_XL),
(false, true) => InitializeFD(handle, BITRATE_FD),
(false, false) => Initialize(handle, BITRATE),
};

match initialize_result {
Ok(_) => println!("Initialized channel"),
Err(status) => {
println!("Error initializing channel: {}", status);
return;
}
}

let write_result = match (is_xl, is_fd) {
(true, _) => WriteXL(handle, &mut MESSAGE_XL),
(false, true) => WriteFD(handle, &mut MESSAGE_FD),
(false, false) => Write(handle, &mut MESSAGE),
};

match write_result {
Ok(_) => println!("Wrote message"),
Err(status) => println!("Error writing message: {}", status),
}

loop {
let result = match (is_xl, is_fd) {
(true, _) => ReadXL(handle).map(|_| println!("Received XL message")),
(false, true) => ReadFD(handle).map(|_| println!("Received FD message")),
(false, false) => Read(handle).map(|_| println!("Received CC message")),
};

match result {
Ok(_) => continue,
Err(status) if status == PCAN_ERROR_QRCVEMPTY => break,
Err(status) => {
println!("Error reading message: {}", status);
return;
}
}
}

match Uninitialize(handle){
Ok(_) => println!("Uninitialized channel"),
Err(status) => println!("Error uninitializing channel: {}", status),
}
}

Abbildung 2: Eine robuste PCAN-Basic-Anwendung behandelt Initialisierung, Statusprüfung, Verarbeitung der Empfangswarteschlange und Aufräumen als expliziten Lebenszyklus.


Typische Anwendungsfälle

Die Kombination aus Performance, Speichersicherheitsgarantien in sicherem Code, expliziter Fehlerbehandlung und starkem Tooling macht Rust zu einer natürlichen Wahl für mehrere PCAN-Basic-Anwendungskategorien:

  • Automotive-Test und -Validierung: ECU-Stimulation, Unterstützung für Restbussimulation, automatisierte Regressionstests, HiL-Integration und Messwerkzeuge.
  • Diagnose- und Servicewerkzeuge: fokussierte Kommandozeilen- oder Desktop-Tools zum Auslesen des Status, zum Absetzen von Diagnoseanfragen über höhere Protokollschichten und zur Beweissicherung.
  • Datenerfassung und Logging: hochfrequenter Empfang, Zeitstempelverarbeitung, Filterung, Konvertierung und Erstellung von PCAN-Trace-Dateien.
  • Gateway- und Brückenanwendungen: Weiterleitung ausgewählten CAN-Verkehrs an Ethernet, Cloud-Dienste, Dateien, Datenbanken oder andere Softwareschnittstellen.
  • Fertigungs- und End-of-Line-Systeme: robuste Utilities für Konfiguration, Identifikation, Flash-Unterstützung, Verifikation und Sammlung von Testergebnissen.
  • Entwickler-Tooling: Frame-Generatoren, Protokollanalysatoren, Replay-Werkzeuge, Fuzzing-Harnesses und reproduzierbare Testtools.
  • Embedded- und IoT-Ökosysteme: Begleitwerkzeuge für Teams, die bereits Rust in eingebetteten Zielsystemen einsetzen und die PC-seitigen CAN-Tools in derselben Sprache haben möchten.

Was Rust garantiert – und was nicht

Rust kann in sicherem Rust-Code viele Speichersicherheits- und Nebenläufigkeitsfehler verhindern, doch zuverlässige Automotive-Software hängt weiterhin von korrekten Anforderungen, Protokolldesign, Timing-Verhalten, Hardwarekonfiguration, Netzwerktopologie, Fehlerbehandlung und Verifikation ab. Der Einsatz von Rust oder PCAN-Basic begründet für sich genommen weder funktionale Sicherheit noch Cybersecurity-Konformität, Echtzeitgarantien oder Freiheit von jeglichen Softwarefehlern.
Das Rust-FFI-Modul verbindet zwangsläufig sicheren Rust-Anwendungscode mit einer nativen API. Entwickler sollten daher unsichere Operationen möglichst klein halten, den API-Vertrag sorgfältig prüfen, Längen und Zeiger validieren und einen sicheren Wrapper aufbauen, der den Lebenszyklus des PCAN-Basic-Kanals korrekt abbildet. Das ist kein Nachteil, der PCAN-Basic vorbehalten wäre – es ist das übliche technische Vorgehen, sobald Rust mit einer ausgereiften nativen Bibliothek integriert wird.

A modern language for an established CAN API

Rusts wachsende Verbreitung in Systems-, Embedded-, Automotive-, Backend- und Entwickler-Tool-Entwicklung führt dazu, dass immer mehr Ingenieure PC-seitige CAN-Anwendungen in derselben Sprache entwickeln möchten, die sie auch anderswo in ihrem Stack einsetzen. PCAN-Basic 5.1 kommt dieser Nachfrage nach, indem es der etablierten PCAN-Basic-Umgebung ein Rust-FFI-Modul und einsatzbereite Konsolenbeispiele hinzufügt.
Für erfahrene C- oder C++-Entwickler bietet Rust einen Weg, native Performance und präzise Ressourcenkontrolle beizubehalten und dabei viele Speicher- und Nebenläufigkeitsprüfungen in den Compiler zu verlagern. Für jüngere Entwickler, die in OEM- und Tier-1-Softwareorganisationen einsteigen, bietet Rust modernes Tooling, explizite Fehlerbehandlung und ein Sprachökosystem, das gut zu automatisierten Tests und Continuous Integration passt.

Am wichtigsten: Entwickler müssen nicht bei einer leeren Integration beginnen. Sie können mit den offiziellen Rust-Konsolenbeispielen von PEAK starten, die Kommunikation mit einer PCAN-Schnittstelle verifizieren und das Beispiel anschließend zu einer sicheren Anwendungsarchitektur für CAN CC, CAN FD oder CAN XL weiterentwickeln.
Bereit loszulegen? Laden Sie PCAN-Basic und die offiziellen Rust-Konsolenbeispiele bei PEAK herunter. 

Download PCAN-Basic API 5.X  Download PCAN-Basic (Linux)