# vemu - Browser Hardware Emulator
> Boot embedded firmware in the browser. vemu is a WebAssembly hardware emulator for Cortex-M and more - no hardware required.
> Generated: 2026-06-01
---
## Getting Started
URL: https://vemulator.com/docs/getting-started
# Getting Started
vemu runs real firmware in the browser through WebAssembly. Two npm packages get you there:
- `@swedishembedded/vemu` - the emulator runtime (freeware wasm build)
- `@swedishembedded/vemu-react` - React components and hooks for embedding it
## Install
```bash
npm install @swedishembedded/vemu @swedishembedded/vemu-react
```
`@swedishembedded/vemu-react` declares `react >= 18` and `@swedishembedded/vemu` as peer dependencies.
## Initialize the runtime
The wasm module loads lazily. Call `initVemu()` once before constructing an emulator:
```ts
await initVemu();
const boards = JSON.parse(list_boards());
// -> [{ id: "nordic,nrf5340-dk-cpuapp", name: "nRF5340 DK (App core)", arch: "..." }, ...]
```
## Boot a board
Construct an `Emulator` with a board id, firmware bytes, and the image kind
(`"elf"` for ELF binaries, `"bin"` for raw flash images, `"hex"` for Intel HEX
images). An empty byte array builds a firmware-less machine - useful for
inspecting peripherals before loading code.
```ts
const elf = new Uint8Array(await (await fetch("/firmware/zephyr.elf")).arrayBuffer());
const emu = new Emulator("nordic,nrf5340-dk-cpuapp", elf, "elf");
emu.onEvent((events) => {
for (const { kind, payload } of events) {
if (kind === "uart.tx") {
// payload.bytes is a Uint8Array of console output
}
}
});
function frame() {
const running = emu.step_frame();
if (running) requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
```
Console input goes the other way through `dispatch`:
```ts
emu.dispatch("uart.rx", JSON.stringify({ bytes: [...new TextEncoder().encode("help\n")] }));
```
Every event kind the runtime accepts and emits is documented in the
[event vocabulary](/docs/reference/events) and on the per-peripheral pages of the
[runtime reference](/docs/reference) - generated from the exact build you install.
## Use the React components
`@swedishembedded/vemu-react` wraps the loop, the canvas, and an xterm.js
terminal so you don't write any of the above by hand:
```tsx
function EmbeddedVemu() {
const vemu = useVemu();
return (
);
}
```
See the [React API reference](/docs/react) for every component, hook, and prop.
The demo on the front page of this site is built with exactly these
components - what you install is what you see.
## Next steps
- [Build your own peripheral view components](/docs/custom-views)
- [Query peripherals and events at runtime](/docs/runtime-introspection)
- [Browse the runtime reference](/docs/reference)
---
## Custom Views
URL: https://vemulator.com/docs/custom-views
# Custom View Components
The peripheral panel in `@swedishembedded/vemu-react` is a plugin system: every
peripheral view is a React component implementing one interface, looked up from
a registry by peripheral name. The built-in inspectors (KMU, UICR) use the same
mechanism - your views are not second-class.
## The view contract
A view receives everything it needs through
[`PeripheralViewProps`](/docs/react/peripheralviewprops):
```tsx
export function MyTimerView({ name, events, refreshKey, getSnapshot, sendCommand }: PeripheralViewProps) {
// 1. Filter the event stream for kinds your peripheral emits.
const myEvents = events.filter((e) => e.kind.startsWith("nrf.timer."));
// 2. Pull a state snapshot whenever refreshKey bumps.
// The shape is the peripheral's snapshot field map - see its reference page.
const snapshot = getSnapshot();
// 3. Drive the peripheral with its documented commands.
const inject = () => sendCommand({ name: "inject_fault", params: { kind: "bus" } });
return
{JSON.stringify(snapshot, null, 2)}
;
}
```
The pieces:
- `events` - the recent [host event](/docs/reference/events) envelopes
(`{ kind, payload }`); filter by the kinds listed on your peripheral's
[reference page](/docs/reference).
- `refreshKey` - a monotonic counter that bumps when new events arrive or
snapshots change; depend on it in `useEffect` to re-read snapshots.
- `getSnapshot()` - the peripheral's current inspector field map (documented as
"snapshot fields" on its reference page).
- `sendCommand(cmd)` - sends an inspector command; names and params are
documented per peripheral.
## Register the view
Map a peripheral name to your component in the `PERIPHERAL_VIEWS` registry:
```tsx
PERIPHERAL_VIEWS["timer0"] = MyTimerView;
PERIPHERAL_LABELS["timer0"] = "TIMER0";
```
When `peripheral_list()` reports a peripheral named `timer0`, the
`PeripheralPanel` renders your view; unregistered peripherals fall back to the
generic JSON inspector ([`GenericInspector`](/docs/react/genericinspector)).
## Discover what a peripheral supports
You never have to guess kinds, commands, or snapshot shapes:
- **At design time** - every published peripheral has a reference page listing
its accepted/emitted event kinds with payload schemas, commands with params,
and snapshot fields. The same data is machine-readable at
[`/docs/reference.json`](/docs/reference.json).
- **At runtime** - the emulator describes itself; see
[runtime introspection](/docs/runtime-introspection).
The docs and the runtime can't disagree: peripheral metadata is declared in
the emulator source and extracted from the same wasm build this site ships.
---
## Runtime Introspection
URL: https://vemulator.com/docs/runtime-introspection
# Runtime Introspection
A running emulator can tell you what it is made of: which peripherals are
wired, which event kinds each accepts and emits (with payload schemas), which
commands it understands, and what its inspector snapshots look like. This is
the same reflection data these docs are generated from - exposed to your code
and to AI tooling at runtime.
## List and inspect peripherals
```ts
const emu = new Emulator("nordic,nrf5340-dk-cpuapp", new Uint8Array(), "elf");
// Named peripherals with inspectors:
const names = JSON.parse(emu.peripheral_list()); // ["kmu", "uicr", ...]
// Current inspector state (field map; shape per the peripheral's docs):
const snapshot = JSON.parse(emu.peripheral_snapshot("kmu"));
// Drive a documented command:
emu.peripheral_command("kmu", JSON.stringify({
name: "write_slot",
params: { slot: "5", k0: "0xDEADBEEF", k1: "0x1", k2: "0x2", k3: "0x3" },
}));
```
Command params always travel as strings; integer params accept `0x`/`0b`
prefixes. Each peripheral's commands and their parsing are listed on its
[reference page](/docs/reference).
## Describe one machine
`describe()` returns the full reflection document for the constructed machine:
its board identity, every wired peripheral (name, base address, capabilities),
each peripheral's static metadata - accepted inputs and event kinds, emitted
effects and event kinds with payload schemas, commands - plus the builtin
event vocabulary:
```ts
const description = JSON.parse(emu.describe());
for (const p of description.peripherals) {
console.log(p.name, p.metadata?.events_out?.map((e) => e.kind));
}
```
## Describe the whole build
The module-level `describe_runtime()` catalogs **every board compiled into the
wasm build you installed** without constructing them yourself:
```ts
await initVemu();
const runtime: RuntimeDescription = JSON.parse(describe_runtime());
runtime.boards; // every board in this build
runtime.peripherals; // catalog keyed by compatible (e.g. "nordic,nrf-kmu-nvmc")
runtime.global_events; // builtin in/out event vocabulary
```
This is the document the [runtime reference](/docs/reference) pages are built
from at site-build time - and the right entry point for an AI agent that needs
to know what it can and cannot do with a given peripheral before debugging
firmware on it.
Because the metadata is declared inside each peripheral model and extracted
from the compiled runtime, `describe_runtime()` always reflects exactly the
build you are running - never a stale document.
## Machine-readable docs
The curated reference data for this site's build ships next to these pages:
- [`/docs/reference.json`](/docs/reference.json) - boards, peripherals, events, commands
- [`/docs/react-api.json`](/docs/react-api.json) - the vemu-react API surface
Both are stable, versioned artifacts - point your tooling at them.
---
## Event Vocabulary
URL: https://vemulator.com/docs/reference/events
### Outbound events (emulator -> host)
#### `audio.samples`
Interleaved PCM audio samples were produced.
Payload schema:
```json
{
"properties": {
"sample_count": {
"description": "Number of samples in the batch.",
"format": "u64",
"type": "integer"
}
},
"required": [
"sample_count"
],
"type": "object"
}
```
#### `gpio.change`
A GPIO output pin changed level.
Payload schema:
```json
{
"properties": {
"level": {
"description": "New logical level (`true` = high).",
"type": "boolean"
},
"pin": {
"description": "Pin number within the port.",
"format": "u32",
"type": "integer"
},
"port": {
"description": "GPIO port index.",
"format": "u32",
"type": "integer"
}
},
"required": [
"port",
"pin",
"level"
],
"type": "object"
}
```
#### `irq.lower`
An interrupt line was deasserted.
Payload schema:
```json
{
"properties": {
"line": {
"description": "NVIC IRQ number (Cortex-M) or GIC SPI number (Cortex-A).",
"format": "u32",
"type": "integer"
}
},
"required": [
"line"
],
"type": "object"
}
```
#### `irq.raise`
An interrupt line was asserted (pended).
Payload schema:
```json
{
"properties": {
"line": {
"description": "NVIC IRQ number (Cortex-M) or GIC SPI number (Cortex-A).",
"format": "u32",
"type": "integer"
}
},
"required": [
"line"
],
"type": "object"
}
```
#### `uart.tx`
Bytes transmitted by the guest on a UART/serial port.
Payload schema:
```json
{
"properties": {
"bytes": {
"description": "Transmitted bytes.",
"format": "bytes",
"items": {
"format": "u8",
"type": "integer"
},
"type": "array"
},
"port": {
"description": "Logical UART port index (0 = primary console).",
"format": "u32",
"type": "integer"
}
},
"required": [
"port",
"bytes"
],
"type": "object"
}
```
#### `video.frame`
A completed display frame is available; fetch pixels via the framebuffer API.
Payload schema:
```json
{
"properties": {
"height": {
"description": "Frame height in pixels.",
"format": "u32",
"type": "integer"
},
"width": {
"description": "Frame width in pixels.",
"format": "u32",
"type": "integer"
}
},
"required": [
"width",
"height"
],
"type": "object"
}
```
### Inbound events (host -> emulator)
#### `joypad`
Game controller state for console boards.
Payload schema:
```json
{
"properties": {
"bits": {
"description": "Packed button bitmask.",
"format": "u32",
"type": "integer"
}
},
"required": [
"bits"
],
"type": "object"
}
```
#### `uart.rx`
Bytes from the host (terminal keystrokes) delivered to the guest UART RX line.
Payload schema:
```json
{
"properties": {
"bytes": {
"description": "Received bytes.",
"format": "bytes",
"items": {
"format": "u8",
"type": "integer"
},
"type": "array"
}
},
"required": [
"bytes"
],
"type": "object"
}
```
---
## Boards
URL: https://vemulator.com/docs/reference
### VEMU Cortex-M55 + Ethos-U65
URL: https://vemulator.com/docs/reference/boards/arm-vemu-cortex-m55-npu
Architecture: armv8m
ID: arm,vemu-cortex-m55-npu
Peripheral map:
- 0x4000c000 uart0 (arm,pl011)
- 0x4000d000 uart1 (arm,pl011)
- 0x4000e000 uart2 (arm,pl011)
- 0x50004000 npu (arm,ethos-u65)
### nRF5340-DK Application Core
URL: https://vemulator.com/docs/reference/boards/nordic-nrf5340-dk-cpuapp
Architecture: armv8m
ID: nordic,nrf5340-dk-cpuapp
Peripheral map:
- 0x00ff0000 ficr (nordic,nrf-ficr)
- 0x00ff8000 uicr (nordic,nrf-uicr)
- 0x40000000 dcnf (nordic,nrf-dcnf)
- 0x40001000 cache (nordic,nrf-cache)
- 0x40003000 spu (nordic,nrf-spu)
- 0x40004000 oscillators (nordic,nrf-oscillators)
- 0x40005000 clock (nordic,nrf-clock)
- 0x40006000 ctrlap (nordic,nrf-ctrlap)
- 0x40008000 uarte0 (nordic,nrf-uarte)
- 0x40009000 uarte1 (nordic,nrf-uarte)
- 0x4000a000 spim4 (nordic,nrf-spim)
- 0x4000b000 uarte2 (nordic,nrf-uarte)
- 0x4000c000 uarte3 (nordic,nrf-uarte)
- 0x4000d000 gpiote0 (nordic,nrf-gpiote)
- 0x4000e000 saadc (nordic,nrf-saadc)
- 0x4000f000 timer0 (nordic,nrf-timer)
- 0x40010000 timer1 (nordic,nrf-timer)
- 0x40011000 timer2 (nordic,nrf-timer)
- 0x40014000 rtc0 (nordic,nrf-rtc)
- 0x40015000 rtc1 (nordic,nrf-rtc)
- 0x40017000 dppic (nordic,nrf-dppic)
- 0x40018000 wdt0 (nordic,nrf-wdt)
- 0x40019000 wdt1 (nordic,nrf-wdt)
- 0x4001a000 comp (nordic,nrf-comp)
- 0x4001b000 egu0 (nordic,nrf-egu)
- 0x4001c000 egu1 (nordic,nrf-egu)
- 0x4001d000 egu2 (nordic,nrf-egu)
- 0x4001e000 egu3 (nordic,nrf-egu)
- 0x4001f000 egu4 (nordic,nrf-egu)
- 0x40020000 egu5 (nordic,nrf-egu)
- 0x40021000 pwm0 (nordic,nrf-pwm)
- 0x40022000 pwm1 (nordic,nrf-pwm)
- 0x40023000 pwm2 (nordic,nrf-pwm)
- 0x40024000 pwm3 (nordic,nrf-pwm)
- 0x40026000 pdm0 (nordic,nrf-pdm)
- 0x40028000 i2s0 (nordic,nrf-i2s)
- 0x4002a000 ipc (nordic,nrf-ipc)
- 0x4002b000 qspi (nordic,nrf-qspi)
- 0x4002d000 nfct (nordic,nrf-nfct)
- 0x4002f000 gpiote1 (nordic,nrf-gpiote)
- 0x40030000 mutex (nordic,nrf-mutex)
- 0x40033000 qdec0 (nordic,nrf-qdec)
- 0x40034000 qdec1 (nordic,nrf-qdec)
- 0x40036000 usbd (nordic,nrf-usbd)
- 0x40037000 usbreg (nordic,nrf-usbreg)
- 0x40039000 kmu (nordic,nrf-kmu-nvmc)
- 0x40081000 vmc (nordic,nrf-vmc)
- 0x40842500 gpio0 (nordic,nrf-gpio)
- 0x40842800 gpio1 (nordic,nrf-gpio)
- 0x40844000 cryptocell (nordic,nrf-cryptocell)
---
## Peripherals
URL: https://vemulator.com/docs/reference
### Arm Ethos-U65 NPU
URL: https://vemulator.com/docs/reference/peripherals/arm-ethos-u65
ID: arm,ethos-u65
Class: System & Infrastructure / Miscellaneous
Arm Ethos-U65 microNPU. The driver writes the command-stream address/length to `QBASE`/`QSIZE` and sets `CMD`=run; the model fetches the command stream by bus-mastered read-back, decodes and sequences it into a neutral operator, gathers the IFM/weight/scale tensors (further read-backs), runs the op on the injected accelerator backend, writes the OFM back to guest memory, and raises the NPU IRQ with the `NPU_OP_STOP` mask reflected into `STATUS`.
#### Events emitted
- `ethos.npu.inference_complete`: The NPU finished executing a command stream (reached NPU_OP_STOP) and raised its completion IRQ.
#### Events accepted
- `vemu.easydma.read_back_complete`: Bus-internal completion: EasyDMA read-back bytes are available.
#### Snapshot fields
- `status` (u32): STATUS
- `running` (bool): Running
- `qbase` (u64): QBASE (cmd stream addr)
- `qsize` (u32): QSIZE (bytes)
- `qread` (u32): QREAD (progress)
- `op_count` (u32): Decoded compute ops
- `stop_mask` (u32): Last NPU_OP_STOP mask
- `inferences` (u64): Inferences completed
- `errors` (u64): Inference errors
- `irq_line` (u32): IRQ line
- `executor` (str): Compute backend
### ARM PrimeCell PL011 UART
URL: https://vemulator.com/docs/reference/peripherals/arm-pl011
ID: arm,pl011
Class: Connectivity / UART / Serial
Behavioral PL011 UART model (also covers `ti,stellaris-uart`). TX bytes surface as `uart.tx` events; host bytes arrive as `uart.rx` inputs and are buffered in a small RX FIFO popped via `DR` reads. No baud timing - TX is always ready.
#### Commands
- `rx`: Inject receive bytes into the UART RX FIFO from a hex string (e.g. "68656c6c6f" or "68 65 6c"; spaces and a 0x prefix are ignored). The guest then reads the bytes via DR.
#### Snapshot fields
- `DR` (u32): Data Register
- `FR` (u32): Flag Register
- `IBRD` (u32): Integer Baud Rate
- `FBRD` (u32): Fractional Baud Rate
- `LCRH` (u32): Line Control Register
- `CR` (u32): Control Register
### nRF5340 CACHE
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-cache
ID: nordic,nrf-cache
Class: Memory & Storage / Cache
Transparent no-op cache controller: READY always reads 1, TASKS_STARTERASE latches EVENTS_STARTED and EVENTS_DONE in the same write (instant erase), INTEN/INTENSET/INTENCLR gate the IRQ, and ENABLE/PROFILING are stored with no effect on memory access behaviour or timing.
#### Events emitted
- `nrf.cache.erase_done`: Fires immediately after nrf.cache.erase_started: the emulated erase completes in the same write cycle, so EVENTS_DONE is set atomically.
- `nrf.cache.erase_started`: Fires when TASKS_STARTERASE is written and the EVENTS_STARTED latch is set. In emulation the erase is instantaneous so EVENTS_DONE fires in the same write cycle.
#### Snapshot fields
- `state_json` (str): CACHE State (JSON)
- `inten` (u32): INTEN
- `enable` (u32): ENABLE
- `profiling` (u32): PROFILING
- `ev_started` (bool): EVENTS_STARTED
- `ev_done` (bool): EVENTS_DONE
### nRF5340 CLOCK/POWER/RESET
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-clock
ID: nordic,nrf-clock
Class: System & Infrastructure / Clock Control
Combined model of the shared CLOCK, POWER, and RESET block. All clock start/stop tasks and LFRC calibration complete instantly: the matching `STARTED`/`DONE` event latches in the same write cycle (IRQ when enabled). GPREGRET, RESETREAS (W1C), and `NETWORK.FORCEOFF` are stored; DPPI subscribe/publish registers are stored but not acted on.
#### Snapshot fields
- `state_json` (str): CLOCK/POWER/RESET State (JSON)
- `inten` (u32): INTEN (interrupt enable mask)
- `hfclkstat` (u32): HFCLKSTAT
- `lfclkstat` (u32): LFCLKSTAT
- `hfclk192mstat` (u32): HFCLK192MSTAT
- `resetreas` (u32): RESETREAS
- `network_forceoff` (u32): NETWORK.FORCEOFF
### nRF5340 COMP (comparator)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-comp
ID: nordic,nrf-comp
Class: Analog / Comparator
Behavioral COMP model: `TASKS_START` fires `EVENTS_READY` (IRQ when enabled). `TASKS_SAMPLE` captures the comparator output. `TASKS_STOP` halts the comparator. SHORTS (READY_SAMPLE, READY_STOP, DOWN_STOP, UP_STOP, CROSS_STOP) and DPPI SUBSCRIBE/PUBLISH are supported. No real analog signal: RESULT always reads 0 (input below threshold); UP/DOWN/CROSS events never fire.
#### Events emitted
- `nrf.comp.ready`: COMP peripheral is ready and output is valid (EVENTS_READY fired).
- `nrf.comp.sampled`: Comparator value was sampled by TASKS_SAMPLE.
#### Snapshot fields
- `state_json` (str): COMP State (JSON)
- `inten` (u32): INTEN
- `ev_ready` (u32): EVENTS_READY
- `ev_down` (u32): EVENTS_DOWN
- `ev_up` (u32): EVENTS_UP
- `ev_cross` (u32): EVENTS_CROSS
- `enable` (u32): ENABLE
- `running` (bool): Running
- `shorts` (u32): SHORTS
### nRF5340 CRYPTOCELL (ARM CryptoCell-312 wrapper)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-cryptocell
ID: nordic,nrf-cryptocell
Class: Security / Crypto Accelerator
Software-fallback stub for the CC312 hardware crypto engine: the wrapper `ENABLE` register (reset value 0) and the `HOST_RGF` IRR/IMR/ICR registers are modelled, which is enough for PSA/TF-M to detect that CryptoCell is unavailable and fall back to Mbed TLS software crypto. The CC_RNG TRNG block at +0x1000 is modelled functionally (EHR entropy registers fed by a deterministic xorshift64 generator) so secure-world provisioning code that drives the TRNG register protocol directly (e.g. TF-M HUK/IAK generation) completes in VEMU. No other crypto operations are emulated.
#### Events emitted
- `nrf.cryptocell.trng_refresh`: Fires when the TRNG entropy health registers (EHR) are refreshed, either on a TRNG_RESET write or after RNG_SW_RESET.
#### Snapshot fields
- `state_json` (str): CryptoCell State (JSON)
- `cc_enable` (u32): CC ENABLE
- `host_irr` (u32): HOST_RGF IRR (pending IRQs)
- `host_imr` (u32): HOST_RGF IMR (IRQ mask)
- `rng_imr` (u32): RNG IMR (RNG interrupt mask)
- `trng_valid` (u32): TRNG_VALID (entropy ready)
- `sample_cnt` (u32): SAMPLE_CNT (subsampling rate)
### nRF5340 CTRLAP (control access port)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-ctrlap
ID: nordic,nrf-ctrlap
Class: System & Infrastructure / Debug & Trace
Behavioral model of the nRF5340 CTRL-AP peripheral (CPU side, sec 8.10.7). The CPU-to-debugger mailbox is fully modeled: writing TXDATA emits a `nrf.ctrlap.mailbox_tx` event and sets TXSTATUS=DataPending; reading RXDATA auto-clears RXSTATUS. Protection LOCK/DISABLE/STATUS registers are stored and read back. All protection is disabled by default in emulation so the debugger always has full access.
#### Events emitted
- `nrf.ctrlap.approtect_disable`: Firmware wrote a value to APPROTECT.DISABLE or SECUREAPPROTECT.DISABLE, attempting to disable access port protection.
- `nrf.ctrlap.mailbox_tx`: Firmware wrote data to the CTRLAP MAILBOX.TXDATA register, sending a message to the debugger. The payload carries the data value.
#### Snapshot fields
- `state_json` (str): CTRLAP State (JSON)
- `mailbox_rxdata` (u32): MAILBOX.RXDATA
- `mailbox_rxstatus` (u32): MAILBOX.RXSTATUS
- `mailbox_txdata` (u32): MAILBOX.TXDATA
- `mailbox_txstatus` (u32): MAILBOX.TXSTATUS
- `approtect_disable` (u32): APPROTECT.DISABLE
- `secureapprotect_disable` (u32): SECUREAPPROTECT.DISABLE
- `status` (u32): STATUS
### nRF5340 DCNF (domain configuration)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-dcnf
ID: nordic,nrf-dcnf
Class: System & Infrastructure / System Config
Domain configuration block present on both application and network cores of the nRF5340. The read-only `CPUID` register reports the core identity (0 = application, 1 = network) so firmware can identify its own core. On the application core the EXTPERI[0], EXTRAM[0], and EXTCODE[0] PROTECT registers gate AHB multilayer interconnect (AMLI) access by the network core; on the network core those registers are not present and writes to them are silently ignored.
#### Snapshot fields
- `core_id` (u32): Core ID (CPUID)
- `extperi0_protect` (u32): EXTPERI[0].PROTECT
- `extram0_protect` (u32): EXTRAM[0].PROTECT
- `extcode0_protect` (u32): EXTCODE[0].PROTECT
- `state_json` (str): DCNF State Summary (JSON)
### nRF5340 DPPIC (distributed PPI controller)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-dppic
ID: nordic,nrf-dppic
Class: System & Infrastructure / Event Routing
DPPI controller with 32 channels and 6 channel groups. CHEN/CHENSET/CHENCLR writes (and CHG group enable/disable tasks) propagate immediately to the shared `DppiBus` channel-enable mask so publishes within the same tick are routed correctly; the event routing itself happens inside the bus, not via effects.
#### Snapshot fields
- `chen` (u32): CHEN (channel enable)
- `chg0` (u32): CHG[0] (channel group 0)
- `chg1` (u32): CHG[1] (channel group 1)
- `chg2` (u32): CHG[2] (channel group 2)
- `chg3` (u32): CHG[3] (channel group 3)
- `chg4` (u32): CHG[4] (channel group 4)
- `chg5` (u32): CHG[5] (channel group 5)
- `state_json` (str): DPPIC State (JSON)
### nRF5340 EGU (event generator unit)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-egu
ID: nordic,nrf-egu
Class: System & Infrastructure / Event Routing
16-channel software event generator: `TASKS_TRIGGER[n]` (via MMIO or DPPI subscribe) latches `EVENTS_TRIGGERED[n]`, publishes to the DPPI bus when configured, and pulses the IRQ for channels enabled in `INTEN`.
#### Snapshot fields
- `inten` (u32): INTEN (interrupt enable mask)
- `events_triggered` (u32): EVENTS_TRIGGERED bitmask
- `state_json` (str): EGU State Summary (JSON)
### nRF5340/nRF9160 FICR (factory information configuration registers)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-ficr
ID: nordic,nrf-ficr
Class: Memory & Storage / Config / OTP Memory
Read-only factory information block pre-populated with plausible nRF5340 or nRF9160 values (`INFO.PART`, `INFO.DEVICEID`, RAM/flash sizes, code page geometry). Writes are silently ignored; unimplemented fields read as `0xFFFFFFFF`.
#### Snapshot fields
- `configid` (u32): INFO.CONFIGID
- `deviceid0` (u32): INFO.DEVICEID[0]
- `deviceid1` (u32): INFO.DEVICEID[1]
- `part` (u32): INFO.PART
- `variant` (u32): INFO.VARIANT
- `package` (u32): INFO.PACKAGE
- `ram_kb` (u32): INFO.RAM (KiB)
- `flash_kb` (u32): INFO.FLASH (KiB)
- `codepagesize` (u32): INFO.CODEPAGESIZE (bytes)
- `codesize` (u32): INFO.CODESIZE (pages)
- `devicetype` (u32): INFO.DEVICETYPE
- `state_json` (str): FICR Summary (JSON)
### nRF5340 GPIO port
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-gpio
ID: nordic,nrf-gpio
Class: Digital I/O / GPIO
32-pin GPIO port model: `OUT`/`OUTSET`/`OUTCLR`, `DIR` variants, `IN`, `LATCH` (W1C), `DETECTMODE` and per-pin `PIN_CNF` with SENSE-based DETECT. Output-pin changes emit `GpioChange` effects. Input edges driven via `GpioSet`/`GpioClear`/`GpioToggle` inputs update `IN` and `LATCH` and are forwarded to GPIOTE through the wiring-time edge callback.
### nRF5340 GPIOTE (GPIO tasks and events)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-gpiote
ID: nordic,nrf-gpiote
Class: Digital I/O / GPIO
8-channel GPIOTE model. Event-mode channels latch `EVENTS_IN[n]` on matching pin edges reported by the GPIO ports and latch `EVENTS_PORT` when a SENSE-configured pin reaches its active level; task-mode channels drive (`TASKS_SET`/`TASKS_CLR`) or toggle (`TASKS_OUT`) pins on the injected GPIO port instances. Enabled events pulse the IRQ signal.
### nRF5340 I2S (inter-IC sound)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-i2s
ID: nordic,nrf-i2s
Class: Audio / I2S
Functional I2S model with no real audio interface: `TASKS_START` fires `TXPTRUPD`/`RXPTRUPD` immediately (single-buffer completion model, IRQ when enabled). TX data is consumed via EasyDMA and discarded; the RX buffer is filled with silence (zeros). `TASKS_STOP` latches `STOPPED`. DPPI SUBSCRIBE/PUBLISH registers are modelled for `TASKS_START`, `TASKS_STOP` and all four events.
#### Snapshot fields
- `state_json` (str): I2S State (JSON summary)
- `inten` (u32): INTEN (interrupt enable mask)
- `enable` (u32): ENABLE
- `ev_rxptrupd` (u32): EVENTS_RXPTRUPD latch
- `ev_stopped` (u32): EVENTS_STOPPED latch
- `ev_txptrupd` (u32): EVENTS_TXPTRUPD latch
- `ev_framestart` (u32): EVENTS_FRAMESTART latch
- `config_mode` (u32): CONFIG.MODE
- `config_mckfreq` (u32): CONFIG.MCKFREQ
- `config_ratio` (u32): CONFIG.RATIO
- `config_swidth` (u32): CONFIG.SWIDTH
- `config_channels` (u32): CONFIG.CHANNELS
- `rxd_ptr` (u32): RXD.PTR
- `txd_ptr` (u32): TXD.PTR
- `rxtxd_maxcnt` (u32): RXTXD.MAXCNT
### nRF5340 IPC (inter-processor communication)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-ipc
ID: nordic,nrf-ipc
Class: System & Infrastructure / Mailbox / IPC
16-channel IPC mailbox model. `TASKS_SEND[n]` latches `EVENTS_RECEIVE` for every channel enabled in `SEND_CNF[n]` (loopback) and accumulates an outgoing channel mask that the compose orchestrator delivers to the peer core's IPC each quantum. Latched events with their `INTEN` bit set pulse the IRQ signal.
### nRF5340 KMU + NVMC (key management + flash controller)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-kmu-nvmc
ID: nordic,nrf-kmu-nvmc
Class: Security / Key Management
Combined model of the shared 4 KiB KMU/NVMC block. KMU pushes and revokes the 128 UICR-backed key slots (zeroizing on revoke, as per the product specification); NVMC provides the flash write-enable gate, page erase, and ERASEALL.
#### Events emitted
- `nrf.kmu.slot_pushed`: A KMU key slot was pushed to its destination address (`TASKS_PUSH`).
- `nrf.kmu.slot_revoked`: A KMU key slot was revoked: key words zeroized, STATE cleared.
#### Commands
- `push_slot`: Trigger a host-side `TASKS_PUSH` of the selected slot.
- `revoke_slot`: Revoke a slot: clear its STATE permission bit and zeroize the key words.
- `write_slot`: Write the four key words of a slot directly into UICR (host-side provisioning shortcut).
#### Snapshot fields
- `state_json` (str): KMU Slot State (JSON)
- `kmu_info` (str): KMU FSM Info (JSON)
### nRF5340 MUTEX (mutual exclusion)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-mutex
ID: nordic,nrf-mutex
Class: System & Infrastructure / Hardware Semaphore
Hardware spinlock model with 16 `MUTEX[n]` registers implementing atomic test-and-set: a read returning 0 claims the mutex, a read returning 1 means it is already held, and writing 0 releases it, per nRF5340 PS sec 7.19.
#### Commands
- `release`: Forcibly release a held mutex (fault injection). `index` is the mutex number 0-15.
#### Snapshot fields
- `claimed_mask` (u32): Claimed mask (bitmask, bit n = mutex n held)
- `state_json` (str): Mutex State Summary (JSON)
### nRF5340 NFCT (NFC tag interface)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-nfct
ID: nordic,nrf-nfct
Class: Wireless / NFC
Behavioral NFCT model: state-machine tasks latch the matching events and pulse the IRQ when enabled. `TASKS_STARTTX` emits a `nrf.nfct.tx_frame` effect carrying TXD configuration. No real RF field; `FIELDPRESENT`, `NFCTAGSTATE`, and `SLEEPSTATE` always read 0. All config registers (PACKETPTR, MAXLEN, NFC-ID, SENSRES, ...) are plain R/W storage.
#### Events emitted
- `nrf.nfct.tx_frame`: NFCT TASKS_STARTTX was triggered: a TX frame configuration was captured.
#### Snapshot fields
- `inten` (u32): INTEN (interrupt enable mask)
- `shorts` (u32): SHORTS
- `packetptr` (u32): PACKETPTR
- `txd_amount` (u32): TXD.AMOUNT
- `rxd_amount` (u32): RXD.AMOUNT
- `errorstatus` (u32): ERRORSTATUS
- `state_json` (str): NFCT State Summary (JSON)
### nRF5340 OSCILLATORS
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-oscillators
ID: nordic,nrf-oscillators
Class: System & Infrastructure / Clock Control
Nordic nRF5340 OSCILLATORS peripheral (sec 4.12): three retained configuration registers - `XOSC32MCAPS` (HFXO internal capacitor trim), `XOSC32KI.BYPASS` (LFXO external-clock bypass), and `XOSC32KI.INTCAP` (LFXO internal load capacitor selection). No TASKS, EVENTS, or IRQ; all writes are stored as-is.
#### Snapshot fields
- `state_json` (str): OSCILLATORS State (JSON)
- `xosc32mcaps` (u32): XOSC32MCAPS
- `xosc32ki_bypass` (u32): XOSC32KI.BYPASS
- `xosc32ki_intcap` (u32): XOSC32KI.INTCAP
### nRF5340 PDM (pulse density modulation microphone)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-pdm
ID: nordic,nrf-pdm
Class: Audio / Digital Microphone (PDM)
Functional PDM model with no real microphone: `TASKS_START` latches `STARTED`, fills the EasyDMA sample buffer with silence (zeros), and latches `END` immediately; `TASKS_STOP` latches `STOPPED` (IRQ when enabled). Supports DPPI SUBSCRIBE/PUBLISH.
#### Events emitted
- `nrf.pdm.end`: Fires when the PDM EasyDMA has written the last sample to RAM (EVENTS_END latched).
- `nrf.pdm.started`: Fires when the PDM peripheral starts a transfer (EVENTS_STARTED latched).
- `nrf.pdm.stopped`: Fires when the PDM peripheral stops (EVENTS_STOPPED latched).
#### Snapshot fields
- `inten` (u32): INTEN (interrupt enable mask)
- `ev_started` (u32): EVENTS_STARTED latch
- `ev_stopped` (u32): EVENTS_STOPPED latch
- `ev_end` (u32): EVENTS_END latch
- `enable` (u32): ENABLE register
- `sample_ptr` (u32): SAMPLE.PTR (EasyDMA destination)
- `sample_maxcnt` (u32): SAMPLE.MAXCNT (number of samples)
- `state_json` (str): PDM State Summary (JSON)
### nRF5340 PWM (pulse width modulation with EasyDMA)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-pwm
ID: nordic,nrf-pwm
Class: Digital I/O / PWM
Functional PWM model with no electrical output. `TASKS_SEQSTART[n]` consumes the sequence descriptor via an EasyDMA read and latches `SEQSTARTED`, `SEQEND`, `PWMPERIODEND`, and `LOOPSDONE` immediately (single-loop completion, IRQ when enabled); `TASKS_STOP` latches `STOPPED`. DPPI subscribe/publish is supported.
#### Snapshot fields
- `inten` (u32): INTEN (interrupt enable mask)
- `enable` (u32): ENABLE
- `countertop` (u32): COUNTERTOP
- `ev_stopped` (u32): EVENTS_STOPPED latch
- `ev_seqstarted0` (u32): EVENTS_SEQSTARTED[0] latch
- `ev_seqstarted1` (u32): EVENTS_SEQSTARTED[1] latch
- `ev_seqend0` (u32): EVENTS_SEQEND[0] latch
- `ev_seqend1` (u32): EVENTS_SEQEND[1] latch
- `ev_pwmperiodend` (u32): EVENTS_PWMPERIODEND latch
- `ev_loopsdone` (u32): EVENTS_LOOPSDONE latch
- `state_json` (str): PWM State Summary (JSON)
### nRF5340 QDEC (quadrature decoder)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-qdec
ID: nordic,nrf-qdec
Class: Digital I/O / Input
Functional QDEC model with no encoder connected: `TASKS_START` latches `SAMPLERDY` and `REPORTRDY` immediately, `TASKS_STOP` latches `STOPPED` (IRQ when enabled). `ACC`, `SAMPLE`, and the read-clear accumulator registers always read 0 (no movement). DPPI SUBSCRIBE/PUBLISH are fully wired. Two instances: QDEC0, QDEC1.
#### Snapshot fields
- `inten` (u32): INTEN (interrupt enable mask)
- `enable` (u32): ENABLE register
- `running` (bool): Decoder running
- `ev_samplerdy` (u32): EVENTS_SAMPLERDY latch
- `ev_reportrdy` (u32): EVENTS_REPORTRDY latch
- `ev_stopped` (u32): EVENTS_STOPPED latch
- `state_json` (str): QDEC State Summary (JSON)
### nRF5340 QSPI (quad SPI external flash interface)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-qspi
ID: nordic,nrf-qspi
Class: Connectivity / SPI
Behavioral QSPI model with no external flash connected: every task (`ACTIVATE`, `DEACTIVATE`, erase tasks, `READ`, `WRITE`) latches `EVENTS_READY` immediately (IRQ when enabled). `TASKS_READ` fills the destination buffer with `0xFF` (erased flash) via EasyDMA; writes and erases are discarded. Custom events `nrf.qspi.transfer` and `nrf.qspi.erase` are emitted for host-side observation.
#### Events emitted
- `nrf.qspi.erase`: Emitted when a QSPI erase task completes (TASKS_ERASESTART, TASKS_ERASE128, TASKS_ERASE4, or TASKS_ERASE). Carries the flash pointer and the erase length in bytes.
- `nrf.qspi.transfer`: Emitted when a QSPI read or write transfer completes (TASKS_READ or TASKS_WRITE). The `direction` field is `"read"` or `"write"`.
#### Snapshot fields
- `state_json` (str): QSPI State Summary (JSON)
- `inten` (u32): INTEN
- `ev_ready` (u32): EVENTS_READY
- `enable` (u32): ENABLE
- `read_cnt` (u32): READ.CNT
- `write_cnt` (u32): WRITE.CNT
- `erase_ptr` (u32): ERASE.PTR
- `erase_len` (u32): ERASE.LEN
### nRF5340 RTC (real-time counter)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-rtc
ID: nordic,nrf-rtc
Class: Timing / Real-Time Counter
24-bit LFCLK (32.768 kHz) counter with prescaler, four compare channels, TICK/OVRFLW/COMPARE events, and DPPI subscribe/publish. Events latch unconditionally; `EVTEN` gates the DPPI publish path and `INTEN` gates the IRQ pulse, matching the product specification.
#### Snapshot fields
- `state_json` (str): RTC State Summary (JSON)
- `inten` (u32): INTEN (interrupt enable mask)
- `evten` (u32): EVTEN (event routing enable)
- `counter` (u32): COUNTER (current 24-bit value)
- `prescaler` (u32): PRESCALER (12-bit divider)
- `running` (bool): Running (RTC is counting)
- `ev_tick` (u32): EVENTS_TICK latch
- `ev_ovrflw` (u32): EVENTS_OVRFLW latch
- `ev_compare` (u32): EVENTS_COMPARE bitmask (bits 0-3)
### nRF5340 SAADC (successive-approximation ADC with EasyDMA)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-saadc
ID: nordic,nrf-saadc
Class: Analog / ADC
Functional SAADC model with no analog front-end. `TASKS_SAMPLE` fills the EasyDMA result buffer with zero samples (0 V input) and latches `RESULTDONE`, `DONE`, and `END` immediately; `TASKS_START` latches `STARTED` and `TASKS_CALIBRATEOFFSET` completes instantly with `CALIBRATEDONE` (IRQ when enabled). DPPI subscribe/publish is supported. External samples can be injected via `nrf.saadc.inject_sample` Custom inputs.
#### Events emitted
- `nrf.saadc.calibratedone`: SAADC offset calibration completed (EVENTS_CALIBRATEDONE fired).
- `nrf.saadc.done`: One SAADC sampling step completed (EVENTS_DONE fired).
- `nrf.saadc.end`: EasyDMA result buffer is full; all requested samples written (EVENTS_END fired).
- `nrf.saadc.resultdone`: SAADC result data is available in the EasyDMA buffer (EVENTS_RESULTDONE fired).
- `nrf.saadc.started`: SAADC peripheral has started a sampling run (EVENTS_STARTED fired).
- `nrf.saadc.stopped`: SAADC peripheral has stopped (EVENTS_STOPPED fired).
#### Events accepted
- `nrf.saadc.inject_sample`: Inject an ADC sample value for a given channel index. The value will be written by the next TASKS_SAMPLE.
#### Snapshot fields
- `state_json` (str): SAADC State (JSON)
- `inten` (u32): INTEN
- `ev_started` (u32): EVENTS_STARTED
- `ev_end` (u32): EVENTS_END
- `ev_done` (u32): EVENTS_DONE
- `ev_resultdone` (u32): EVENTS_RESULTDONE
- `ev_calibratedone` (u32): EVENTS_CALIBRATEDONE
- `ev_stopped` (u32): EVENTS_STOPPED
- `enable` (u32): ENABLE
- `running` (bool): Running
- `shorts` (u32): SHORTS
- `result_maxcnt` (u32): RESULT.MAXCNT
- `result_amount` (u32): RESULT.AMOUNT
### nRF5340 SPIM (SPI master with EasyDMA)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-spim
ID: nordic,nrf-spim
Class: Connectivity / SPI
Behavioral SPIM model with no real SPI bus: `TASKS_START` fires `STARTED` immediately, queues the TXD/RXD EasyDMA transfers (RX is filled with the `ORC` idle byte), and latches `ENDTX`, `ENDRX`, and `END` in the same write cycle (IRQ when enabled). DPPI subscribe/publish is supported; the `END_START` short does not auto-restart in emulation. A `nrf.spim.transfer` custom event is emitted on every transfer so the host can observe SPI traffic.
#### Events emitted
- `nrf.spim.transfer`: Fires when a SPIM EasyDMA transfer completes (END event). Carries the TX pointer, TX byte count, RX pointer, and RX byte count.
#### Snapshot fields
- `inten` (u32): INTEN (interrupt enable mask)
- `ev_stopped` (u32): EVENTS_STOPPED latch
- `ev_endrx` (u32): EVENTS_ENDRX latch
- `ev_end` (u32): EVENTS_END latch
- `ev_endtx` (u32): EVENTS_ENDTX latch
- `ev_started` (u32): EVENTS_STARTED latch
- `enable` (u32): ENABLE register
- `frequency` (u32): FREQUENCY register
- `config` (u32): CONFIG register (CPHA/CPOL/ORDER)
- `orc` (u32): ORC (over-run character)
- `txd_ptr` (u32): TXD.PTR
- `txd_maxcnt` (u32): TXD.MAXCNT
- `txd_amount` (u32): TXD.AMOUNT
- `rxd_ptr` (u32): RXD.PTR
- `rxd_maxcnt` (u32): RXD.MAXCNT
- `rxd_amount` (u32): RXD.AMOUNT
- `state_json` (str): SPIM State Summary (JSON)
### nRF5340 SPU (system protection unit)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-spu
ID: nordic,nrf-spu
Class: Security / Access Control / TrustZone
Secure/Non-Secure partitioning model: stores `FLASHREGION`, `RAMREGION`, `PERIPHID`, NSC and GPIOPORT permission registers consulted by the bus IDAU/security controller and the NVMC (`FLASHREGION[n].PERM.LOCK` gates write/erase). Access violations injected by the bus latch `EVENTS_RAMACCERR`/`FLASHACCERR`/`PERIPHACCERR` and pulse the IRQ when enabled.
#### Commands
- `inject_event`: Inject an access-error event latch by name for fault-injection testing.
### nRF5340 TIMER
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-timer
ID: nordic,nrf-timer
Class: Timing / Timer
Functional TIMER/counter model: 16 MHz base clock with prescaler, `BITMODE` widths, eight CC channels with capture and compare, `SHORTS` (COMPARE-CLEAR/STOP), `ONESHOTEN`, and DPPI subscribe/publish. COMPARE events latch unconditionally and pulse the IRQ when enabled in `INTEN`.
#### Snapshot fields
- `state_json` (str): TIMER State Summary (JSON)
- `inten` (u32): INTEN (interrupt enable mask)
- `running` (bool): Running (timer is counting)
- `mode` (u32): MODE (0=Timer, 1=Counter, 2=LowPowerCounter)
- `bitmode` (u32): BITMODE (0=16-bit, 1=8-bit, 2=24-bit, 3=32-bit)
- `prescaler` (u32): PRESCALER (0-9; fTIMER = 16 MHz / 2^PRESCALER)
- `counter` (u32): COUNTER (current masked value)
- `shorts` (u32): SHORTS bitmask
- `events_compare` (u32): EVENTS_COMPARE latch bitmask (bit i = channel i latched)
### nRF5340 UARTE (UART with EasyDMA)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-uarte
ID: nordic,nrf-uarte
Class: Connectivity / UART / Serial
UART with EasyDMA model. `TASKS_STARTTX` queues an EasyDMA read of `TXD.PTR`/`TXD.MAXCNT` from guest SRAM (console bytes are routed by the bus); the bus reports completion back, latching `EVENTS_ENDTX`. Received bytes pass through a 4-byte hardware FIFO into the active `RXD` buffer via DMA writes, with ENDRX/RXTO and SHORTS handling and level-sensitive IRQ re-evaluation on every event change.
#### Events accepted
- `vemu.easydma.tx_complete`: Bus-internal completion: an EasyDMA TX transfer finished.
#### Commands
- `rx`: Inject receive bytes into the UARTE RX FIFO from a hex string (e.g. "68656c6c6f" or "68 65 6c"; spaces and a 0x prefix are ignored). The bytes flow through the EasyDMA RX path exactly like real line input, so an attached guest reads them via RXD.
#### Snapshot fields
- `state_json` (str): UARTE State Summary (JSON)
- `inten` (u32): INTEN (interrupt enable mask)
- `enable` (u32): ENABLE (0=disabled, 8=enabled)
- `rx_active` (bool): RX active (EasyDMA RX transfer in progress)
- `errorsrc` (u32): ERRORSRC (error source bitmask)
- `baudrate` (u32): BAUDRATE register value
- `shorts` (u32): SHORTS bitmask
- `rxd_amount` (u32): RXD.AMOUNT (bytes received into current DMA buffer)
- `txd_amount` (u32): TXD.AMOUNT (bytes sent in last DMA transfer)
### nRF5340 UICR (user information configuration registers)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-uicr
ID: nordic,nrf-uicr
Class: Memory & Storage / Config / OTP Memory
Non-volatile UICR flash model backed by a shared (optionally file-backed) byte store. Enforces the real NVMC WEN write-enable gate: stores with `NVMC.CONFIG != WEN` are dropped. Survives reset like silicon; only an NVMC ERASEALL clears it.
#### Events emitted
- `nrf.uicr.write_dropped`: A UICR store was silently dropped because NVMC was not in WEN (write-enable) mode - mirrors real nRF5340 flash-controller behaviour.
- `nrf.uicr.written`: A UICR write was committed to the non-volatile store (e.g. BL2 ROTPK provisioning into the OTP/CUSTOMER region).
#### Commands
- `load_image`: Overwrite the UICR region with a raw image supplied as a hex string (host-side provisioning shortcut, e.g. the web UI 'Load UICR' button). Shorter images leave the tail unchanged.
#### Snapshot fields
- `approtect` (u32): APPROTECT
- `secureapprotect` (u32): SECUREAPPROTECT
- `state_json` (str): UICR Region Summary (JSON)
### nRF5340 USBD (USB 2.0 full-speed device controller)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-usbd
ID: nordic,nrf-usbd
Class: Connectivity / USB
Behavioral USBD stub: writing ENABLE latches EVENTS_USBRESET (no VBUS - disconnected-bus semantics). All endpoint EasyDMA registers, EPINEN/EPOUTEN, EPSTALL, EPDATASTATUS, HALTED, and SETUP data registers are modelled as plain R/W storage. INTEN/INTENSET/INTENCLR gate IRQ assertion on every latched event.
#### Snapshot fields
- `state_json` (str): USBD State (JSON summary)
- `inten` (u32): INTEN (interrupt enable mask)
- `enable` (u32): ENABLE register
- `ev_usbreset` (u32): EVENTS_USBRESET latch
- `ev_started` (u32): EVENTS_STARTED latch
- `ev_ep0datadone` (u32): EVENTS_EP0DATADONE latch
- `ev_epdata` (u32): EVENTS_EPDATA latch
- `ev_sof` (u32): EVENTS_SOF latch
- `ev_usbevent` (u32): EVENTS_USBEVENT latch
- `epinen` (u32): EPINEN (endpoint IN enable bitmask)
- `epouten` (u32): EPOUTEN (endpoint OUT enable bitmask)
- `epstatus` (u32): EPSTATUS
- `epdatastatus` (u32): EPDATASTATUS
- `eventcause` (u32): EVENTCAUSE
- `shorts` (u32): SHORTS bitmask
- `usbaddr` (u32): USBADDR (assigned USB address)
### nRF5340 USBREG
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-usbreg
ID: nordic,nrf-usbreg
Class: Connectivity / USB
Nordic Semiconductor USBREG peripheral (nRF5340). Models VBUS detection events (USBDETECTED, USBREMOVED) and USB regulator ready event (USBPWRRDY). USBREGSTATUS reflects the current VBUS and regulator state. Events latch unconditionally; INTEN gates the IRQ assertion only. No real VBUS modeled at reset: all events are 0 and USBREGSTATUS reads 0 (no VBUS, output not ready).
#### Snapshot fields
- `inten` (u32): INTEN (interrupt enable mask)
- `usbregstatus` (u32): USBREGSTATUS (VBUSDETECT | OUTPUTRDY)
- `ev_detected` (u32): EVENTS_USBDETECTED latch
- `ev_removed` (u32): EVENTS_USBREMOVED latch
- `ev_pwrrdy` (u32): EVENTS_USBPWRRDY latch
- `state_json` (str): USBREG State Summary (JSON)
### nRF5340 VMC (volatile memory controller)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-vmc
ID: nordic,nrf-vmc
Class: Memory & Storage / RAM Control
RAM block power control model. `RAMBLOCK[n].POWER` registers (with POWERSET/POWERCLR set/clear semantics) are stored and read back, but RAM is always powered and retained in emulation - the programmed values have no behavioural effect on guest SRAM access.
#### Snapshot fields
- `power0` (u32): RAMBLOCK[0].POWER
- `power1` (u32): RAMBLOCK[1].POWER
- `power2` (u32): RAMBLOCK[2].POWER
- `power3` (u32): RAMBLOCK[3].POWER
- `state_json` (str): VMC State Summary (JSON)
### nRF5340 WDT (watchdog timer)
URL: https://vemulator.com/docs/reference/peripherals/nordic-nrf-wdt
ID: nordic,nrf-wdt
Class: Timing / Watchdog
Behavioral watchdog model: LFCLK-driven down-counter with `CRV` reload value, eight `RR[n]` reload slots gated by `RREN`, `CONFIG.STOPEN`-guarded stop requiring `TSEN` unlock, DPPI SUBSCRIBE/PUBLISH support, and INTEN/NMIEN gating. On timeout `EVENTS_TIMEOUT` latches and the IRQ/NMI signal is pulsed; on deliberate stop `EVENTS_STOPPED` latches. No system reset is performed by the model itself.
#### Snapshot fields
- `state_json` (str): WDT State Summary (JSON)
- `inten` (u32): INTEN (interrupt enable mask)
- `nmien` (u32): NMIEN (NMI enable mask)
- `running` (bool): Running (WDT is counting)
- `crv` (u32): CRV (counter reload value)
- `rren` (u32): RREN (reload register enable bitmask)
- `config` (u32): CONFIG (SLEEP/HALT/STOPEN)
- `reqstatus` (u32): REQSTATUS (pending reload requests)
- `ev_timeout` (u32): EVENTS_TIMEOUT latch
- `ev_stopped` (u32): EVENTS_STOPPED latch
---
## React API
URL: https://vemulator.com/docs/react
Package: @swedishembedded/vemu-react v0.8.0
### GenericInspector
URL: https://vemulator.com/docs/react/genericinspector
Kind: component
Default inspector view used for any peripheral that has no domain-specific
view registered in `PERIPHERAL_VIEWS`. Renders the raw snapshot field map,
pretty-printing any JSON-string fields. This is what makes "implement the
inspector, see it in the UI" work before a custom view exists.
Accepts the uniform PeripheralViewProps shape, so it can stand in
for any registered view.
Signature:
```tsx
function GenericInspector(props: PeripheralViewProps): JSX.Element
```
Props:
- `name` `string`: Peripheral name as reported by the machine (e.g. "kmu", "uicr").
- `events` `PeripheralEvent[]`: All peripheral events seen so far; the view filters for the ones it cares about.
- `refreshKey` `number`: Monotonic counter that increments whenever new events arrive.
- `getSnapshot` `() => PeripheralSnapshot | null`: Pull the current snapshot for this peripheral (null if unavailable).
- `sendCommand` `(cmd: { name: string; params: Record }) => void`: Send a command to this peripheral's inspector.
- `sendUartRx` (optional) `(target: string, bytes: number[], timing?: TimingSpec) => void`: Deliver UART RX bytes to this peripheral, optionally at a precise virtual
time (`timing`). Absent `timing` is immediate. Undefined on hosts/boards
without timed-delivery support (feature-detect before use).
- `clockHz` (optional) `number`: Guest clock in Hz (cycles/sec), or 0 when unknown. For timing conversions.
Examples:
```tsx
getPeripheralSnapshot("uicr")}
sendCommand={(cmd) => sendPeripheralCommand("uicr", cmd)}
/>
```
### PERIPHERAL_LABELS
URL: https://vemulator.com/docs/react/peripheral-labels
Kind: constant
Optional human-friendly labels for the selector. Unknown peripherals fall
back to an upper-cased name.
Signature:
```tsx
const PERIPHERAL_LABELS: Record
```
### PERIPHERAL_VIEWS
URL: https://vemulator.com/docs/react/peripheral-views
Kind: constant
Registry mapping a peripheral name (as reported by the machine) to a
domain-specific inspector view. A peripheral without an entry here still
appears in the list and is rendered with the generic fallback view.
To add a richer view for a peripheral: write a component that accepts
`PeripheralViewProps`, then add one line here.
Signature:
```tsx
const PERIPHERAL_VIEWS: Record>
```
### peripheralLabel
URL: https://vemulator.com/docs/react/peripherallabel
Kind: function
Display label for a peripheral name: registered label or upper-cased name.
Signature:
```tsx
function peripheralLabel(name: string): string
```
Returns: `string`
### PeripheralPanel
URL: https://vemulator.com/docs/react/peripheralpanel
Kind: component
Generic peripheral inspector panel. A permanent section (like Display and
Console): it always renders, lists whatever inspectable peripherals the live
machine exposes, and shows a domain-specific view when registered, otherwise
the generic fallback. Empty/error states keep it visible and diagnosable.
Signature:
```tsx
function PeripheralPanel(props: PeripheralPanelProps): JSX.Element
```
Props:
- `peripherals` `string[]`: Names of inspectable peripherals reported by the running machine.
- `events` `PeripheralEvent[]`: All peripheral events seen so far (passed through to the selected view).
- `error` (optional) `string | null`: Build/exposure error to surface (instead of a silent empty panel).
- `refreshKey` `number`: Monotonic counter that bumps when new events arrive.
- `getSnapshot` `(name: string) => PeripheralSnapshot | null`: Pull the current snapshot for a peripheral by name (null if unavailable).
- `sendCommand` `(name: string, cmd: { name: string; params: Record }) => void`: Send a command to a peripheral's inspector.
- `sendUartRx` (optional) `(target: string, bytes: number[], timing?: import("./timing").TimingSpec) => void`: Deliver UART RX bytes to a named UART, optionally at a precise virtual time.
- `clockHz` (optional) `number`: Guest clock in Hz (cycles/sec); 0 when unknown.
Examples:
```tsx
const { peripheralList, peripheralEvents, peripheralError,
snapshotVersion, getPeripheralSnapshot, sendPeripheralCommand } = useVemu();
```
### PeripheralSelector
URL: https://vemulator.com/docs/react/peripheralselector
Kind: component
Vertical list of inspectable peripherals (the left pane of
PeripheralPanel). Renders human-friendly labels via
`peripheralLabel` and highlights the current selection.
Signature:
```tsx
function PeripheralSelector(props: PeripheralSelectorProps): JSX.Element
```
Props:
- `peripherals` `string[]`: Names of the peripherals to list, in display order.
- `selected` `string | null`: Currently selected peripheral name, or null when nothing is selected.
- `onSelect` `(name: string) => void`: Called with the peripheral name when the user clicks an entry.
Examples:
```tsx
const [selected, setSelected] = useState(null);
```
### PeripheralViewProps
URL: https://vemulator.com/docs/react/peripheralviewprops
Kind: interface
Uniform props every peripheral inspector view receives.
Domain-specific views (KMU, UICR) and the generic fallback all implement
this interface, so adding a new view is: write a component matching these
props + register it in peripheralViews.tsx.
Signature:
```tsx
interface PeripheralViewProps
```
Fields:
- `name` `string`: Peripheral name as reported by the machine (e.g. "kmu", "uicr").
- `events` `PeripheralEvent[]`: All peripheral events seen so far; the view filters for the ones it cares about.
- `refreshKey` `number`: Monotonic counter that increments whenever new events arrive.
- `getSnapshot` `() => PeripheralSnapshot | null`: Pull the current snapshot for this peripheral (null if unavailable).
- `sendCommand` `(cmd: { name: string; params: Record }) => void`: Send a command to this peripheral's inspector.
- `sendUartRx` `(target: string, bytes: number[], timing?: TimingSpec) => void`: Deliver UART RX bytes to this peripheral, optionally at a precise virtual
time (`timing`). Absent `timing` is immediate. Undefined on hosts/boards
without timed-delivery support (feature-detect before use).
- `clockHz` `number`: Guest clock in Hz (cycles/sec), or 0 when unknown. For timing conversions.
### useVemu
URL: https://vemulator.com/docs/react/usevemu
Kind: hook
Core VEMU hook. Manages wasm init, board selection, firmware loading,
the RAF render loop, UART I/O, and peripheral inspector state.
Signature:
```tsx
function useVemu(options?: { loadModule?: () => Promise }): UseVemuResult
```
Returns: `UseVemuResult`
Examples:
```tsx
function Emu() {
const { boards, selectedBoard, setSelectedBoard, loadProgram,
hasVideo, setDraw, setUartSink, sendUart } = useVemu();
return (
<>
>
);
}
```
### UseVemuResult
URL: https://vemulator.com/docs/react/usevemuresult
Kind: interface
Everything useVemu returns: emulator status, board selection,
program/run controls, video + UART wiring callbacks, and the peripheral
inspector surface.
Signature:
```tsx
interface UseVemuResult
```
Fields:
- `status` `VemuStatus`: Current emulator lifecycle state.
- `boards` `BoardInfo[]`: Boards compiled into the loaded runtime.
- `selectedBoard` `string`: Id of the currently selected board (empty string until boards are listed).
- `setSelectedBoard` `Dispatch>`: Select a board by id; instantiates a fresh (non-running) machine for it.
- `selectedHasDisplay` `boolean`: Static display capability of the selected board (false when unknown).
- `hasVideo` `boolean`: True once the running machine has produced at least one video frame.
- `ips` `string`: Human-readable simulated clock speed (e.g. "4.2 MHz"); empty while not running.
- `loadProgram` `(data: Uint8Array, kind: ProgramKind, boardOverride?: string) => void`: Load a program (ROM/ELF/binary) and start running, optionally switching board first.
- `loadLinux` `(kernel: Uint8Array, initrd: Uint8Array, boardOverride?: string) => void`: Boot a Linux kernel + initramfs (arm64) and start running, optionally
switching board first. Uses the wasm `newLinux` factory: the board
builder generates the DTB and bootargs, so only the raw kernel `Image`
and `initrd` bytes are passed. UART wiring is identical to loadProgram.
- `loadRiscvLinux` `( firmware: Uint8Array, image: Uint8Array, initrd: Uint8Array, boardOverride?: string, ) => void`: Build + start a RISC-V Linux machine from OpenSBI firmware + kernel Image
+ initramfs (the `vemu_riscv64_virt` board), optionally switching board.
- `loadUicr` `(data: Uint8Array) => boolean`: Load a raw UICR image (uicr.bin) into the running machine's UICR region.
Returns false when no machine is built or the board has no UICR.
Not persisted - re-apply after loading a new program image.
- `loadWithFiles` `( files: Array<{ id: string; bytes: Uint8Array; addr?: number; kind?: ProgramKind }>, boardOverride?: string, cmdline?:...`: Build + start a machine from a board-declared set of file slots (the
generic path behind every board's loader UI). Each entry pairs a slot id
with its bytes plus an optional load-address override and program `kind`.
Supersedes loadProgram/loadLinux/loadRiscvLinux for the slot-based UI.
- `stop` `() => void`: Pause the run loop (status returns to "ready").
- `reset` `() => void`: Reset the machine and restart with the last loaded program.
- `eraseAll` `() => void`: Discard the current machine and rebuild the selected board with empty flash.
- `setDraw` `(cb: (f: VemuFrame) => void) => void`: Register the callback that renders video frames (wired up by `VemuCanvas`).
- `setUartSink` `(cb: (b: Uint8Array) => void) => void`: Register the sink for UART output bytes (wired up by `VemuTerminal`).
- `setTerminalClear` `(cb: () => void) => void`: Register a callback that clears the terminal UI (wired up by `VemuTerminal`);
invoked on `reset()` / `eraseAll()` so a reboot starts from a clean screen.
- `sendUart` `(bytes: Uint8Array) => void`: Send UART input bytes to the running machine.
- `peripheralList` `string[]`: Names of inspectable peripherals exposed by the current machine.
- `peripheralEvents` `PeripheralEvent[]`: Rolling buffer (last 100) of peripheral events emitted by the machine.
- `peripheralError` `string | null`: Build/exposure error to surface in the peripheral panel, or null.
- `snapshotVersion` `number`: Monotonic counter that bumps when inspector snapshots should be re-pulled.
- `getPeripheralSnapshot` `(name: string) => PeripheralSnapshot | null`: Pull the current snapshot for a peripheral by name (null if unavailable).
- `sendPeripheralCommand` `(name: string, cmd: { name: string; params: Record }) => void`: Send a command to a peripheral's inspector.
- `sendUartRx` `(target: string, bytes: number[], timing?: TimingSpec) => void`: Deliver UART RX bytes to a named UART, optionally at a precise virtual time
(deterministic timed delivery). Absent `timing` is immediate.
- `clockHz` `number`: Guest clock in Hz (cycles/sec), or 0 when unknown.
### VemuCanvas
URL: https://vemulator.com/docs/react/vemucanvas
Kind: component
Pixel-perfect display surface for the emulator's video output. Registers a
draw callback that blits each RGBA frame into a 2D canvas, resizing the
backing store whenever the frame dimensions change, and shows a "NO SIGNAL"
overlay until the first frame arrives.
Signature:
```tsx
function VemuCanvas(props: VemuCanvasProps): JSX.Element
```
Props:
- `hasVideo` `boolean`: True once the machine has produced a video frame; gates the "NO SIGNAL" overlay.
- `setDraw` `(cb: (f: VemuFrame) => void) => void`: Registers the frame-draw callback with the hook (`useVemu().setDraw`).
Examples:
```tsx
const { hasVideo, setDraw } = useVemu();
```
### VemuLoader
URL: https://vemulator.com/docs/react/vemuloader
Kind: interface
Optional override for testing / stub mode. Returned by the `loadModule`
factory passed to useVemu to replace the default wasm loading.
Signature:
```tsx
interface VemuLoader
```
Fields:
- `EmulatorClass` `VemuModuleStatic`: Constructor used to build emulator instances (the wasm `Emulator` class or a stub).
- `listBoards` `() => string`: Returns the available boards as a JSON-encoded `BoardInfo[]` string.
### VemuTerminal
URL: https://vemulator.com/docs/react/vemuterminal
Kind: component
xterm.js console bound to the emulator's UART. Machine output is written to
the terminal; keystrokes are passed through raw (picocom-style) as UART
input. Auto-fits to its container and re-fits on resize.
Signature:
```tsx
function VemuTerminal(props: VemuTerminalProps): JSX.Element
```
Props:
- `setUartSink` `(cb: (b: Uint8Array) => void) => void`: Registers the UART output sink with the hook (`useVemu().setUartSink`).
- `sendUart` `(bytes: Uint8Array) => void`: Sends keystrokes to the machine as UART input bytes (`useVemu().sendUart`).
- `setTerminalClear` (optional) `(cb: () => void) => void`: Registers a terminal-clear callback with the hook
(`useVemu().setTerminalClear`); invoked on machine reset / erase.
Examples:
```tsx
const { setUartSink, sendUart } = useVemu();
```
### VemuTitleBar
URL: https://vemulator.com/docs/react/vemutitlebar
Kind: function
Branded title bar for the VEMU emulator window. Renders the `vemu.` wordmark
as a link back to https://vemulator.com - every embedding carries attribution.
Signature:
```tsx
function VemuTitleBar(): import("react").JSX.Element
```
Returns: `import("react").JSX.Element`
Examples:
```tsx
```