Skip to main content

Crate hilt

Crate hilt 

Source
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). hilt reads the ELF’s vector table, sets SP/PC, and hooks a marker symbol to log HIL OK (and a fail symbol / the panic handler to log HIL FAIL). Fail ends the run at once, as does pass for a lone machine with no host bridge. Assert with HilOutput::passed / HilOutput::failed / assert_hil_ok!; console UART text is in HilOutput::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 over vcan and 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 with RenodeRunner::spawn, connect with RunningHil::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 HilOutput passed.

Structs§

ElfInfo
Vector table and marker symbol extracted from a firmware ELF.
GuestBuild
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.
MachineSpec
One emulated machine in a HIL run.
MatrixTestKey
A matrix cell under test and the HID usage it should produce.
MatrixTestPlan
GPIO ↔ matrix ↔ keycode mapping for a board under test.
Platform
A target platform: one emulated machine’s bring-up recipe.
RenodeRunner
Runs firmware in Renode inside a container, generating the platform description(s) and .resc script from a HilConfig.
RunningHil
A HIL run in progress, from RenodeRunner::spawn.
UartBridge
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.
ReplSource
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 aarch64 hosts, where the amd64-only DEFAULT_RENODE_IMAGE would run under qemu-user and never finish LoadPlatformDescription. Built on demand from the upstream linux-arm64 portable release (see crate::RENODE_ARM64_VERSION).
RENODE_ARM64_VERSION
Upstream Renode release the native aarch64 image (RENODE_ARM64_IMAGE) is built from. There is no official arm64 Renode container, so hilt builds one on demand from this release’s linux-arm64 portable (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 MatrixTestPlan from row/col GPIO lists and a flat base layer.
container_runtime_available
Returns true if 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 tries podman then docker.
extract_elf_info
Extracts the vector table (vtor/sp/pc) and the marker, fail_marker, and panic-handler symbol addresses from a firmware ELF. Pure Rust: the .vector_table section and symbol table are read directly.
find_symbol_address
Returns the address of the defined symbol in firmware_elf (thumb bit cleared for functions), or None if the file is unreadable, not a little-endian ELF32, or lacks the symbol.
generate_matrix_test_resc
Generates a .resc for the matrix keycode-verification test.
interface_available
Returns true if the given network interface exists.
parse_key_log
Parses KEY:row,col,mod,kc lines into (row, col, mods, keycode) tuples.
parse_tapdance_log
Parses a TAPDANCE:tap,hold line into (tap, hold).
renode_available
Returns true if 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, then renode on PATH, then /opt/renode/renode (the antmicro/renode image path).
run_renode_container
Runs a prepared Renode container command and a cleanup callback, with the same wall-clock budget RenodeRunner::run derives from a simulated-time timeout_secs (see HilConfig::wall_timeout_secs). Thin convenience over run_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.