Raspberry Pi Pico: PIO State Machine development - VSCode Plugin

Chris Hockuba
3 min readAug 11, 2021

--

PIO is essentially an assembly low-level programming language therefore it might be intimidating at the beginning for many who worked only with high-level languages. This is why I created a plugin with simple syntax highlighting for PIO.

Introduction

Raspberry Pi Pico introduced PIO State Machine, it’s quite a revolutionary concept that allows implementing any hardware protocol like I2C, SPI, SWD, JTAG, SDIO, and many others.

PIO Block Diagram

Every Pico contains two PIO blocks with 4 state machines each. Each PIO block contains a dedicated memory able to hold 32 instructions. For most protocols, this is more than enough for implementation. For more complicated ones, features available in PIO like side-set or instruction delay allow for more complicated scenarios.

PIO peripheral is so efficient and fast that you can even output VGA or DVI output from Pico. If you think about it, you wouldn’t imagine that a Cortex M0+ MCU could output a high-resolution image.

Development — PIO Plugin for Visual Studio Code

I highly recommend reading the RP2040 datasheet section PIO. It will get you familiar with PIO syntax and available instructions.

PIO instruction set.

You should be quickly up and running since there are only 9 instructions available. The example below is from picoprobe repository on Raspberry Pi GitHub.

PIO Syntax Highlighting in action

The syntax is quite straightforward but at the beginning, you might find it confusing to use after all it’s not C/C++ high-level programming language. I’ve been there and decided to create a VSCode extension able to highlight PIO assembly syntax. I found it very useful when developing my own code. Feel free to download my extension using the link below:

PIO ASM Syntax Highlighting

Tips & Tricks

  • Always use side-set instead of manually setting dedicated clock pins (especially in case of the clock signal or switching pin direction for half-duplex interfaces)
  • Instead of using NOP as a delay, place delay into instruction if possible (it will delay next instruction x amount of cycles)
  • Use wrap_target instead of JMP if possible (saves one instruction)
  • If you have a simple code sequence you can execute it manually from your C code instead of putting it into instruction memory. It’s done by writing instruction values, into the INSTR state machine register. This is especially the case when throughput isn’t that important. It will save you precious space.
  • Use available IRQs to run code asynchronously instead of checking the state of the state machine continuously.
  • Synchronize between state machines using IRQs (each state machine can set or wait for any of the IRQ flags).
  • Use labels and comments to make your PIO code more readable.
  • You can extend FIFO size from 4 to 8 by combining available FIFOs

I’m always open to new ideas or suggestions regarding the plugin, so feel free to put them in the comments section below.

--

--

Chris Hockuba

Embedded Software Engineer, Entrepreneur, FPV Drone enthusiast and Hardware hobbyist.