Writing and Compiling Rust Code for the RP2040 Chip

The Raspberry Pi Pico, powered by the RP2040 microcontroller, has gained significant popularity among embedded systems enthusiasts and hobbyists. While it’s often programmed in C/C++, Rust has also emerged as a compelling option for developing firmware for this chip. In this article, I’ll guide you through the process of writing and compiling Rust code for the RP2040 chip using the rp-hal and rp-pico crates. We’ll illustrate the process with a simple LED blink example.

Prerequisites

Before we dive into writing and compiling Rust code, make sure you have the following prerequisites in place:

  1. Rust Environment: You need Rust installed on your development machine. You can install Rust by following the instructions at rustup.rs.
  2. Cargo and Rustc: Ensure that you have Cargo (the Rust package manager) and Rustc (the Rust compiler) properly set up.
  3. RP2040 Toolchain: You’ll need the RP2040 toolchain. You can obtain it by running the following commands:
    rustup target install thumbv6m-none-eabi <br></br>cargo install flip-link <br></br>cargo install elf2uf2-rs --locked
  4. Raspberry Pi Pico: Have a Raspberry Pi Pico board on hand for testing your code.

Setting Up Your Project

Let’s create a new Rust project and configure it for the RP2040 chip.

  1. Create a new Rust project using Cargo:bash

cargo new pico-blink --bin cd pico-blink

Edit your Cargo.toml file to add dependencies:

toml

[dependencies] rp-hal = "0.5" rp-pico = "0.5"

Next, create a new main.rs file in the src directory of your project.

In main.rs, import the necessary crates and set up the main function:

// Import the necessary crates
use rp_hal::prelude::*;
use rp_pico::hal::pac as rp2040;

fn main() { // Your code will go here }

Now, let’s write a simple LED blink code for the RP2040 chip. We will blink the built-in LED (pin 25) on the Raspberry Pi Pico.

use rp_hal::prelude::*;
use rp_pico::hal::pac as rp2040;
fn main() {
// Initialise the RP2040 peripherals
let mut pac = rp2040::Peripherals::take().unwrap();
let mut watchdog = rp2040::WATCHDOG::take().unwrap();
// Configure GPIO pin 25 as an output
let mut gpio = rp2040::GPIO::take().unwrap();
gpio.gpio25_ctrl.write(|w| w.funcsel().bits(1)); // 1 corresponds to GPIO function
gpio.gpio25_oe.modify(|_, w| w.bits(1)); // Set pin 25 as an output

// Main loop loop
{
// Turn the LED on
gpio.gpio25_set.write(|w| w.bits(1));
// Delay for a while
for _ in 0..1_000_000 { cortex_m::asm::nop(); }

// Turn the LED off
gpio.gpio25_clr.write(|w| w.bits(1));

// Delay for a while
for _ in 0..1_000_000 { cortex_m::asm::nop(); }
}
}

This code initialises the RP2040 peripherals, configures pin 25 as an output, and enters a loop to toggle the LED state, creating a blinking effect.

Compiling and Flashing

To compile your Rust code and flash it onto the Raspberry Pi Pico, follow these steps:

  1. Build the code:bash

cargo build --release

Convert the resulting binary into a UF2 format file compatible with the Pico:

bash

  1. cargo objcopy --release -- -O binary target/thumbv6m-none-eabi/release/pico-blink.bin
  2. Flash the UF2 file onto the Raspberry Pi Pico:
    • Connect your Pico to your computer via USB.
    • While holding down the “BOOTSEL” button on the Pico, plug it in.
    • The Pico will appear as a USB drive. Copy the pico-blink.bin file to this drive.
    • The Pico will reset, and your Rust program will start running.

Conclusion

With the rp-hal and rp-pico crates, writing and compiling Rust code for the RP2040 chip on the Raspberry Pi Pico becomes accessible and straightforward. You can now expand upon this example to create more complex projects and explore the capabilities of Rust in embedded systems development with the RP2040 microcontroller.