In cloud deployments, CI/CD is taken for granted. In embedded, a lot of testing still happens on a board sitting on someone's desk. Tests pass on your laptop, the board behaves on your bench, and then someone else on the team — or the field — sees a failure that nobody can reproduce.
Hardware-in-the-loop, or HIL, is the answer to that. It's a way to run automated tests against the actual device you ship, on every commit, the same way cloud teams run unit and integration tests in CI.
This article gives you the shape of the problem and the pieces of a working HIL setup. Each section links to a deeper article when you're ready to build that part.
What HIL Actually Is
A HIL rig is a small piece of fixed test infrastructure that sits between your CI pipeline and a real device under test. It controls power to the device, talks to it over a serial console, provisions it with a known firmware image, drives the buses and peripherals around it, and reports results back to CI.
This isn't about replacing the bench. The bench is still where you bring up new hardware and chase the weird stuff. It's about making sure the validation that actually matters is repeatable, reviewable, and runs every time someone pushes a commit.
Mocks and emulators still have a place — they're cheap, fast, and great for catching software bugs early. The bugs that survive those layers tend to be the ones that only show up on real hardware: timing-sensitive boot flows, peripheral quirks, electrical assumptions, and recovery paths that nobody exercises until the field does. For a longer take on why this layer exists, see Why Hardware CI Needs Real Devices.
The Pieces of a HIL Setup
A working HIL rig has a few moving parts. You don't need all of them on day one, but every serious setup grows toward this shape:
- Power control. Cutting and restoring power to the DUT from software, without a human at the bench. This is usually the first problem to solve. More in Power Control Is the First HIL Problem.
- Console access. A serial console for each board, with stable device names so CI knows which DUT is which. More in Console Access for Multi-Board HIL.
- Booting from a known image. Netboot for Linux boards, OpenOCD for MCU targets — the goal is for every test run to start from the same image, with no leftover state. More in Booting Devices from a Known Image in CI.
- Signal routing and peripheral simulation. A small MCU between the management node and the DUT to drive buses with deterministic timing and to stand in for the peripherals the DUT expects to see in the field. More in Signal Routing and Peripheral Simulation in HIL.
- Orchestration and CI integration. Test code that drives all of this from a self-hosted CI runner, plus a sense of when the breadboard prototype starts to outgrow itself. More in Orchestrating HIL Tests in CI.
A Reasonable Order to Build It
If you're starting from scratch, the path that works in practice is:
- Move the DUT off your laptop and onto a small management node, typically a Raspberry Pi.
- Get power control working with a relay board.
- Wire up serial console access through a multi-channel USB UART hub.
- Boot the DUT from a known image on every reset.
- Add a signal-router MCU once you need cycle-accurate buses or simulated peripherals.
- Wire the whole thing into CI through a self-hosted runner.
Each step is useful on its own. By the time you reach the end, you have something that catches real hardware bugs on every push, instead of hoping someone remembered to test the build before tagging a release.