Connecting Hardware with dutctl
Connect a board to FirmwareCI so that jobs can power it on and off, flash firmware, and read its serial console. FirmwareCI does this through dutctl. Its service, the dutagent, runs on a computer next to the board and receives commands from FirmwareCI over the network.
Prerequisites
- A dutagent that controls the board. See the dutctl documentation for installation and configuration.
- A network route from FirmwareCI to the agent (see Reachability).
- The
fwciCLI and a repository with.firmwareciinitialized (see Repository Setup).
Step-by-Step Setup
1. Collect the Agent Details
FirmwareCI needs three things from the agent:
| What | Example | Used as |
|---|---|---|
| Address with port | lab-pi.local:2024 | Agent attribute |
| Device name | board-1 | Device attribute |
| Command names | power, flash | command in the steps |
The agent’s configuration defines the command names and their arguments. Use the dutctl CLI to list the devices and commands of the agent, and try each command there before you use it in FirmwareCI. A command that works with the CLI works the same way in a FirmwareCI step.
2. Add the DUT to FirmwareCI
fwci init created an example DUT in .firmwareci/duts/dut-<name>/ that uses
reservation-system: mock and controls no hardware. Replace it, or add a new
directory for the board, for example .firmwareci/duts/board-1/dut.yaml:
Workflows find the board by its label: a workflow with runs-on: board runs
on every DUT with label: board. To run jobs on several identical boards, add
one DUT per board with the same label. With reservation-system: dutctl,
FirmwareCI locks the board on the agent while a job runs, so no other job uses
it at the same time.
See DUT Configuration for all fields.
3. Prepare and Clean Up the Board
pre.yaml runs before every test on this DUT, and post.yaml runs after it,
even if the test fails. The examples use the commands power and flash. Use
the names and arguments your agent defines.
.firmwareci/duts/board-1/pre.yaml:
.firmwareci/duts/board-1/post.yaml:
[[attributes.Agent]] and [[attributes.Device]] take their values from
dut.yaml. [[input.Binary]] is the firmware file you pass when you trigger
the job (see Templating and Variables).
To wait until the board has booted, add a serial step to the pre-stage (see Serial Console). See the dutctl step reference for all options.
4. Validate and Push
Then point a workflow at the board with runs-on: board. The example workflow
from fwci init runs on the label of the example DUT. Change its runs-on, or
write a new workflow and test as described in
Writing a Simple Boot Test.
5. Watch a Job
While a job runs, the device list in FirmwareCI shows the device as Busy,
and FirmwareCI holds the lock on the agent as <job-id>@firmwareci.
Using the Board Manually
While a job runs, the board belongs to the job, and manual dutctl commands are refused. To work on the board yourself, disable the device in FirmwareCI. Jobs skip it, and everybody sees why. A manual dutctl lock also keeps jobs away (see Manual Locks).
Common Issues
| Problem | Solution |
|---|---|
fwci validate reports reservation-system is required | Add reservation-system: dutctl to dut.yaml. |
Device is Unavailable with agent unreachable | Start the agent, and make sure FirmwareCI can reach the host and port in Agent. Reaching it from your own machine is not enough. |
| Device is Unavailable, but the agent is running | Set Device to the device name the agent lists. |
| Job stays Queued while the device shows Idle | Release the manual dutctl lock on the device (see Manual Locks). |
See also When the Step Fails.
See Also
- dutctl Step - Parameters, files, locking, and errors
- DUT Configuration - Reservation, device status, and disabling
- Writing a Simple Boot Test - Workflow and test for the board
- dutctl documentation - dutagent setup, configuration, modules, and CLI