epio
A cycle-accurate RP2350 PIO emulator
Loading...
Searching...
No Matches
epio - A cycle exact RP2350 PIO Emulator

While RP2350 PIO programs are conceptually simple and easy to write, testing their precise behaviour is hard:

  • They operate at high speed, with limited visibility into their internal state.
  • When modifying, it is difficult to prevent them from regressing without time consuming testing on real hardware. This is particularly problematic for testing multiple hardware revisions and configuration.

epio solves both of these problems, by providing a cycle-accurate emulator for RP2350 PIO programs, that can run on non-RP2350 hosts, including CI runners. This allows you to test and verify your PIO programs in a convenient and deterministic way, without needing to rely on real hardware.

It provides a `wasm` build, allowing you to run and visualise PIO programs in the browser, with a simple JavaScript API.

To make it easy to setup, epio integrates with apio, a runtime PIO assembler and disassembler. apio allows you to write your PIO programs with C macros directly in your RP2350 firmware (avoding the need for a separate pioasm step), and run them both on real RP2350 hardware and emulated using epio on non-RP2350 hosts.

epio includes comprehensive automated testing to ensure correct, cycle exact PIO emulation behaviour, and to avoid regressions.

Why epio?

Existing PIO emulators lack comprehensive support for RP2350 PIOs, which are more advanced than RP2040 PIOs and support additional instructions. A fully tested implementation is essential to ensure the emulation can be relied upon. Being C-based allows integration with existing bare-metal RP2350 firmware, and the design targets portability across a wide range of hosts, including WASM.

Video

This video shows what is possible with epio:

https://youtu.be/eNu0JAY1Dvc?si=N3-KCYJ04APH3RlB

Video Title

Interactive Demo

Try the interactive demo of the WASM example.

Usage

See the example for a complete bare-metal RP2350 firmware with a PIO, using apio and epio. This example can be built and run on both a real RP2350 and emulated on non-RP2350 hosts. Here is a snippet that demonstrates how to use epio to run a PIO program assembled with apio:

// Call the firmware main function, which returns instead of entering an
// infinite loop. This firmware_main() function uses apio to set up a PIO
// program, in both the firmware and emulation builds.
firmware_main();
// Create an epio instance and configure it from the apio state.
// Step the epio instance - cycling every enabled PIO SM exactly one cycle.
// Check the state of the GPIOs
uint64_t gpio_states = epio_read_pin_states(epio);
// ...
struct epio_t epio_t
Opaque epio instance type.
Definition epio.h:37
EPIO_EXPORT epio_t * epio_from_apio(void)
Create an epio instance configured from the current apio state.
EPIO_EXPORT void epio_step_cycles(epio_t *epio, uint32_t cycles)
Advance all enabled state machines by a number of clock cycles.
EPIO_EXPORT uint64_t epio_read_pin_states(epio_t *epio)
Read the current state of all GPIO pins.

Features

  • Cycle-accurate emulation of RP2350 PIO programs.
  • Auto-configureing if used in conjunction with apio.
  • Supports emulating all 12 PIO state machines running simultaneously.
  • Single, multi-step modes, and run until supported conditions are met.
  • Supports internal PIO IRQs.
  • Supports GPIOBASE=0 and 16, and up to 48 GPIOs to support both RP2350A and B.
  • Provides an SRAM API, so tests can simulate reading and writing to the RP2350's SRAM, based on PIO RX/TX FIFOs.
  • WASM build, allowing you to run emulated firmware and visualise PIO programs and GPIO states in the browser.
  • Comprehensive unit testing, with 100% of reachable code branches tested.

Documentation

Start here.

Source Code

See the GitHub repo.

Requirements

In order to use epio for emulation, you can either use apio to set up your PIO programs, or manually configure the epio instance to match the state of your PIOs.

You must stub out any RP2350-specific non-PIO functionality that your program relies on when operating in the emulator, such as direct hardware register access, SDK usage, interrupts, etc. Direct hardware register, SRAM, and other peripheral access will cause faults on the host.

Limitations

There are currently some limitations in epio's PIO emulation. If you need a feature that isn't implemented yet, please raise an issue or submit a PR.

Current limitations:

  • No side step pin support (delays are supported).
  • MOVs to/from the RX FIFO are not supported.
  • Does not suport 2 cycle GPIO input delay via flip-flops to avoid meta-stability.
  • Only supports 4 word FIFOs.
  • Ignores clock divider settings.
  • Limited DMA support - implements a pair of DMA channels doing a read from the address in one PIO SM's TX FIFO, and writing to another SM's RX FIFO.

WASM

epio provides a wasm build, allowing you to run and visualise PIO programs in the browser, with a simple JavaScript API.

Try the live demo.

The example is documented in the example README, and the source code is in the example directory.

See also the JS API for details.

License

MIT License, see [LICENSE](LICENSE).