#raspberry-pi-pico #raspberry-pi #raspberry-silicon #place-pio


Support for the Raspberry Silicon RP2040's PIO State Machines

4 releases (2 breaking)

0.2.1 Dec 26, 2022
0.2.0 Mar 6, 2022
0.1.0 Dec 11, 2021
0.0.1 Jan 23, 2018

#59 in Hardware support

Download history 2200/week @ 2023-11-02 2309/week @ 2023-11-09 2593/week @ 2023-11-16 2412/week @ 2023-11-23 2782/week @ 2023-11-30 2386/week @ 2023-12-07 2541/week @ 2023-12-14 2155/week @ 2023-12-21 2098/week @ 2023-12-28 2207/week @ 2024-01-04 2413/week @ 2024-01-11 2247/week @ 2024-01-18 2401/week @ 2024-01-25 2140/week @ 2024-02-01 2805/week @ 2024-02-08 2237/week @ 2024-02-15

9,982 downloads per month
Used in 58 crates (17 directly)

MIT license

774 lines


Support for the Raspberry Silicon RP2040's PIO State Machines.

What is PIO?

See https://www.raspberrypi.com/news/what-is-pio/. You can also read the PIO section in the (very well written) RP2040 datasheet: https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf.

What is pio-rs?

PIO programs must be compiled from PIO Assembly Language into a special PIO machine code. This machine code is then stored in your C or Rust program, and program is copied to the PIO hardware at the relevant point in time.

Raspberry Pi provide a PIO assembler called pioasm, and it lives at https://github.com/raspberrypi/pico-sdk/tree/master/tools/pioasm. This is an excellent choice if you want use the Raspberry Pi Pico SDK (https://github.com/raspberrypi/pico-sdk) to write C or C++ programs for your RP2040.

The pio-rs project provides an alternative implementation of pioasm. The main benefits are:

  • It's easier to integrate into an Embedded Rust program for the RP2040 than pioasm
  • The compiler itself can be included in your Embedded Rust program, so you can compile PIO code on the RP2040, at run-time!
  • Writing an assembler was a good way to test our understanding of the specification.
  • It's written in Rust :)

How do I use pio-rs?

If you want to write a program in Rust that uses the RP2040's PIO block, there are three ways to use pio-rs:


There is a macro called pio! which allows you to place PIO assembly language source into your Rust program. This source code is assembled into a PIO program at compile time.

Your Cargo.toml file should include:

pio-proc = "0.2"
pio = "0.2"

Your Rust program should contain your PIO program, as follows with PIO asm directly in the file:

use pio_proc::pio_asm;

let program_with_defines = pio_proc::pio_asm!(
    "set pindirs, 1",
    "set pins, 0 [31]",
    "set pins, 1 [31]",
    options(max_program_size = 32) // Optional, defaults to 32
let program = program_with_defines.program;

Or you can assemble a stand-alone PIO file from disk:

use pio_proc::pio_file;

let program_with_defines = pio_proc::pio_file!(
    select_program("test"), // Optional if only one program in the file
    options(max_program_size = 32) // Optional, defaults to 32
let program = program_with_defines.program;

The syntax should be the same as supported by the official pioasm tool.


You can call pio::Assembler::new() and construct a PIO program using the 'builder pattern' - effectively you are compiling a PIO program at run-time on the RP2040 itself!

// Define some simple PIO program.
const MAX_DELAY: u8 = 31;
let mut assembler = pio::Assembler::<32>::new();
let mut wrap_target = assembler.label();
let mut wrap_source = assembler.label();
// Set pin as Out
assembler.set(pio::SetDestination::PINDIRS, 1);
// Define begin of program loop
assembler.bind(&mut wrap_target);
// Set pin low
assembler.set_with_delay(pio::SetDestination::PINS, 0, MAX_DELAY);
// Set pin high
assembler.set_with_delay(pio::SetDestination::PINS, 1, MAX_DELAY);
// Define end of program loop
assembler.bind(&mut wrap_source);
// The labels wrap_target and wrap_source, as set above,
// define a loop which is executed repeatedly by the PIO
// state machine.
let program = assembler.assemble_with_wrap(wrap_source, wrap_target);

Each line starting assembler. adds a new line to the program. The completed program can be passed to the PIO driver in the Rust-language RP2040 HAL.

PIO Examples

This crate is just the PIO assembler. If you want to see some fully-featured PIO examples integrated with Embedded Rust on the RP2040, check out the rp-hal examples.


NOTE This tool is under active development. As such, it is likely to remain volatile until a 1.0.0 release.

See the open issues for a list of proposed features (and known issues).


Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request


Distributed under the MIT License. See LICENSE for more information.


Project Link: https://github.com/rp-rs/pio-rs/issues Matrix: #rp-rs:matrix.org



~33K SLoC