|
epio
A cycle-accurate RP2350 PIO emulator
|
While RP2350 PIO programs are conceptually simple and easy to write, testing their precise behaviour is hard:
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.
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.
This video shows what is possible with epio:
https://youtu.be/eNu0JAY1Dvc?si=N3-KCYJ04APH3RlB
Try the interactive demo of the WASM example.
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:
apio.Start here.
See the GitHub repo.
epio follows semantic versioning, with each release tagged in git. While the major version is 0, breaking changes are released in a new minor version, and additions and fixes in a new patch version. See CHANGELOG.md for what changed in each release.
main is not a release branch, and may take breaking changes at any time. Pin your project to a tag:
If your project clones epio from a Makefile, keep the version in a variable, so it is visible and easy to bump:
Checking out a tag leaves the repository with a detached HEAD, which is what you want for a vendored copy - the contents are then frozen at that release. The -c advice.detachedHead=false just suppresses git's advice message about it, to keep the build output readable.
Note that this target will not update an existing checkout - after bumping EPIO_VERSION, remove the epio/ directory so it is re-cloned.
epio v0.2.3 requires apio v0.3.0 or later. epio_from_apio() reads GPIO pull, drive strength and slew rate state that apio did not track before v0.2.0, and epio's tests stage RX FIFO words in a way that apio v0.3.0 changed.
epio's own build clones apio at the version given by APIO_VERSION in the [Makefile](Makefile). If your project already vendors apio, make sure it is pinned to a compatible version too - the two are built from source together, so a mismatch shows up as a compile error in apio.h rather than anything more helpful.
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.
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:
SIDESET_BASE, SIDE_EN and SIDE_PINDIR are ignored.OUT_STICKY or inline OUT enable (INLINE_OUT_EN, OUT_EN_SEL).FJOIN_RX_PUT, FJOIN_RX_GET).FJOIN_RX and FJOIN_TX are ignored).EXEC_STALLED in EXECCTRL isn't reported.WAIT on a pin that is low, is skipped. On real hardware, the state machine waits until the instruction completes.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.
MIT License, see [LICENSE](LICENSE).