RP2040Sharp.TestKit 1.0.0

dotnet add package RP2040Sharp.TestKit --version 1.0.0
                    
NuGet\Install-Package RP2040Sharp.TestKit -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RP2040Sharp.TestKit" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RP2040Sharp.TestKit" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="RP2040Sharp.TestKit" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RP2040Sharp.TestKit --version 1.0.0
                    
#r "nuget: RP2040Sharp.TestKit, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RP2040Sharp.TestKit@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RP2040Sharp.TestKit&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=RP2040Sharp.TestKit&version=1.0.0
                    
Install as a Cake Tool

RP2040Sharp

Build Status License .NET Version

RP2040Sharp is a high-performance emulator for the Raspberry Pi RP2040 microcontroller, written entirely in modern C# (.NET 10). It runs real RP2040 firmware — including MicroPython — without modification.

This project is a port and re-imagination of the excellent rp2040js project by Uri Shaked. The goal is to bring embedded emulation to the .NET ecosystem with a strong focus on speed and type safety, leveraging the latest runtime features.

Performance

Measured on Apple Silicon (macOS, .NET 10, Release build):

Workload Throughput
Tight arithmetic loop (Flash, steady-state) ~460 MIPS
MicroPython boot ~250 MIPS
MicroPython REPL execution ~250 MIPS

The emulator boots MicroPython v1.21.0 and reaches the interactive REPL in approximately 3–4 seconds of simulated time (wall time varies by host). On iOS/MAUI (Mono AOT, no JIT), throughput is lower but the proportional optimizations still apply.

Features

  • ARM Cortex-M0+ full instruction set (Thumb-1), including exceptions and NVIC
  • Real RP2040 BootROM (B1) — loaded as an embedded resource; rom_table_lookup, memcpy44, memset4 and bit-manipulation helpers run natively
  • Flash erase/program via C# native hooks — MicroPython's LittleFS filesystem works correctly
  • MicroPython boots to interactive REPL over emulated USB-CDC
  • Dual-core: Core 1 launches via the SIO FIFO multicore handshake (RP2040 §2.8.3); both cores advance in lock-step
  • GDB stub: debug Core 0 with arm-none-eabi-gdb over target remote :3333 (registers, memory, stepi, breakpoints)
  • Peripherals: GPIO, SIO, UART0/1, SPI0/1, I2C0/1 (master + slave simulation), ADC, PWM, PIO0/1, DMA, Timer, Watchdog, RTC, USB (CDC-ACM host for the MicroPython REPL), Clocks, PSM, Resets, and more
  • Per-pin GPIO API (SetGpioExternalIn, GetGpioOutputEnable, GetGpioOut) for embedding in circuit simulators
  • TestKit fluent API for writing firmware integration tests

Getting Started

git clone https://github.com/PyMCU/RP2040Sharp.git
cd RP2040Sharp
dotnet restore
dotnet build

Run the demo (downloads MicroPython, boots it, executes REPL snippets, reports MIPS):

dotnet run --project src/RP2040Sharp.Demo -c Release

Run the tests:

dotnet test

Basic Usage

using RP2040.Peripherals;

var machine = new RP2040Machine();
machine.LoadFlash(File.ReadAllBytes("firmware.bin"));

// Capture UART output
machine.Uart0.OnByteTransmit += b => Console.Write((char)b);

// Run 125 000 cycles (1 ms at 125 MHz)
machine.Run(125_000);

TestKit

using RP2040.TestKit;

var sim = RP2040TestSimulation.Create()
    .WithBinary(File.ReadAllBytes("firmware.bin"))
    .AddUart(0, out var uart);

sim.RunMilliseconds(100);
Assert.Contains("Hello", uart.Text);

Validating firmware in CI

Built for using the emulator as a compiler/firmware testkit (e.g. for PyMCU) without flaky or hanging builds. A run is always bounded — wedged firmware fails the test with a reason instead of stalling the job — and the instruction count is deterministic and reproducible across machines.

var sim = RP2040TestSimulation.Create()
    .WithBinary(File.ReadAllBytes("firmware.bin"))
    .AddUart(0, out var uart);

