RP2040Sharp 1.0.0

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package RP2040Sharp --version 1.0.0
                    
NuGet\Install-Package RP2040Sharp -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" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RP2040Sharp" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="RP2040Sharp" />
                    
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 --version 1.0.0
                    
#r "nuget: RP2040Sharp, 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@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&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=RP2040Sharp&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.
  • net10.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on RP2040Sharp:

Package Downloads
RP2040Sharp.TestKit

Test utilities and helpers for writing unit tests against RP2040Sharp emulator firmware.

RP2040Sharp.Wireless

A firmware-agnostic emulation of the Infineon CYW43439 Wi-Fi + Bluetooth LE combo chip as wired on the Raspberry Pi Pico W: the gSPI bus (bit-banged through PIO), the SDIO backplane and firmware download, the WHD/SDPCM control + Ethernet data plane, and the BT HCI shared-bus transport. The radio link is virtualized behind the chip's register/protocol boundary, so unmodified firmware (pico-sdk, MicroPython, CircuitPython) runs in STA and SoftAP modes against a virtual access point, and BLE advertises/scans/connects and relays GATT between virtual devices.

RP2040Sharp.NanoFramework.TestKit

Boot a deployed .NET nanoFramework app on the RP2040Sharp emulator: firmware discovery, deployment assembly from .pe metadata, and a native-checksum compatibility guard. Run your real deployed C# on the emulated chip and assert against it from xUnit — managed static and instance fields by name, run-until-managed-method, and a NanoSymbols source generator that emits strongly-typed symbols for your app's methods and static fields.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1-beta.6 70 6/26/2026
1.0.1-beta.5 54 6/25/2026
1.0.1-beta.4 67 6/25/2026
1.0.1-beta.3 51 6/25/2026
1.0.1-beta.2 55 6/25/2026
1.0.1-beta.1 58 6/12/2026
1.0.1-alpha.1 55 6/9/2026
1.0.0 142 6/6/2026
1.0.0-rc.2 65 6/6/2026
1.0.0-rc.1 63 6/6/2026