Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/scenario-cloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:

- name: Install xPack OpenOCD
# The SDK flashes through OpenOCD's CMSIS-DAP TCP backend (cmsis_dap_tcp), which is newer
# than OpenOCD 0.12.0 (apt's 0.12.0 lacks it); see selftest-cloud.yml.
# than OpenOCD 0.12.0 (apt's 0.12.0 lacks it).
run: |
V=0.12.0-7
curl -fsSL "https://github.com/xpack-dev-tools/openocd-xpack/releases/download/v$V/xpack-openocd-$V-linux-x64.tar.gz" \
Expand Down
82 changes: 0 additions & 82 deletions .github/workflows/selftest-cloud.yml

This file was deleted.

38 changes: 15 additions & 23 deletions selftest-stm32/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
# STM32 selftest — cloud HIL via GitHub Actions
# STM32 selftest: a minimal hardware-in-the-loop test

`selftest.c` is a tiny STM32F446 firmware that boots, prints a UART banner ending in
`APP_OK`, and exposes a `ping`/`status` console. It's the "hello world" of an EmbeddedCI
hardware-in-the-loop test driven entirely from CI.

## What the workflow does
## Run it over the cloud

[`.github/workflows/selftest-cloud.yml`](../.github/workflows/selftest-cloud.yml) runs on every
change to `selftest.c` (or the workflow itself):
The pod does not have to be on your network: the SDK reaches it **through embeddedci.com**,
flashes the firmware over the cloud, power-cycles the target and asserts the `APP_OK` UART
marker. Use the device name from the **BenchPod** page in the EmbeddedCI web app and an API key
(or a `benchpod login` session):

1. builds `selftest.c` → `build/selftest.elf` (arm-none-eabi + STM32CubeF4),
2. installs the `embeddedci` SDK and runs `pytest selftest-stm32/tests`,
3. the test connects to the device **through embeddedci.com** with the connection
`embeddedci:benchpod-v1.0.0`, flashes the firmware over the cloud, power-cycles the
target, and asserts the `APP_OK` UART marker.

There is **no BenchPod on the GitHub runner** — the physical pod lives wherever it's plugged in
and connects out to embeddedci.com. Auth is the job's **GitHub OIDC token** (`permissions:
id-token: write`); no API key or secret is stored.

## One-time setup
```bash
pip install "embeddedci[pytest]>=2.0,<3"
make CUBE_F4=/path/to/STM32CubeF4
BENCHPOD_API_KEY=eci_... pytest selftest-stm32/tests -v \
--benchpod-connection=embeddedci:<device-name> \
--benchpod-firmware=selftest-stm32/build/selftest.elf
```

1. **Register the device** from the machine wired to the pod:
```bash
benchpod register --connection <pod-ip>
```
then rename it to `benchpod-v1.0.0` on the **BenchPod** page in the EmbeddedCI web app
(names are URL-safe and unique per org).
2. **Trust this repo**: BenchPod → **GitHub Actions** → add `OWNER/REPO` (click *Look up* to fill
the numeric ids) and allow it to drive **benchpod-v1.0.0** (Any device, or this specific one).
To run this from GitHub Actions instead, see [`scenario-sensors-stm32`](../scenario-sensors-stm32)
and its workflow: it authenticates with the job's GitHub OIDC token, so no secret is stored.

## Run it locally (against a pod on your LAN)

Expand Down
13 changes: 5 additions & 8 deletions selftest-stm32/tests/test_selftest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
"""Cloud hardware-in-the-loop self-test for the device registered as ``benchpod-v1.0.0``.
"""Hardware-in-the-loop self-test: flash ``build/selftest.elf`` and check that it boots.

Runs in GitHub Actions (see ``.github/workflows/selftest-cloud.yml``): the workflow builds
``selftest.c`` into ``build/selftest.elf``, then pytest drives the device **through
embeddedci.com** — there is no BenchPod on the runner. The connection
``embeddedci:benchpod-v1.0.0`` authenticates with the workflow's GitHub OIDC token, the
server bridges a tunnel to the physical BenchPod, and we flash + UART-verify the firmware
over the cloud exactly as we would locally.
Pass ``--benchpod-connection`` a LAN address or ``embeddedci:<device-name>`` (through
embeddedci.com, authenticated with an API key or a ``benchpod login`` session); the test
flashes and UART-verifies the firmware the same way over either (see the README).

Wiring (BenchPod logic-analyzer channels → DUT). The pod has no dedicated SWD/UART
pins — it exposes 12 generic LA channels (``pins.pin_1`` .. ``pins.pin_12``) and any
Expand Down Expand Up @@ -109,7 +106,7 @@ def dut(benchpod, wiring):

@pytest.mark.hardware
def test_selftest_boots_over_cloud(dut, wiring, firmware, build_report):
"""Flash selftest.elf to benchpod-v1.0.0 over the cloud and assert it boots cleanly.
"""Flash selftest.elf to the pod's DUT and assert it boots cleanly.

The ``build_report`` fixture is the opt-in that records this run as a GitHub-sourced build on
embeddedci.com (uploading the firmware and capturing pass/fail) — but only inside GitHub Actions
Expand Down
Loading