Warning
This documentation is actively being updated as the project evolves and may not be complete in all areas.
JEP-0010: Renode Integration for Microcontroller Targets¶
Field |
Value |
|---|---|
JEP |
0010 |
Title |
Renode Integration for Microcontroller Targets |
Author(s) |
@vtz (Vinicius Zein) |
Status |
Implemented |
Type |
Standards Track |
Created |
2026-04-06 |
Updated |
2026-04-15 |
Discussion |
Abstract¶
This JEP proposes integrating the Renode emulation
framework into Jumpstarter as a new driver package
(jumpstarter-driver-renode). The driver enables microcontroller-class
virtual targets running bare-metal firmware or RTOS on Cortex-M and
RISC-V MCUs, complementing the existing QEMU driver which targets
Linux-capable SoCs.
Motivation¶
Jumpstarter provides a driver-based framework for interacting with devices under test, both physical hardware and virtual systems. The existing QEMU driver enables Linux-class virtual targets (aarch64, x86_64) using full-system emulation with virtio devices and cloud-init provisioning.
There is growing demand for microcontroller-class virtual targets running bare-metal firmware or RTOS (Zephyr, FreeRTOS, ThreadX) on Cortex-M and RISC-V MCUs. QEMU’s MCU support is limited in peripheral modeling and does not match Renode’s breadth for embedded platforms. Renode by Antmicro is an open-source emulation framework designed specifically for this domain, with extensive peripheral models for STM32, NXP S32K, Nordic, SiFive, and other MCU platforms.
User Stories¶
As a firmware CI pipeline author, I want to run my Zephyr firmware against a virtual STM32 target in Jumpstarter, so that I can validate UART output and basic functionality without physical hardware.
As a SOME/IP stack developer, I want to configure virtual NXP S32K388 and STM32F407 targets through exporter YAML, so that I can test multi-platform firmware builds without modifying driver code.
As a Jumpstarter lab operator, I want to mix physical boards and Renode virtual targets in the same test environment, so that my team can scale testing beyond available hardware.
Reference Targets¶
The initial targets for validation are:
STM32F407 Discovery (Cortex-M4F) – opensomeip FreeRTOS/ThreadX ports, Renode built-in platform
NXP S32K388 (Cortex-M7) – opensomeip Zephyr port, custom platform description
Nucleo H753ZI (Cortex-M7) – openbsw-zephyr, Renode built-in
stm32h743.repl
Constraints¶
The driver must follow Jumpstarter’s established composite driver pattern (as demonstrated by
jumpstarter-driver-qemu)Users must be able to define new Renode targets through configuration alone, without modifying driver code
The solution should minimize external dependencies and runtime requirements
The UART/console interface must be compatible with Jumpstarter’s existing
PySerialandpexpecttoolingThe async framework must be
anyio(the project’s standard)
Proposal¶
The jumpstarter-driver-renode package provides a composite driver
(Renode) that manages a Renode simulation instance with three child
drivers:
RenodePower— controls the Renode process lifecycle (on/off)RenodeFlasher— handles firmware loading (sysbus LoadELF/sysbus LoadBinary)PySerial(console) — serial access over a PTY terminal
Users configure targets entirely through exporter YAML:
export:
Renode:
platform: "platforms/boards/stm32f4_discovery-kit.repl"
uart: "sysbus.usart2"
machine_name: "stm32f4"
extra_commands:
- "sysbus WriteDoubleWord 0x40090030 0x0301"
allow_raw_monitor: false
The driver starts Renode with --disable-xwt --plain --port <N>,
connects to the telnet monitor via anyio.connect_tcp, and
programmatically sets up the platform, UART terminal, and firmware.
A RenodeMonitor async client handles the telnet protocol:
Retry-based connection with
fail_after(timeout)Prompt detection using registered machine names
Per-line error marker detection
Newline injection prevention
Configurable command timeout
API / Protocol Changes¶
No gRPC protocol changes. The driver exposes standard Jumpstarter
interfaces (PowerInterface, FlasherInterface) plus:
get_platform(),get_uart(),get_machine_name()— read-only config accessorsmonitor_cmd(command)— raw monitor access, gated behindallow_raw_monitor: true(default:false)
Hardware Considerations¶
No physical hardware required. Renode is a pure software emulator.
The driver uses PTY terminals for UART, which requires a POSIX
system (Linux or macOS). The Renode process is managed via
subprocess.Popen.
Design Decisions¶
DD-1: Control Interface — Telnet Monitor¶
Alternatives considered:
Telnet monitor — Renode’s built-in TCP monitor interface. Simple socket connection, send text commands, read responses. Lightweight, no extra runtime needed.
pyrenode3 — Python.NET bridge to Renode’s C# internals. More powerful but requires .NET runtime or Mono, heavy dependency, less stable API surface.
Decision: Telnet monitor.
Rationale: It is the lowest-common-denominator interface that works
with any Renode installation. It mirrors the QEMU driver’s pattern
where Popen starts the emulator process and a side-channel protocol
(QMP for QEMU, telnet monitor for Renode) provides programmatic
control. The monitor client uses anyio.connect_tcp with
anyio.fail_after for timeouts, consistent with TcpNetwork and
grpc.py in the project.
DD-2: UART Exposure — PTY Terminal¶
Alternatives considered:
PTY (
emulation CreateUartPtyTerminal) — Creates a pseudo-terminal file on the host. Reuses the existingPySerialchild driver exactly as QEMU does. Linux/macOS only.Socket (
emulation CreateServerSocketTerminal) — Exposes UART as a TCP socket. Cross-platform. Maps toTcpNetworkdriver. Has telnet IAC negotiation bytes to handle.
Decision: PTY as the primary interface.
Rationale: Consistency with the QEMU driver, which uses -serial pty and wires a PySerial child driver to the discovered PTY path.
This reuses the same serial/pexpect/console tooling without any
adaptation. Socket terminal support can be added later as a fallback
for platforms without PTY support.
DD-3: Configuration Model — Managed Mode¶
Alternatives considered:
Managed mode — The driver constructs all Renode monitor commands from YAML config parameters (
platform,uart, firmware path). The driver handles platform loading, UART wiring, and firmware loading programmatically.Script mode — User provides a complete
.rescscript. The driver runs it but still manages UART terminal setup.
Decision: Managed mode as primary, with an extra_commands list
for target-specific customization.
Rationale: Managed mode gives the driver full control over the UART
terminal setup (which must use PTY for Jumpstarter integration, not the
CreateFileBackend or showAnalyzer used in typical .resc scripts).
The extra_commands list covers target-specific needs like register
pokes (e.g., sysbus WriteDoubleWord 0x40090030 0x0301 for S32K388
PL011 UART enablement) and Ethernet switch setup.
DD-4: Firmware Loading — Deferred to Flash¶
Alternatives considered:
flash()stores the firmware path,on()loads it into the simulation and startson()starts the simulation,flash()loads firmware and resets
Decision: Option 1 — flash() stores the path, on() loads and
starts.
Rationale: This matches the QEMU driver’s semantic where you flash
a disk image first, then power on. It also allows re-flashing between
power cycles without restarting the Renode process. The RenodeFlasher
additionally supports hot-loading: if the simulation is already running,
flash() sends the load command and resets the machine.
DD-5: Security — Restricted Monitor Access¶
Alternatives considered:
Open access — Expose
monitor_cmdto all authenticated clientsOpt-in access — Gate behind
allow_raw_monitorconfig flag
Decision: Opt-in with allow_raw_monitor: false by default.
Rationale: The Renode monitor supports commands that interact with
the host filesystem (logFile, include, CreateFileTerminal). In a
shared lab environment, unrestricted monitor access from any
authenticated client poses a risk. The load_command parameter in
flash() is separately validated against an allowlist of known Renode
load commands. Newline characters are rejected in all monitor commands
to prevent command injection.
Design Details¶
Component Architecture¶
Renode (composite driver)
├── RenodePower → manages Popen lifecycle + RenodeMonitor
├── RenodeFlasher → writes firmware, sends LoadELF/LoadBinary
└── PySerial → console over PTY terminal
Monitor Protocol¶
The RenodeMonitor client connects to Renode’s telnet port and
communicates via line-oriented text:
Connection: retry loop with
fail_after(timeout), closing leaked streams on retryPrompt detection: matches
(monitor)or registered machine names only — no false positives from output like(enabled)Error detection: per-line check against markers (
Could not find,Error,Invalid,Failed,Unknown)Timeout:
execute()wraps reads infail_after(30)to prevent indefinite blockingInjection prevention: newline characters rejected in commands;
load_commandvalidated against allowlist
Firmware Auto-Detection¶
When load_command is not specified, the driver reads the first 4
bytes of the firmware file. If they match the ELF magic (\x7fELF),
sysbus LoadELF is used; otherwise sysbus LoadBinary.
Test Plan¶
Unit Tests¶
TestRenodeMonitor— connection retry, command execution, error detection (per-line), disconnect, newline rejection, stream cleanup on retry, prompt matching against expected prompts onlyTestRenodePower— command sequence verification, extra commands ordering, firmware-less boot, idempotent on/off, process termination and cleanupTestRenodeFlasher— firmware path storage, hot-load with reset, custom load command, invalid load command rejection, ELF magic detection, dump not-implementedTestRenodeConfig— default values, children wiring, custom config, PTY path construction, lifecycle
Integration Tests¶
TestRenodeClient— round-trip properties viaserve(), children accessibility,monitor_cmddisabled by default,monitor_cmdnot running error, CLI rendering
E2E Tests¶
test_driver_renode_e2e— full power on/off cycle with real Renode process, skipped when Renode is not installed
CI¶
Renode is installed in the python-tests.yaml workflow:
Linux:
.debpackage from builds.renode.iomacOS:
brew install renode
Backward Compatibility¶
This JEP introduces a new driver package with no changes to existing
packages. There are no breaking changes. The jumpstarter-all
meta-package includes the new driver as an optional dependency.
Consequences¶
Positive¶
Single
jumpstarter-driver-renodepackage supports any Renode target through YAML configuration aloneNo .NET runtime or Mono dependency required
Consistent user experience with the QEMU driver (same composite pattern, same console/pexpect workflow)
extra_commandsprovides an escape hatch for target-specific customization without code changesSecurity-by-default with
allow_raw_monitor: false
Negative¶
PTY-only UART exposure limits to Linux/macOS (acceptable since Renode itself primarily targets these platforms)
The telnet monitor protocol is text-based and less structured than QMP’s JSON — error detection requires string matching
Full
.rescscript support is deferred; users with complex Renode setups must express their configuration as managed-mode parameters plusextra_commands
Risks¶
Renode’s monitor protocol has no formal specification; prompt detection and error handling rely on observed behavior
Renode’s PTY terminal support on macOS may have edge cases not covered in testing
Rejected Alternatives¶
Beyond the alternatives listed in each Design Decision above, the
high-level alternative of not integrating Renode and instead
extending the QEMU driver for MCU targets was considered. QEMU’s MCU
support (e.g., qemu-system-arm -M stm32vldiscovery) is limited in
peripheral modeling and does not match Renode’s breadth for embedded
platforms. The QEMU driver remains the right choice for Linux-capable
SoCs while Renode fills the MCU gap.
Prior Art¶
jumpstarter-driver-qemu — The existing Jumpstarter QEMU driver established the composite driver pattern,
Popen-based process management, and side-channel control protocol (QMP) that this JEP follows.Renode documentation — Renode docs for monitor commands, platform descriptions, and UART terminal types.
opensomeip — github.com/vtz/opensomeip provides the reference Renode targets (STM32F407, S32K388) used for validation.
Future Possibilities¶
Socket terminal fallback for Windows/cross-platform UART access
.rescscript mode for users with complex existing Renode setupsMulti-machine simulation for testing inter-MCU communication
Renode metrics integration for performance profiling
Implementation History¶
2026-04-06: JEP proposed
2026-04-06: Initial implementation proposed (PR #533)
2026-04-11: Address review feedback (DEVNULL, try-except cleanup, async wait, RenodeMonitorError, multi-word CLI, docstrings)
2026-04-15: Security hardening (load_command allowlist, allow_raw_monitor, newline rejection, per-line error detection, prompt matching, execute timeout, stream leak fix)
References¶
This JEP is licensed under the Apache License, Version 2.0, consistent with the Jumpstarter project.