Skip to content

HIL: Hardware-in-the-Loop testing for integration tests on real STM32F469 #13

@Amperstrand

Description

@Amperstrand

Goal

Enable the existing 16 integration tests (test_basic.py + test_with_rpc.py) to run on real STM32F469 Discovery hardware via serial UART, mirroring the unix simulator flow exactly.

Approach

  • Minimal invasive changes — only 8 modified files + 6 new files from origin/master
  • Zero SeedKeeper code — keystore-agnostic, tests internal flash keystore only
  • Conditional imports — all debug_trace/hil imports guarded by hil_test_mode, no impact on normal or simulator builds
  • Mirrors SimController.load() exactly: PIN → PIN confirm → menu option 1 → mnemonic → wait for USB → run tests

Files Changed

New files (6)

File Purpose
src/hil.py HIL command handler — 8 commands over debug UART
src/debug_trace.py Serial debug logging (ST-Link UART only)
manifests/disco-hil.py Build manifest (HIL variant)
test/hil/__init__.py Package init
test/hil/controller.py HardwareController — mirrors SimController interface
test/hil/run_integration.py HIL test runner (discovers bitcoind via env vars)

Modified files (8)

File Change
src/platform.py hil_test_mode flag + usb_connected() bypass
src/main.py Dupterm guard, network="regtest" override, boot logging
src/specter.py HIL listener, USB auto-enable, init_apps() bugfix, keystore ref wiring
src/hosts/usb.py HIL auto-enable, log_exception, no USB disable in HIL
src/gui/tcp_gui.py TEST_STATUS/TEST_SCREEN/TEST_RESET control commands
test/integration/util/controller.py SIGSEGV detection + sim.guiself.gui bugfix
test/integration/util/rpc.py r["error"]r.get("error") (upstream bug fix)
Makefile hardwareintheloop and hardwareintheloop-test targets

Test Results (2026-03-19)

Hardware (STM32F469, no-bootloader mode, bitcoind v29.3):

  • 3/3 basic tests: PASS
  • 12/13 RPC tests: PASS (2 pre-existing failures below)
  • 15/16 total: PASS

Pre-existing failures (NOT caused by HIL changes):

  • test_miniscript — uses {0,1} multi-path descriptors, not supported by upstream firmware
  • test_weird_wsh — hangs, likely same descriptor issue

Known limitations:

Build & Test

# Build
source /etc/profile.d/arm-toolchain.sh
make hardwareintheloop

# Flash (no-bootloader mode)
st-flash --connect-under-reset erase
st-flash --connect-under-reset write bin/specter-diy-hil.bin 0x08000000

# Start bitcoind
bitcoind -regtest -daemon -fallbackfee=0.0001 \
  -rpcuser=specter -rpcpassword=specter -rpcport=18443 \
  -rpcallowip=127.0.0.1 -listen=0

# Run tests
source .venv/bin/activate
BTC_RPC_USER=specter BTC_RPC_PASSWORD=specter BTC_RPC_PORT=18443 \
  python3 test/hil/run_integration.py

Manual Debug Commands (over debug UART /dev/ttyACM0 at 9600 baud)

TEST_STATUS     → OK:READY
TEST_SCREEN     → OK:SCREEN:<class>:<id>[:<title>]
TEST_KEYSTORE   → OK:KEYSTORE:<name>
TEST_FINGERPRINT → OK:FINGERPRINT:<hex>
TEST_MNEMONIC   → OK:MNEMONIC:<words>
TEST_UI:<json>  → OK:UI (inject value into current screen)
TEST_WIPE       → OK:WIPED (wipe storage + reset)
TEST_RESET      → OK:RESET (soft reset)

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    hilHardware-in-the-loop testing

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions