rp-hal
Rust support for the Raspberry Pi family of microcontrollers
Explore the API docs for RP2040 or RP235x
View Demos
·
Report a Bug
·
Chat on Matrix
Table of Contents
- Getting Started
- Programming
- Roadmap
- Contributing
- License
- Contact
- Acknowledgements
## Getting Started
So, you want to program your new Raspberry Pi microcontroller, using the
Rust programming language. You've come to the right place!
This repository is `rp-hal` - a collection of high-level drivers for the
Raspberry Pi RP2040 and RP235x microcontrollers.
If you want to write an application for the RP2040, check out our [RP2040
Project Template](https://github.com/rp-rs/rp2040-project-template). If you
want to use the RP235x family, check out the [RP235x Project
Template](https://github.com/rp-rs/rp235x-project-template) instead.
If you want to write code that uses the Raspberry Pi PIO State Machines,
check out [pio-rs](https://github.com/rp-rs/pio-rs). You can even compile PIO
programs at run-time, on the MCU itself!
This repository only includes examples suitable for the Raspberry Pi Pico and
Raspberry Pi Pico 2 boards. We do also have some [*Board Support
Packages*][BSPs] which you can refer to, although note, you can also just
start with the bare HAL if you prefer (or if there is no BSP for your board
yet).
Before trying any of the examples, please ensure you have the latest stable
version of Rust installed, along with the right target support:
```sh
rustup self update
rustup update stable
rustup target add thumbv6m-none-eabi
rustup target add thumbv8m.main-none-eabihf
rustup target add riscv32imac-unknown-none-elf
```
You may also want to install probe-rs, to flash your device over the SWD pins
with a debug probe:
```sh
cargo install --locked probe-rs-tools
```
And also [picotool], if you are not using a debug probe or wish to create UF2
images for the USB bootloader. You can download a [pre-built picotool
binary][picotool-releases] for your system.
[picotool]: https://github.com/raspberrypi/picotool
[picotool-releases]: https://github.com/raspberrypi/pico-sdk-tools/releases
## Packages
There is one _Hardware Abstraction Layer_ (or HAL) crate for the RP2040, and
another for the RP235x. We also have a common HAL, and various examples.
### [rp2040-hal] - The HAL for the [Raspberry Pi RP2040]
You should include this crate in your project if you want to write a driver or
library that runs on the [Raspberry Pi RP2040], or if you are writing a Board
Support Package (see later on).
The crate provides high-level drivers for the RP2040's internal peripherals,
such as the SPI Controller and the I²C Controller. It doesn't know anything
about how your particular board is wired up (such as what each IO pin of the
RP2040 is connected to).
There are examples in this crate to show how to use various peripherals
(GPIO, I²C, SPI, UART, etc) but note that the pin-outs may not match any
particular board.
### [rp2040-hal-examples] - Examples for using [rp2040-hal]
This folder contains various examples for how to use the Rust HAL for the
RP2040. We have examples for the following (plus many more):
* GPIO
* I²C
* SPI
* UART
* Spawning tasks on Core 1
* Blinking an LED with PWM
* Using PIO
* Sleeping and waiting on the RTC
### [rp235x-hal] - The HAL for the [Raspberry Pi RP235x]
You should include this crate in your project if you want to write a driver or
library that runs on the [Raspberry Pi RP235x], or if you are writing a Board
Support Package (see later on). We call it the 'rp235x-hal' because it
supports the RP2350A, the RP2350B, and variants which include on-board Flash
such as the RP2354A and RP2354B.
The crate provides high-level drivers for the RP235x's internal peripherals,
such as the SPI Controller and the I²C Controller. It doesn't know anything
about how your particular board is wired up (such as what each IO pin of the
RP2350 is connected to).
There are examples in this crate to show how to use various peripherals
(GPIO, I²C, SPI, UART, etc) but note that the pin-outs may not match any
particular board.
This HAL fully supports the RP2350A, and has partial support for the extra
pins on the RP2350B. The versions with on-board flash (like the RP2354A)
are programmatically exactly the same as the ones without flash - the flash
is in-package, but electrically connected just like an external QSPI flash
chip - and so no additional support is required.
### [rp235x-hal-examples] - Examples for using [rp235x-hal]
This folder contains various examples for how to use the Rust HAL for the
RP2040. We have examples for the following (plus many more):
* GPIO
* I²C
* SPI
* UART
* Spawning tasks on Core 1
* Blinking an LED with PWM
* Using PIO
* Sleeping and waiting on the RTC
* Running in RISC-V mode
### [rp-hal-common] - Shared code for the two HALs
We're in the process of rationalising the two HALs into one (or, mostly into
one) and any common components will get moved here. You will likely never need
to use this library yourself.
### [rp-binary-info] - Library for generating `picotool` compatible metadata
Raspberry Pi's `picotool` program supports marking binaries with certain
metadata - the name of the program, the version number, and so on. We have
implemented support for this on the firmware side, so your Rust binaries can
also have this metadata appear in `picotool`.
### [BSPs] - Board support packages
There are BSPs for various boards based on the RP2040 available in a [separate
repository][BSPs]. They used to be in this repository, but were moved out
because there were so many of them.
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
[rp2040-hal-examples]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal-examples
[rp235x-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp235x-hal
[rp235x-hal-examples]: https://github.com/rp-rs/rp-hal/tree/main/rp235x-hal-examples
[rp-binary-info]: https://github.com/rp-rs/rp-hal/tree/main/rp-binary-info
[rp-hal-common]: https://github.com/rp-rs/rp-hal/tree/main/rp-hal-common
[Raspberry Pi RP2040]: https://www.raspberrypi.org/products/rp2040/
[Raspberry Pi RP235x]: https://www.raspberrypi.org/products/rp2350/
[BSPs]: https://github.com/rp-rs/rp-hal-boards/
## Programming
Rust generates standard Arm ELF files, which you can load onto your Raspberry
Pi microcontroller device with your favourite Arm flashing/debugging tool. In
addition, the RP2040 contains a ROM bootloader which appears as a Mass Storage
Device over USB that accepts UF2 format images. You can use picotool to flash
your device over USB, or convert the Arm ELF file to a UF2 format image.
The RP2040 contains two Cortex-M0+ processors, which execute Thumb-2 encoded
Armv6-M instructions. There are no operating-specific features in the binaries
produced - they are for 'bare-metal' systems. For compatibility with other Arm
code (e.g. as produced by GCC), Rust uses the *Arm Embedded-Application Binary
Interface* standard or EABI. Therefore, any Rust code for the RP2040 should be
compiled with the target *`thumbv6m-none-eabi`*.
The RP2350 contains two Cortex-M33 processors (each with a single-precision
FPU), which execute Thumb-2 encoded Armv8-M Mainline instructions. There are
no operating-specific features in the binaries produced - they are for
'bare-metal' systems. For compatibility with other Arm code (e.g. as produced
by GCC), Rust uses the *Arm Embedded-Application Binary Interface* standard or
EABI. Therefore, any Rust code for the RP2350 should be compiled with the
target *`thumbv8m.main-none-eabihf`*.
Each core in the RP2350 can optionally be swapped out at run-time for a RISC-V
Hazard3 processor core. Any Rust code for the RP2350 in RISC-V mode should be
compiled with the target *`riscv32imac-unknown-none-elf`*.
More details can be found in the [RP2040 Project Template] and the [RP235x
Project Template].
### Linker flags
Besides the correct target, which mainly defines the instruction set, it's
also necessary to use a certain memory layout compatible with your MCU. To
achieve that, rustc must be called with appropriate linker flags. In the
[RP2040 Project Template], those flags are defined in
[`.cargo/config.toml`](https://github.com/rp-rs/rp2040-project-template/blob/main/.cargo/config.toml).
You must also provide a file called
[`memory.x`](https://github.com/rp-rs/rp2040-project-template/blob/main/memory.x),
which is required by the [`cortex-m-rt`](https://crates.io/crates/cortex-m-rt)
start-up library we use.
More detailed information on how the linker flags work can be found in
[the `cortex-m-rt` docs](https://docs.rs/cortex-m-rt/latest/cortex_m_rt/).
In most cases, it should be sufficient to use the example files from the
[RP2040 Project Template] or [RP235x Project Template].
### Loading over USB with picotool
*Step 1* - Install a [picotool binary][picotool-releases] for your system.
*Step 2* - Make sure your .cargo/config contains the following (it should by
default if you are working in this repository):
```toml
[target.thumbv6m-none-eabi]
runner = "picotool load --update --verify --execute -t elf"
```
The `thumbv6m-none-eabi` target may be replaced by the all-Arm wildcard
`'cfg(all(target_arch = "arm", target_os = "none"))'`.
*Step 3* - Boot your RP2040 into "USB Bootloader mode", typically by rebooting
whilst holding some kind of "Boot Select" button. On Linux, you will also need
to 'mount' the device, like you would a USB Thumb Drive.
*Step 4* - Use `cargo run`, which will compile the code and start the
specified 'runner'. As the 'runner' is picotool, it will flash your compiled
binary over USB.
```sh
cd rp2040-hal-examples # Or: cd rp235x-hal-examples
cargo run --release --bin pwm-blink
```
If you want to create a UF2 file, which is loaded by copying it over to the
RPI-RP2 mass storage device, use the `picotool uf2 convert` command on your
compiled program with the `-t elf` argument.
```sh
picotool uf2 convert -t elf target/thumbv6m-none-eabi/release/pwm-blink pwm-blink.uf2
```
Picotool can also read "Binary Info" from a device with `picotool info`. To
enable this in your firmware, see the [rp-binary-info] crate and the
corresponding [binary info example].
[binary info example]: https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal-examples/src/bin/binary-info-demo.rs
### Loading with probe-rs
[probe-rs](https://github.com/probe-rs/probe-rs) is a library and a
command-line tool which can flash a wide variety of microcontrollers
using a wide variety of debug/JTAG probes. Unlike using, say, OpenOCD,
probe-rs can autodetect your debug probe, which can make it easier to use.
*Step 1* - Install `probe-rs`:
Follow the installation instructions at the [probe-rs website](https://probe.rs/).
*Step 2* - Make sure your .cargo/config contains the following:
```toml
[target.thumbv6m-none-eabi]
runner = "probe-rs run --chip RP2040"
```
*Step 3* - Connect your USB JTAG/debug probe (such as a Raspberry Pi Pico
running [this firmware](https://github.com/majbthrd/DapperMime)) to the SWD
programming pins on your RP2040 board. Check the probe has been found by
running:
```