Run STM32 firmware in CI, and get the same answer every time.
zensim boots the firmware you flash on the board, on models of the silicon, under virtual time. A script drives the console and judges the run — so a test that passes once passes always, on any host.
$ curl -fsSL https://zensimlabs.com/install.sh | shmacOS arm64 today. Elsewhere, a Rust toolchain builds it.
What it does
Deterministic to the picosecond
Time is virtual and every external input is timestamped. A run that passes once passes always, however fast or busy the host is — which is what makes a simulator worth putting in CI.
Your firmware, unmodified
The same ELF you flash on the board. The console, the LEDs, the timers and the DMA are the real register interfaces, so the firmware cannot tell the difference until it reads something nobody modelled.
Peripheral models, not stubs
USART with its FIFO, timers to the advanced ones, RCC with a clock tree per family, flash with its programming sequences, ADC, SPI, I²C, CAN, SDMMC, QSPI, USB, Ethernet. What is missing says so and is counted.
Scripted, and honest about it
Wait for text on a UART, type into it, read memory, set a breakpoint, drive a pin, assert. Scenarios run in parallel with a timeout each and write JUnit, so a failure names the expectation it broke.
Boards from your devicetree
Point the importer at the flattened devicetree your firmware build leaves behind and it writes the platform file: memory map, peripherals, NVIC lines, bus clocks, DMA requests, console, LEDs, buttons.
One binary
No emulator, no JIT, no toolchain at run time, no container. A Cortex-M interpreter in Rust, the models beside it, and a Starlark reader for the platforms and the scenarios.
A scenario
Platforms and scenarios are Starlark files. Load an ELF, wait for what the firmware prints, assert on it. Run one with zensim run, or a directory of them in parallel with zensim test.
Install
$ curl -fsSL https://zensimlabs.com/install.sh | shIt reads the latest release, checks its SHA-256, and installs the binary and the platform library. It clones nothing and compiles nothing. ZENSIM_VERSION, ZENSIM_INSTALL_DIR and ZENSIM_NO_MODIFY_PATH change what it does.
What it is not, yet
- —A profile's clocks are fixed at the frequency the generator chose; the clock tree answers its registers but the models do not follow a change.
- —TrustZone has its registers and filters no access.
- —Some scenarios need a firmware built from a workspace of your own, and skip cleanly without it.
- —Only STM32 is published. Other vendors exist and do not ship.