class PIO – advanced PIO usage

The PIO class wraps one of the RP2040’s two Programmable I/O (PIO) blocks. Each PIO block contains an instruction memory (32 instructions) shared by four independent state machines, plus a private FIFO interface to each state machine and an IRQ controller.

Most scripts interact with PIO through StateMachine – this class is for advanced use cases that need to:

  • Load and remove programs explicitly via add_program() / remove_program().

  • Move the PIO’s GPIO base across the chip’s 32-pin window via gpio_base().

  • Hook into block-wide IRQ flags via irq().

For assembling PIO programs see rp2.asm_pio().

Constructors

class rp2.PIO(id: int)

Return the singleton PIO object for the PIO block identified by id. The RP2040 has two PIO blocks, numbered 0 and 1. Raises ValueError for any other id.

Methods

gpio_base(base: machine.Pin | int | None = None, /) int

Get or set the GPIO base for this PIO block.

The RP2040 PIO sees a 32-pin window into the GPIO space; the window can start at GPIO0 or GPIO16. The base controls which window is in effect for all state machines on this PIO.

With no argument, return the current base (the GPIO pin number, 0 or 16).

With an argument, set the base. base may be a machine.Pin instance or the integer pin number, and must resolve to GPIO0 or GPIO16. The base must be set before any program is added or state machine constructed on this PIO block.

add_program(program: Callable) None

Load program into this PIO’s instruction memory. The resulting memory layout is reused across all state machines on this PIO block.

Each PIO has only 32 instructions of program memory shared across all programs; if the new program doesn’t fit, this method raises OSError(ENOMEM). The same program can be loaded onto both PIO instances, but they consume separate memory regions.

remove_program(program: Callable | None = None, /) None

Remove program from this PIO’s instruction memory, freeing up space for new programs. If program is omitted, every program currently loaded on this PIO is removed.

Removing a program that wasn’t loaded is a no-op (no exception).

state_machine(id: int, program: Callable | None = None, *args, **kwargs) StateMachine

Return one of the four StateMachine instances owned by this PIO block. id is the local state-machine index (03).

If program is provided, the state machine is configured to run it – all positional/keyword arguments are forwarded to StateMachine.init().

Example:

>>> rp2.PIO(1).state_machine(3)
StateMachine(7)

The returned object’s global state-machine ID is pio_id * 4 + sm_id.

irq(handler: Callable[[PIO], None] | None = None, trigger: int = IRQ_SM0 | IRQ_SM1 | IRQ_SM2 | IRQ_SM3, hard: bool = False) Callable

Get or configure the block-level IRQ for this PIO.

handler is the callback to fire when any of the requested state-machine IRQs latch. The handler receives this PIO instance as its only argument; inside the handler the firing state machines can be identified via self.irq().flags() AND’d against the IRQ_SM* constants.

trigger is a bitmask of one or more IRQ_SM0 .. IRQ_SM3. The default fires on any state machine.

hard=True registers a hard-interrupt handler (no heap allocation in the callback).

MicroPython binds IRQ 0 on each PIO block; IRQ 1 is reserved and not accessible from Python.

Constants

IN_LOW: int

Pass to out_init / set_init / sideset_init of asm_pio() so the pin starts as an input driven low (i.e. tristate with the output buffer holding a 0).

IN_HIGH: int

Pass to out_init / set_init / sideset_init of asm_pio() so the pin starts as an input with the output buffer holding a 1.

OUT_LOW: int

Pass to out_init / set_init / sideset_init of asm_pio() so the pin starts as a driven output at logic 0.

OUT_HIGH: int

Pass to out_init / set_init / sideset_init of asm_pio() so the pin starts as a driven output at logic 1.

SHIFT_LEFT: int

Pass to in_shiftdir / out_shiftdir of asm_pio() or StateMachine.init() so shifts move bits towards the MSB.

SHIFT_RIGHT: int

Pass to in_shiftdir / out_shiftdir of asm_pio() or StateMachine.init() so shifts move bits towards the LSB.

JOIN_NONE: int

Pass to fifo_join of asm_pio() so the state machine has separate 4-word TX and RX FIFOs (the default).

JOIN_TX: int

Pass to fifo_join of asm_pio() so the TX FIFO is doubled to 8 words by absorbing the RX FIFO. The state machine can no longer receive data.

JOIN_RX: int

Pass to fifo_join of asm_pio() so the RX FIFO is doubled to 8 words by absorbing the TX FIFO. The state machine can no longer transmit data.

IRQ_SM0: int

irq() trigger flag: state machine 0 raised its IRQ.

IRQ_SM1: int

irq() trigger flag: state machine 1 raised its IRQ.

IRQ_SM2: int

irq() trigger flag: state machine 2 raised its IRQ.

IRQ_SM3: int

irq() trigger flag: state machine 3 raised its IRQ.