In 2019, I joined a team working on open-source firmware sample using two development kits for cellular IoT.
I am responsible for demonstrating to our customers what they need on the cloud side.
This talk is my personal opinion, and does not represent the views of my employer.
Firmware build pipeline for the open-source sample applications is closed source.
Pipeline to run tests is closed source, too.
Test firmware automatically for every change.
because Continuous Delivery solves all your problems
(don’t trust me, read Accelerate)
on GitHub Actions
(so others can see, copy, adapt, improve)
more robust products = more $$$
(and we don’t want to end up on @internetofshit).
Setting up system for building firmware in the SDK is only documented as a manual process.
I’ve created a Docker image that provides all required dependencies.
GitHub Actions support Docker, so I can now build firmware from the SDK automatically!
If you are using this approach you must be aware that you are using software from many untrusted sources with all the consequences that brings.
The SDK is a monorepo with a slow release cycle (months).
Use GitHub Actions to copy subfolder into seperate repository.
Can’t use emulation (e.g. running in QEMU).
A lot of problems during testing are because of connection issues (TLS):
Runs on a GitHub runner, pulls Docker image and compiles the firmware. HEX file is stored as artifact.
Source
docker run --rm -v ${PWD}:/workdir/project nordicplayground/nrfconnect-sdk:main \
/bin/bash -c '\
cd firmware && \
west init -l && \
west update --narrow -o=--depth=1 && \
west build -p always -b ${{ matrix.board }} -- \
-DOVERLAY_CONFIG="overlay-aws.conf;overlay-pgps.conf;overlay-debug.conf;asset-tracker-cloud-firmware-aws.conf;firmware.conf" \
-DEXTRA_CFLAGS="-Werror=format-truncation"\
'
Runner creates a certificate for a device with a unique and random name.
Repository has intermediate CA certificate, which can be used to create device certificates.
Certificate is stored as artifact (so it can be accessed by other jobs later).
On a self-hosted runner, with a development kit attached, the firmware and the certificates are flashed onto the development kit.
There are all kinds of reasons why devices crash, so turning it on and off again is needed (power cycle).
********************************************
The Asset Tracker v2 has started
Version: 67bcbead-original
Client ID: a11d8e1b-9751-4036-9deb-0ed875c1ded2
Cloud: AWS IoT
Endpoint: abcdef12345678-ats.iot.eu-west1.amazonaws.com
********************************************
The test runner waits for the device to connect to the cloud (until it writes to its shadow), then schedules a FOTA.
# Device has connected and reported device information.
<dbg> aws_iot_integration: aws_iot_event_handler: AWS_IOT_EVT_CONNECTED
# FOTA job "db572411-d7da-4c32-8f0c-5684e84c9242" created.
<inf> download_client: Downloading: a11d8e1b.bin [0]
<dbg> ui_module: state_set:
State transition STATE_RUNNING --> STATE_FOTA_UPDATING
<inf> download_client: Downloaded 1024/286472 bytes (0%)
...
<inf> download_client: Downloaded 286472/286472 bytes (100%)
<inf> download_client: Download complete
<dbg> STREAM_FLASH: stream_flash_erase_page: Erasing page at offset 0x000ef000
<inf> dfu_target_mcuboot: MCUBoot image-0 upgrade scheduled.
Reset device to apply
<inf> app_event_manager: MODEM_EVT_SHUTDOWN_READY
<err> util_module: Rebooting!
I: Starting bootloader
I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3
I: Boot source: none
I: Swap type: test
I: Bootloader chainload address offset: 0x10000
I: Jumping to the first image slot
*** Booting Zephyr OS build 186cf4539e5a ***
********************************************
The Asset Tracker v2 has started
Version: 67bcbead-upgraded
Client ID: a11d8e1b-9751-4036-9deb-0ed875c1ded2
Cloud: AWS IoT
Endpoint: abcdef12345678-ats.iot.eu-west1.amazonaws.com
********************************************
Using UART we can immediately react on device output.
<endOn> Termination criteria seen: aws_iot_integration: cloud_wrap_init: Version: 67bcbead-upgraded
Nice, but:
More hassle, than it’s worth.
Store output, but don’t depend on it for testing.
Treat device as black box: observe outcome on cloud side.
We have now ensured, that
Tests are describe in BDD scenarios:
We could test more, but:
Please share your feedback!
m@coderbyheart.com
@coderbyheart
Latest version:
bit.ly/fwtesting
We are hiring!
nordicsemi.com/jobs
Trondheim · Oslo · 20+ more locations