Nous utilisons des cookies sur notre site web afin de vous fournir le meilleur service possible et d'améliorer encore notre site web. En cliquant sur le bouton "Accepter tout", vous acceptez l'utilisation de tous les cookies. Vous pouvez limiter les cookies utilisés en cliquant sur "Accepter la sélection". Vous trouverez de plus amples informations et une option pour révoquer votre sélection dans notre politique de confidentialité.
Ces cookies sont nécessaires pour la fonctionnalité de base. Cela vous permet de vous inscrire sur notre site web et notre forum ou de commander des produits avec notre boutique en ligne.
Avec ces cookies, nous collectons des données d'utilisation anonymisées pour notre site web. Par exemple, nous pouvons voir quel contenu est intéressant pour nos visiteurs et quelles résolutions sont utilisées. Nous utilisons ces informations pour optimiser notre site web et vous offrir la meilleure expérience utilisateur possible.
plus
Vehicle and machine software is under growing pressure to be fast, dependable, maintainable, and secure. As architectures move toward zonal designs and more development, test, diagnostic, logging, simulation, and gateway logic runs on general-purpose PCs, the programming languages and APIs used for that logic matter more than ever.
Memory-safety defects such as buffer overruns, use-after-free errors, invalid pointer access, and data races can cause crashes, unpredictable behavior, and security vulnerabilities in systems software. Traditional systems languages such as C and C++ give developers a high level of control and performance, but they also place substantial responsibility on the developer and the surrounding development process.
Rust addresses this challenge with compile-time ownership and borrowing rules. In safe Rust, these rules prevent broad classes of memory and concurrency errors before the program runs, without requiring a garbage collector. Rust does not make an application automatically functionally correct or safety-certified, and FFI boundaries still require care. However, it can reduce important implementation risks while providing native-code performance and low-level control.
That combination is why Rust is increasingly relevant for automotive tooling, test systems, diagnostics, data acquisition, gateways, command-line utilities, and other applications that communicate with CAN networks. With PCAN-Basic 5.1, developers can now use Rust to access PEAK PC CAN hardware through the same established API model used by other supported languages.
Figure 1: Rust is an additional language entry point to the established PCAN-Basic API and driver architecture.
PCAN-Basic is PEAK’s API for developing applications with CAN CC, CAN FD, and CAN XL connections. It provides the functions required to communicate with PCAN PC hardware, including channel initialization, bit-rate configuration, message transmission and reception, status queries, hardware identification, tracing, and other channel parameters.
The PCAN-Basic architecture consists of the device driver and an interface library that provides access to the API functions. The product is designed so that applications can be ported between supported platforms with limited changes. The public product information lists Windows 11 and Windows 10 as well as Linux for PCAN-Basic generally. The Rust support announced with version 5.1 is documented by PEAK as an FFI module with console samples; developers should consult the current package and sample README files for the exact Rust platform and toolchain requirements of their target deployment.
PCAN-Basic already supports a broad range of development languages, including C++, C#, C++/CLR, Pascal OO, VB.NET, Java, and Python 2.x & 3.x. Version 4 introduced CAN FD support, version 5 introduced CAN XL support, and version 5.1 added the Rust FFI module and Rust console samples.
Important capabilities for application developers include:
Rust is a compiled systems programming language rather than a scripting language. It targets many of the same application areas as C and C++, including software that requires predictable performance, direct control over resources, and close interaction with operating-system or hardware APIs.
Its defining feature is the ownership model. Every value has an owner, and the compiler checks how values are moved, borrowed, shared, and released. Lifetimes describe relationships between references so that invalid references can be rejected at compile time. These checks provide strong guarantees in safe Rust and are particularly useful in multithreaded programs, where Rust’s type system can prevent many data races.
Error handling follows a similarly explicit approach. Operations that can fail commonly return Result values, while optional values use Option. This encourages the calling code to handle success, failure, and absence deliberately instead of relying on unchecked return values or implicit exception paths.
Rust also includes Cargo, its standard build system and package manager. Cargo manages builds, dependencies, tests, examples, and documentation in a consistent workflow. For teams accustomed to assembling different build, dependency, and test tools around C or C++, this integrated developer experience can be a significant productivity benefit.
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)
}
}
Figure 2: Rust provides strong safety guarantees in safe code. Calls across an FFI boundary must still respect the native API contract.
PCAN-Basic 5.1 adds Rust support as an FFI module. FFI is the mechanism that allows Rust code to call functions provided by a native library. In practical terms, the Rust layer exposes the proven PCAN-Basic function set to a Rust application rather than replacing the PCAN driver or reimplementing the complete API as an independent pure-Rust stack.
This distinction is important for technical clarity. Developers gain Rust language support, Rust project tooling, and Rust-side type checking around their application code. At the same time, they must deploy the correct PCAN-Basic library and device driver, select compatible hardware and bit rates, check every returned PCAN status, and follow the API’s initialization and cleanup rules.
The result is a practical combination: an established hardware-access API and driver stack on one side, and a modern systems language for the surrounding application logic on the other.
Performance without a garbage collector. Rust compiles to native code and is well suited to continuous receive loops, high-rate data processing, test automation, protocol tooling, and command-line utilities where predictable behavior matters.
Compile-time protection against common defects. Safe Rust prevents many invalid-memory-access and data-race patterns before execution. This can reduce debugging effort and improve maintainability, although it does not replace system testing, code review, static analysis, or functional-safety processes.
Explicit status and error handling. PCAN-Basic operations return status values. Rust’s Result-oriented style encourages developers to convert these statuses into clear application-level success and error paths.
Modern project tooling. Cargo provides a consistent way to build, test, run examples, manage dependencies, and automate continuous integration.
Strong concurrency model. Rust is well suited to designs that separate CAN reception, decoding, logging, UI, and network forwarding into controlled threads or asynchronous tasks.
Easier distribution of focused tools. Rust can produce efficient standalone executables for manufacturing, service, validation, flashing support, trace processing, or engineering diagnostics.
These advantages come with a learning curve. Ownership, borrowing, lifetimes, and trait-based abstractions differ from C, C++, C#, or Python. Developers with systems-programming experience are well positioned to learn Rust, but teams should plan time for language onboarding, code-review conventions, and safe wrappers around repeated FFI operations.
The sample overview is useful because it reflects the operations most CAN applications need:
For the authoritative, current source code, download the latest PCAN-Basic package from the PEAK PCAN-Basic page and open the Rust console samples included with version 5.1. Using the shipped sample is preferable to copying a blog snippet because it contains the exact module layout, constants, data structures, linking configuration, and error handling for the released package.
The following abbreviated example shows the application flow a developer should expect. It is intentionally presented as a workflow-oriented excerpt rather than a drop-in replacement for the official PEAK sample. Import paths, type names, and helper functions must be taken from the Rust FFI module delivered in the current PCAN-Basic package.
// 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. }
A production implementation should wrap this native call sequence in a small Rust abstraction that:
Official example and download: PCAN-Basic product page
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(¶meters){
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),
}
}
Figure 2: PCAN-Basic 5.1 adds Rust support as a Foreign Function Interface (FFI) module and includes Rust console samples.
Rust’s combination of performance, memory-safety guarantees in safe code, explicit error handling, and strong tooling makes it a natural fit for several PCAN-Basic application categories:
Rust can prevent many memory-safety and concurrency defects in safe Rust code, but reliable automotive software still depends on correct requirements, protocol design, timing behavior, hardware configuration, network topology, error handling, and verification. The use of Rust or PCAN-Basic does not by itself establish functional safety, cybersecurity compliance, real-time guarantees, or freedom from all software defects.
The Rust FFI module necessarily connects safe Rust application code to a native API. Developers should therefore keep unsafe operations small, review the API contract carefully, validate lengths and pointers, and build a safe wrapper that represents the PCAN-Basic channel lifecycle accurately. This is not a disadvantage unique to PCAN-Basic; it is the normal engineering model whenever Rust integrates with a mature native library.
Rust’s growing footprint in systems, embedded, automotive, backend, and developer-tool development means that more engineers want to build PC-side CAN applications in the same language they use elsewhere in their stack. PCAN-Basic 5.1 meets that demand by adding a Rust FFI module and ready-to-use console samples to the established PCAN-Basic environment.
For experienced C or C++ developers, Rust offers a route to retain native performance and precise resource control while moving many memory and concurrency checks into the compiler. For younger developers entering OEM and Tier-1 software organizations, it provides modern tooling, explicit error handling, and a language ecosystem that fits well with automated testing and continuous integration.
Most importantly, developers do not have to begin with a blank integration. They can start from the official Rust console samples supplied by PEAK, verify communication with a PCAN interface, and then evolve the sample into a safe application architecture for CAN CC, CAN FD, or CAN XL.
Ready to start? Download PCAN-Basic and the official Rust console samples from PEAK.
Download PCAN-Basic API 5.X Download PCAN-Basic (Linux)