Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compiling for Microcontroller

Now let’s talk about embedded systems. When it comes to compiling Rust code for a microcontroller, things work a little differently from normal desktop systems. Microcontrollers don’t usually run a full operating system like Linux or Windows. Instead, they run in a minimal environment, often with no OS at all. This is called a bare-metal environment.

Rust supports this kind of setup through its no_std mode. In normal Rust programs, the standard library (std) handles things like file systems, threads, heap allocation, and I/O. But none of those exist on a bare-metal microcontroller. So instead of std, we use a much smaller core library, which provides only the essential building blocks.

The Target Triple for Pico 2

The Raspberry Pi Pico 2 (RP2350 chip), as you already know that it is unique; it contains selectable ARM Cortex-M33 and Hazard3 RISC-V cores . You can choose which processor architecture to use.

ARM Cortex-M33 Target

For ARM mode, we have to use the target [thumbv8m.main-none-eabi](https://doc.rust-lang.org/nightly/rustc/platform-support/thumbv8m.main-none-eabi.html):

Let’s break this down:

  • Architecture (thumbv8m.main): The Cortex-M33 uses the ARM Thumb-2 instruction set for ARMv8-M architecture.
  • Vendor (none): No specific vendor designation.
  • OS (none): No operating system - it’s bare-metal.
  • ABI (eabi): Embedded Application Binary Interface, the standard calling convention for embedded ARM systems.

To install and use this target:

rustup target add thumbv8m.main-none-eabi
cargo build --target thumbv8m.main-none-eabi

RISC-V Hazard3 Target

For RISC-V mode, use the target [riscv32imac-unknown-none-elf](https://doc.rust-lang.org/nightly/rustc/platform-support/riscv32-unknown-none-elf.html):

riscv32imac-unknown-none-elf

Let’s break this down:

  • Architecture (riscv32imac): 32-bit RISC-V with I (integer), M (multiply/divide), A (atomic), and C (compressed) instruction sets.
  • Vendor (unknown): No specific vendor.
  • OS (none): No operating system - it’s bare-metal.
  • Format (elf): ELF (Executable and Linkable Format), the object file format commonly used in embedded systems.

To install and use this target:

rustup target add riscv32imac-unknown-none-elf
cargo build --target riscv32imac-unknown-none-elf

In our exercises, we’ll mostly use the ARM mode. Some crates like panic-probe don’t work in RISC-V mode.

Cargo Config

In the quick start, you might have noticed that we never manually passed the –target flag when running the cargo command. So how did it know which target to build for? That’s because the target was already configured in the .cargo/config.toml file.

This file lets you store cargo-related settings, including which target to use by default. To set it up for Pico 2 in ARM mode, create a .cargo folder in your project root and add a config.toml file with the following content:

[build]
target = "thumbv8m.main-none-eabihf"

Now you don’t have to pass –target every time. Cargo will use this automatically.