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.gui→self.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
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
origin/masterdebug_trace/hilimports guarded byhil_test_mode, no impact on normal or simulator buildsSimController.load()exactly: PIN → PIN confirm → menu option 1 → mnemonic → wait for USB → run testsFiles Changed
New files (6)
src/hil.pysrc/debug_trace.pymanifests/disco-hil.pytest/hil/__init__.pytest/hil/controller.pyHardwareController— mirrorsSimControllerinterfacetest/hil/run_integration.pyModified files (8)
src/platform.pyhil_test_modeflag +usb_connected()bypasssrc/main.pynetwork="regtest"override, boot loggingsrc/specter.pyinit_apps()bugfix, keystore ref wiringsrc/hosts/usb.pylog_exception, no USB disable in HILsrc/gui/tcp_gui.pyTEST_STATUS/TEST_SCREEN/TEST_RESETcontrol commandstest/integration/util/controller.pysim.gui→self.guibugfixtest/integration/util/rpc.pyr["error"]→r.get("error")(upstream bug fix)Makefilehardwareintheloopandhardwareintheloop-testtargetsTest Results (2026-03-19)
Hardware (STM32F469, no-bootloader mode, bitcoind v29.3):
Pre-existing failures (NOT caused by HIL changes):
test_miniscript— uses{0,1}multi-path descriptors, not supported by upstream firmwaretest_weird_wsh— hangs, likely same descriptor issueKnown limitations:
OSError: 4(EINTR) — pre-existing upstream issue (upstream f469-disco: simulator crashes with OSError 4 (EINTR) in asyncio poller #12)init_apps()after unlock) — handled by retry logicBuild & Test
Manual Debug Commands (over debug UART /dev/ttyACM0 at 9600 baud)
Related Issues
rpc.pyKeyError on batch responses