Play with RP2040 MCU PIO Assembler

using Rust pio-rs library



With the trend of ROE (Rust on Everything), cool kids (respectfully) have worked hard to port Rust Embedded toolchain to RP2040 MCU, in addition to many other MCUs already.

After the ubiquitous Micro-Python (also Circuit-Python) and Arduino toolchains, Rust now becomes another development platform for Raspberry Pi Foundation’s RP2040 MCU, which similar to STM32 Bluepill, provides a cheap and versatile piece of hardware. RP2040 helps you learn about ARM MCU, digital design from its excellent documentation, and Rust embedded programming in general.

The Rust rp-hal library (link) provides detailed setup information to get you started.

One interesting feature of RP2040 is its self-driving GPIO pins, called PIO. PIO has its own 9 instructions set, bunch of registers, full access to GPIO pins.

Parallax Propeller 2’s smart pin idea is kind of similar, but not exactly the same … (

In this article, we will examine a few PIO programs, as well as their disassembled instructions, as the output from the Rust assembler (pio-rs).

1. square wave output

let pm = pio_proc::pio_asm!(
"set pindirs, 1",
"set pins, 0 [5]",
"set pins, 1 [5]",
for x in &pm.code {


Rust assembler outputs three instructions:

0b111 00000 100 00001
0b111 00101 000 00000
0b111 00101 000 00001

As you can see, these are three SET instructions

  • The leading opcode 111 identifies the SET instruction (Yes, PUSH and PULL share the same opcode, that’s why 3-bit can encode 9 instructions)
  • five-clock-cycle delay is encoded in BIT12 to BIT8 field
  • 100 in “Destination” field points at PINDIR
  • SET value stays at the last 5 bits, ZERO or ONE in this case

In addition, Rust assembler also spits out some control register settings that are not represented by these three…




memento of electronics and fun exploration for my future self