Back to resources
HIL
Testing

Power Sequencing and Brown-out Testing

Controlled power is the foundation of HIL. The BenchPod gates the target through protected eFuses, schedules power-on pod-side, monitors current per rail, and can sag the supply on purpose to test brown-out handling.

Edward Viaene · June 18, 2026 · 3 min read

The first thing any hardware test needs is control over power — a hard, trustworthy way to put the target into a known-off state and bring it back. The BenchPod treats power as a first-class, scriptable part of every test, not an afterthought.

Power that's protected, not just switched

The target's supply is gated through electronic eFuses rather than a relay or a USB hub. That matters for two reasons: a misbehaving DUT — a dead short on a fresh prototype, say — trips the fuse instead of taking down the bench, and the pod monitors current and voltage per rail, so power isn't a blind on/off but a measurement.

From a test, power is two calls — and the rail is something you can read back:

from embeddedci.benchpod import INTERNAL

def test_powered(benchpod):                              # `benchpod` is the connected-pod fixture
    benchpod.power_on(INTERNAL)                          # 5V internal eFuse
    assert not benchpod.target_status().efuse(INTERNAL).fault   # tripped on a short?
    print(benchpod.power_status().rail(INTERNAL).current, "A")  # per-rail monitor: volts + amps
    # ... run the test ...
    benchpod.power_off(INTERNAL)

The benchpod_target fixture wraps that lifecycle for you — target on for the test, off at teardown, even if the test fails — so you never leave a board powered on after a crash.

Scheduled power-on

Power-cycling cleanly is its own small problem: you want the board to come up while something is watching its output. The pod can schedule the power-on on its own timer and return immediately, so your test arranges the listener first and the board boots into it:

from embeddedci.benchpod import INTERNAL

def test_boot_banner(benchpod, pins):
    benchpod.power_off(INTERNAL)
    benchpod.power_on(INTERNAL, delay=1.5)   # fires 1.5s from now, pod-side
    # LA channels are generic (pins.pin_1..pin_12) — here this bench's UART is on LA5/LA4:
    with benchpod.open_uart(rx=pins.pin_5, tx=pins.pin_4) as uart:
        assert uart.read_until(r"APP_OK", timeout=12)

The pod won't open the UART until the LA bank voltage is chosen, so set the board's I/O voltage once in conftest.py (see the pytest docs).

That's the same trick behind catching boot regressions — the scheduled power-on lands the boot banner inside an already-listening window.

A clean reset every run

A surprising number of "flaky" hardware failures are really state leaking between runs — a peripheral left configured, a latch still set, RAM that wasn't actually cleared. A real power-down through the eFuse gives every test the same starting point: cold silicon. Combined with flashing a known image, each run starts from the same place instead of inheriting the last one's mess. When a power cycle is more than you need, benchpod.reset_target() pulses the target's reset line (DUT header J1 pin 22, rev3 pods) without dropping its supply.

Brown-out and fault testing

The interesting failures aren't at a clean 5 V — they're at the edges, where firmware's power assumptions get tested for real:

  • Brown-out — sag the rail below the brown-out threshold and confirm the firmware resets cleanly or holds in a safe state, instead of executing on a marginal supply and corrupting flash or NVM.
  • Drop-out and recovery — cut power mid-operation and check the device recovers to a sane state on the next boot, not a half-written one.
  • Inrush and sequencing — watch the current the board draws as it powers up, and catch a regression that suddenly pulls far more than it used to.

Pair the eFuse control with the pod's analog DAC and you can drive a sensor input while the supply dips — reproducing the messy, simultaneous conditions a device meets in the field, on every commit. Power control is the foundation everything else in a HIL test is built on; the pytest framework docs have the full eFuse and pin reference.