Raspberry Pi has cemented itself as one of the most popular single-board computers for embedded applications. With strong community adoption and excellent Linux support, it is a versatile platform for programming Internet of Things devices. For squeezing the most performance out of a Pi, the choice of language is also critical.
Rust has recently risen to prominence as an efficient and robust language for systems programming. Originally developed by Mozilla, it offers numerous features that make Rust an outstanding choice for embedded Raspberry Pi development…
Why Use Rust for Embedded Systems?
Rust brings several key advantages over languages like C/C++ to the table:
Memory Safety
Rust eliminates entire classes of bugs and vulnerabilities by enforcing memory safety without garbage collection. Attempting to access invalid memory results in compile-time errors rather than crashes.
Fearless Concurrency
Rust‘s borrow checker allows programs safely share access to resources across threads. This enables efficient concurrent code without data races.
Blistering Performance
Careful systems-level considerations allow Rust to compete with C/C++ for raw speed while preserving safety. No run-time or VM overhead gives it an edge over higher-level languages.
Benchmarks demonstrate Rust‘s excellent performance on embedded devices:
| Benchmark | Rust Pi 3 perf | C Pi 3 perf | % Difference |
|---|---|---|---|
| Octane | 12500 | 15000 | 20% faster |
| LINPACK | 850 MFLOP/s | 800 MFLOP/s | 6% faster |
| Mandlebrot 1000x | 22 fps | 20 fps | 10% faster |
And most importantly, Rust prevents 70%+ of vulnerabilities compared to equivalent C code according to research from Oracle Labs.
This combination of speed, small footprint, and bulletproof safety makes Rust perfect for embedded use cases. Its increasing adoption for mission-critical domains like web infrastructure (Cloudflare) and databases (MongoDB) demonstrates excellent maturity.
On 32-bit ARM devices like Raspberry Pi, the thumbv6m-none-eabi Rust target strikes a good balance of performance and compatibility….
Step-by-Step Rust Installation on Pi
Without further ado, let‘s dive into installing the powerful Rust toolchain on Raspberry Pi! We will focus on the latest stable release which is version 1.67 as of this writing.
Make sure prerequisites like git, curl, libssl are installed. We need these for building Rust programs later on:
$ sudo apt update
$ sudo apt install build-essential git curl libssl-dev
Then we can fetch the latest version of Rust by piping the install script directly from the official website to bash:
$ curl --proto ‘=https‘ --tlsv1.2 https://sh.rustup.rs -sSf | sh
info: downloading installer
info: profile set to ‘default‘
info: default host triple is arm-unknown-linux-gnueabihf
...
Rust is installed now. Great!
This tiny installer downloads required Rust components like rustc, cargo, sets up the $HOME/.cargo directories, and configures the current shell.
However, we should persist the environment variables and $PATH modifications by appending the following lines to ~/.profile:
$ export PATH="$HOME/.cargo/bin:$PATH"
Now open a new terminal, and verify everything is in order by checking versions:
$ rustc --version
rustc 1.67.0 (697fda316 2022-12-19)
$ cargo --version
cargo 1.67.0 (f0921051c 2022-12-19)
With Rust successfully set up, we are ready to start building!
Creating Our First Rust Project
Cargo is Rust‘s officially blessed build tool and package manager. Let‘s use it generate a binary crate called pi-app:
$ cargo new pi-app --bin
Created binary (application) `pi-app` package
$ ls pi-app
Cargo.toml src
This bootstrap‘s a simple Rust binary with auto-generated code and project manifests. By default src/main.rs contains a barebones program.
Replace src/main.rs with the following:
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
println!("Hello Rust!");
if args.len() > 1 {
println!("Arguments: {:?}", &args[1..]);
}
}
Here we use the built-in env::args() method to process command line arguments passed to the program. The standard library makes many things ergonomic!
Now build the project:
$ cargo build
Compiling pi-app v0.1.0 (/home/pi/projects/pi-app)
Finished dev [unoptimized + debuginfo] target(s) in 0.28 secs
And lastly run the generated executable:
$ ./target/debug/pi-app
Hello Rust!
$ ./target/debug/pi-app argument1 argument2
Hello Rust!
Arguments: ["argument1", "argument2"]
Fantastic, our first Rust program on a Pi! While simple, this shows off Rust‘s facilities for quickly building fast, reliable binaries.
Accessing RPi Hardware in Rust
Rust provides purpose-built libraries for interacting with various embedded hardware modules like GPIO, I2C, SPI etc.
For demonstration, we will blink an LED hooked up to GPIO17 (physical pin 11). The full circuit diagram looks as follows:
5V
GPIO2 -|- Resistor -|> LED -|- Ground
(17)
First, add the rppal crate which contains Raspberry Pi IO bindings to Cargo.toml:
[dependencies]
rppal = "0.14.0"
Then write a simple LED blinker in main.rs:
use rppal::gpio::{Gpio, Level, Output, Pin};
use std::{thread, time};
fn main() {
let mut led = Gpio::new().unwrap().get(17).unwrap().into_output();
loop {
led.set_high();
thread::sleep(time::Duration::from_millis(500));
led.set_low();
thread::sleep(time::Duration::from_millis(500));
}
}
Here we leverage the helper methods on Gpio to easily configure GPIO pins and write output HIGH/LOW. This repetitively pulses the LED on/off ever 500 milliseconds using Rust‘s strong timing facilities.
Build and run it:
$ cargo build --release
Compiling pi-app v0.1.0 (/home/pi/projects/pi-app)
Finished release [optimized] target(s) in 5.35 secs
$ sudo ./target/release/pi-app
Our onboard LED should now be flashing happily every half second thanks to Rust!
This provides just a small glimpse – Rust can manipulate all kinds of sensors/HATs for data logging, visualization, automation…
Additional Tips and Tricks
Here are some other useful things to know when working with Rust on Pi:
Cross Compiling
To avoid compiling on the Pi itself, install the arm-unknown-linux-gnueabihf toolchain on x86 machines. Then set the build target:
$ rustup target add arm-unknown-linux-gnueabihf
$ cargo build --target=arm-unknown-linux-gnueabihf
This enables quick iteration without needing to copy code back and forth.
Optimizing for Speed
Make sure to use cargo build --release before deployment for code optimized by the compiler. The optimizations enabled make a huge difference in runtime.
Leveraging C Libraries
Rust can interface directly with native C libraries which is useful for incorporating niche hardware drivers. Just declare an extern block:
extern "C" {
fn hardware_func(param: c_int) -> c_int;
}
GUI Libraries
For adding graphical interfaces, libraries like Iced provide reactive components while avoiding platform lock-in.
This covers some helpful starter points for going beyond basic Rust on embedded Pi.
Closing Thoughts
In closing, Rust is an extremely versatile and practical language for making the most out of Raspberry‘s impressive hardware capabilities. It combines speed, efficiency and stability in one package that feels almost purpose-built for ARM devices.
The benefits go well beyond IoT too – anywhere reliability and raw performance matter, Rust shines. Its rapid adoption across domains like web services, finance, OS kernels, simulations, and databases confirms excellent support for a wide range of workloads.
I highly recommend all Pi enthusiasts give Rust a try. It may very well become a new favorite! Let me know if you have any other questions.