// Never hangs: returns PredicateMet / LockedUp / BudgetReached.
var result = sim.RunUntilHalt(() => uart.Text.Contains("PASS"), maxInstructions: 5_000_000);

result.Succeeded.Should().BeTrue();
sim.Cpu.Should().NotHaveFaulted();
sim.Cpu.Should().HaveExecutedAtMost(2_000_000);   // compiler-size regression guard

Or headless from a pipeline, with the rp2040sharp runner CLI (exit 0 found · 1 not found · 2 crashed):

dotnet run --project src/RP2040Sharp.Runner -c Release -- \
    firmware.uf2 --expect-text "PASS" --channel uart

GPIO integration (circuit simulators)

// Inject an external signal on GP5
machine.Sio.SetGpioExternalIn(5, high: true);

// Read firmware output state
bool isHigh = machine.Sio.GetGpioOut(3);
bool isOutput = machine.Sio.GetGpioOutputEnable(3);

Debugging with GDB

Run the demo with --gdb to expose Core 0 over the GDB Remote Serial Protocol:

dotnet run --project src/RP2040Sharp.Demo -c Release -- --gdb
# in another terminal:
arm-none-eabi-gdb -ex "target remote :3333"

Or embed the server in your own host:

using RP2040.Gdb;

var server = new GdbTcpServer(myGdbTarget, port: 3333); // myGdbTarget : IGdbTarget
server.Start();

Solution Structure

Project Description
src/RP2040Sharp Core library — CPU, bus, peripherals, machine
src/RP2040.TestKit Fluent test harness for firmware integration tests
src/RP2040Sharp.Runner Headless rp2040sharp CLI: run firmware, --expect-text, CI exit codes
src/RP2040Sharp.Demo Demo: boots MicroPython and drives the REPL

Architecture Notes

  • Instruction decoder: 65 536-entry flat table of delegate* function pointers — O(1) dispatch with no branch on opcode
  • Bus reads: explicit SRAM → Flash → BootROM fast paths with direct pointer arithmetic; no table indirection
  • Native hook guard: registered hooks are bounded by _nativeHookMax; Flash-region instructions skip the dictionary lookup entirely via a single uint comparison
  • Fetch cache: region and base pointer cached in Run() locals; region changes (rare) flush the cache

Roadmap

Core / CPU

  • Full Thumb-1 instruction set
  • Exceptions, NVIC, SysTick, PendSV
  • Native hooks (BootROM ROM API, flash erase/program)
  • WFI / WFE sleep with correct peripheral wakeup
  • Dual-core (Core 1 launch, SIO FIFO)
  • GDB stub for step-debugging firmware

Peripherals

  • GPIO, SIO (spinlocks, interpolator)
  • UART0 / UART1
  • SPI0 / SPI1
  • I2C0 / I2C1 (master + slave-mode simulation)
  • ADC
  • PWM (all 8 slices)
  • PIO0 / PIO1 (state machines, GPIO integration)
  • DMA (all channels, DREQ sources)
  • USB (CDC-ACM host driver for the MicroPython REPL)
  • Timer / Alarms, Watchdog, RTC
  • Clocks, Resets
  • [~] XOSC, ROSC, PLL, PSM, VREG — register stubs (report stable/locked; no frequency model)
  • Flash programming via SSI (XIP hardware path)

Ecosystem

  • UF2 parser in demo
  • Real RP2040 B1 BootROM (embedded resource)
  • MicroPython v1.21.0 boots to REPL
  • Per-pin GPIO API for circuit simulator embedding
  • iCircuit element (RP2040Elm) — in design
  • NativeAOT targets (Windows, Linux, macOS, iOS)
  • WebAssembly (WASM) target

Contributing

  1. Fork the repository.
  2. Create a feature branch (git checkout -b feature/my-feature).
  3. Ensure all tests pass (dotnet test).
  4. Commit following Conventional Commits.
  5. Open a Pull Request against master.

License

MIT License — see LICENSE.

Based on the original work from rp2040js © 2021 Uri Shaked.
C# Port © 2026 Iván Montiel Cardona.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 0 6/6/2026
1.0.0-rc.2 41 6/6/2026
1.0.0-rc.1 37 6/6/2026