Expand description
hilt — hardware-in-the-loop test fixtures for embedded Rust.
Runs compiled firmware inside a Renode simulation in a Podman/Docker container, captures its output, and lets host tests assert on it. It supports three firmware-verification styles, and mixes them freely:
- Self-reporting firmware — a generic Cortex-M board (
CpuInit::VectorTable).hiltreads the ELF’s vector table, setsSP/PC, and hooks a marker symbol to logHIL OK(and a fail symbol / the panic handler to logHIL FAIL). Fail ends the run at once, as does pass for a lone machine with no host bridge. Assert withHilOutput::passed/HilOutput::failed/assert_hil_ok!; console UART text is inHilOutput::uart. Great for one firmware image per test. - Live CAN interaction — board-described platforms (
CpuInit::Board) wired into a CAN hub, with any machine optionally bridged to a host SocketCAN interface (MachineSpec::with_socketcan_bridge). Host code then exchanges frames with the firmware overvcanand asserts on protocol behavior. Multiple machines are supported; Linux hosts only. - Live UART interaction — any machine’s UART exposed to the host as a
raw TCP socket (
MachineSpec::with_uart_bridge). Start the run withRenodeRunner::spawn, connect withRunningHil::connect_uart, and exchange bytes with the firmware’s serial line; works on macOS/Windows hosts too.
§Quick start (single self-reporting firmware)
use hilt::{HilConfig, Platform, RenodeRunner, assert_hil_ok};
let output = RenodeRunner::new(HilConfig::single(
Platform::rp2040(),
"target/thumbv6m-none-eabi/release/examples/hil_keyboard",
))
.run();
assert_hil_ok!(output);§Quick start (multi-machine CAN with a host bridge)
use hilt::{HilConfig, MachineSpec, Platform, RenodeRunner};
let machines = vec![
MachineSpec::new("controller", "controller.elf", Platform::stm32h7())
.with_socketcan_bridge(),
MachineSpec::new("sensor", "sensor.elf", Platform::stm32h7()),
];
// hilt::setup_vcan("vcan0"); // once, with privileges
let run = RenodeRunner::new(HilConfig::multi(machines)).spawn();
// ... open vcan0 and exercise the firmware ...
let output = run.wait();External requirements: podman or docker (or a native renode). The
firmware ELF’s vector table and symbols are read in pure Rust.
Macros§
- assert_
hil_ ok - Asserts that a
HilOutputpassed.
Structs§
- ElfInfo
- Vector table and marker symbol extracted from a firmware ELF.
- Guest
Build - Builds a cross-compiled guest firmware binary on demand.
- HilConfig
- Configuration for a HIL run: one or more machines plus run-wide settings.
- HilOutput
- Result of a HIL run: captured stdout/stderr and the container exit code.
- Machine
Spec - One emulated machine in a HIL run.
- Matrix
Test Key - A matrix cell under test and the HID usage it should produce.
- Matrix
Test Plan - GPIO ↔ matrix ↔ keycode mapping for a board under test.
- Platform
- A target platform: one emulated machine’s bring-up recipe.
- Renode
Runner - Runs firmware in Renode inside a container, generating the platform
description(s) and
.rescscript from aHilConfig. - Running
Hil - A HIL run in progress, from
RenodeRunner::spawn. - Uart
Bridge - Bridges an emulated UART to a host TCP socket.
Enums§
- Artifact
- Which cargo artifact a guest build produces.
- CpuInit
- How to initialize the CPU after
LoadELF. - Repl
Source - Where a Renode platform description (
.repl) comes from.
Constants§
- DEFAULT_
FAIL_ MARKER - Default marker symbol hooked to emit
HIL FAIL. - DEFAULT_
MARKER - Default marker symbol hooked to emit
HIL OK. - DEFAULT_
RENODE_ IMAGE - Default Renode container image on x86-64 hosts (Antmicro’s official, amd64-only image).
- DEFAULT_
SOCKETCAN_ IFACE - Default host SocketCAN interface name.
- HIL_
FAIL_ MARKER - Failure marker logged when firmware reaches the fail symbol
(
HilConfig::fail_marker) or its panic handler. - HIL_
OK_ MARKER - Success marker firmware logs (via a CPU hook or semihosting print).
- RENODE_
ARM64_ IMAGE - Locally-built native Renode image used on
aarch64hosts, where the amd64-onlyDEFAULT_RENODE_IMAGEwould run underqemu-userand never finishLoadPlatformDescription. Built on demand from the upstreamlinux-arm64portable release (seecrate::RENODE_ARM64_VERSION). - RENODE_
ARM64_ VERSION - Upstream Renode release the native
aarch64image (RENODE_ARM64_IMAGE) is built from. There is no official arm64 Renode container, sohiltbuilds one on demand from this release’slinux-arm64portable (self-contained .NET) tarball. - RENODE_
IMAGE_ ENV - Env var overriding the auto-selected Renode image.
- RUNTIME_
ENV - Env var that overrides container-runtime auto-detection.
Functions§
- build_
test_ plan - Builds a
MatrixTestPlanfrom row/col GPIO lists and a flat base layer. - container_
runtime_ available - Returns
trueif a container runtime is available (non-panicking). - default_
renode_ image - The Renode container image to use by default on this host.
- detect_
container_ runtime - Detects the container runtime. Honors
HILT_CONTAINER_RUNTIME, else triespodmanthendocker. - extract_
elf_ info - Extracts the vector table (
vtor/sp/pc) and themarker,fail_marker, and panic-handler symbol addresses from a firmware ELF. Pure Rust: the.vector_tablesection and symbol table are read directly. - find_
symbol_ address - Returns the address of the defined
symbolinfirmware_elf(thumb bit cleared for functions), orNoneif the file is unreadable, not a little-endian ELF32, or lacks the symbol. - generate_
matrix_ test_ resc - Generates a
.rescfor the matrix keycode-verification test. - interface_
available - Returns
trueif the given network interface exists. - parse_
key_ log - Parses
KEY:row,col,mod,kclines into(row, col, mods, keycode)tuples. - parse_
tapdance_ log - Parses a
TAPDANCE:tap,holdline into(tap, hold). - renode_
available - Returns
trueif a native Renode binary is available (for non-container use, e.g. running inside a Renode-based image). - renode_
bin - Resolves a native Renode binary, in order:
HILT_RENODE_BIN, thenrenodeonPATH, then/opt/renode/renode(theantmicro/renodeimage path). - run_
renode_ container - Runs a prepared Renode container command and a cleanup callback, with the
same wall-clock budget
RenodeRunner::runderives from a simulated-timetimeout_secs(seeHilConfig::wall_timeout_secs). Thin convenience overrun_with_timeout_and_cleanup. - run_
with_ timeout_ and_ cleanup - Runs a command with a hard wall-clock timeout and a cleanup callback.
- setup_
vcan - Creates (or recreates) a virtual CAN interface with CAN-FD MTU.