Two of the most exciting open movements in computing β the RISC-V open ISA and the Rust programming language β turn out to fit together beautifully. If you want memory-safe firmware running on open hardware, embedded Rust on RISC-V is one of the most satisfying stacks you can build. Here is how to get started.

Why Rust and RISC-V Belong Together
Both are open, modern, and built without legacy baggage. The RISC-V ISA gives you a clean, royalty-free instruction set; Rust gives you memory safety without a garbage collector. On a microcontroller β where a stray pointer can hard-fault a device in the field β that safety is worth a great deal. And because Rust is built on LLVM, which has strong RISC-V code generation, the two have grown up alongside each other.
Picking a Target
Rust identifies platforms with target triples. For RISC-V the common ones are:
riscv32imac-unknown-none-elfβ bare-metal RV32 microcontrollersriscv64gc-unknown-none-elfβ bare-metal RV64riscv64gc-unknown-linux-gnuβ full Linux userspace on RV64
The letters after riscv32/riscv64 are the ISA extensions you are compiling for. Adding a bare-metal target is one command:
rustup target add riscv32imac-unknown-none-elfThe no_std World
Firmware has no operating system, so embedded Rust is #![no_std] β it drops the OS-dependent standard library and uses the core library instead. A minimal entry point leans on the riscv-rt runtime crate for startup and the #[entry] attribute:
#![no_std]
#![no_main]
use riscv_rt::entry;
use panic_halt as _;
#[entry]
fn main() -> ! {
loop {
// your firmware logic
}
}The -> ! return type says βthis never returnsβ β exactly right for firmware that runs until power-off.
PACs and HALs: Talking to Hardware
You rarely poke registers by hand. The embedded Rust ecosystem layers two abstractions:
- PAC (Peripheral Access Crate): a generated, type-safe map of a specific chipβs registers.
- HAL (Hardware Abstraction Layer): an ergonomic API on top of the PAC (GPIO, timers, UART) that often implements the shared
embedded-haltraits.
Because many drivers target embedded-hal, a sensor driver written for one board frequently works on a RISC-V chip with little or no change β a quiet but powerful form of portability.
Flashing and Debugging
Building produces an ELF; getting it onto silicon uses the same hardware path as C. Tools like probe-rs (and classic OpenOCD + GDB) flash the binary over JTAG and let you set breakpoints on real hardware. For pure experimentation you can also run firmware under QEMU before touching a board.
cargo build --release --target riscv32imac-unknown-none-elf
# then flash with probe-rs / openocdGreat Boards to Start With
Affordable RISC-V microcontrollers with good Rust support make this approachable β see my development boards guide and the embedded/IoT overview for picks. A cheap board plus a debug probe is all you need to go from cargo build to blinking an LED on hardware you fully understand.
The Bottom Line
Embedded Rust on RISC-V pairs an open ISA with a memory-safe language, and the toolchain is genuinely ready: pick a target with rustup, write #![no_std] firmware on riscv-rt, reach hardware through a PAC and an embedded-hal HAL, and flash with probe-rs. You get C-level control with compile-time safety, on hardware whose design is open all the way down. For anyone building the next generation of reliable embedded devices, it is hard to imagine a more future-proof foundation.
Part of my RISC-V series. See also the embedded/IoT guide and development boards.



