14.1.1.3. Simulators#
Twee TARGET-waarden bouwen de firmware om binnen een simulator op je host te draaien, zonder dat er hardware is aangesloten. Ze bestaan zodat de firmware overal gedraaid en getest kan worden.
| Core | NPU | Simulator |
|---|---|---|---|
| Cortex-M7 | None | QEMU |
| Cortex-M55 | Ethos-U55 (256 MACs) | Arm FVP – Corstone SSE-300 |
MPS2_AN500 is het basis-Cortex-M7-target zonder NPU. Het draait onder QEMU, dat snel start en de lichtgewicht manier is om de platformonafhankelijke code en de testsuite uit te oefenen.
MPS3_AN547 is een Cortex-M55 met de Ethos-U55 NPU, gedraaid op Arm’s Fast Models – de FVP, die het Corstone SSE-300-referentiesubsysteem modelleert. Dit is het target om de NPU en het ML-modelpad in simulatie uit te oefenen.
Beide bieden het ROM-bestandssysteem en ruim voldoende RAM (en de NPU op de M55), dus vision- en ML-scripts draaien ongewijzigd.
Er is geen echte sensor, maar de csi-module werkt nog steeds tegen een virtuele – csi.CSI.snapshot() geeft een synthetisch, geanimeerd testpatroon terug (een scrollend schaakbordpatroon in grijswaarden, een gradiënt in RGB565), geen live scène. Om echte beeldinhoud te verwerken, laad je die in plaats daarvan uit een bestand: een image.Image uit een fixture in het ROM-bestandssysteem, of een image.ImageIO-stream voor opgenomen frames.
14.1.1.3.1. Bouwen en draaien#
Elke simulator is een host-tool die je zelf installeert. Je bouwt een target zoals elk ander (zie De firmware bouwen) en draait het dan met run onder de bijbehorende simulator – run bouwt de ROMFS-image, start de firmware op en laat die draaien met een seriële verbinding waaraan je je kunt koppelen.
14.1.1.3.1.1. MPS2_AN500 (QEMU)#
QEMU zit in de meeste pakketbeheerders als de Arm-systeememulator:
Linux (Debian / Ubuntu) – installeer het met
apt:sudo apt install qemu-system-armmacOS – installeer het met Homebrew:
brew install qemu
Bouw en draai vervolgens het target:
make -j$(nproc) TARGET=MPS2_AN500
make TARGET=MPS2_AN500 run
14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#
De FVP is Arm’s Fixed Virtual Platform voor de Corstone SSE-300, geleverd als onderdeel van Arm Virtual Hardware. Het is alleen beschikbaar voor Linux – gebruik op een Mac in plaats daarvan het QEMU-target hierboven.
Download de bundel, pak hem uit en zet zijn bin/-map op je PATH:
wget https://artifacts.tools.arm.com/avh/11.31.28/avh-linux-x86_11.31_28_Linux64.tar.gz
mkdir -p ~/fvp
tar --strip-components=1 -xzf avh-linux-x86_11.31_28_Linux64.tar.gz -C ~/fvp
export PATH="$HOME/fvp/bin:$PATH"
De FVP heeft ook de Python-bibliotheken van de SDK op LD_LIBRARY_PATH nodig wanneer hij draait. Exporteer het één keer per shell vanuit de root van de repo – het lezen van SDK_VERSION houdt het correct naarmate de repo de vastgepinde SDK bijwerkt:
export LD_LIBRARY_PATH="$HOME/openmv-sdk-$(cat SDK_VERSION)/python/lib:$LD_LIBRARY_PATH"
Bouw en draai vervolgens het target:
make -j$(nproc) TARGET=MPS3_AN547
make TARGET=MPS3_AN547 run
14.1.1.3.2. De testsuite draaien#
De unittests staan in scripts/unittest/tests/, met hun fixture-images en -data in scripts/unittest/data/. Ze worden gedraaid met mpremote, dat scripts/unittest/ aankoppelt op de draaiende simulator en zijn run.py uitvoert.
De simulatorverbinding is traag met de standaard mpremote, dus gebruik de in de repo meegeleverde kopie met de seriële patch toegepast (pas hem één keer toe):
patch -N -p1 -d lib/micropython < tools/mpremote-qemu-serial.patch
Start voor MPS2_AN500 onder QEMU het target – het print de pseudo-terminal waarop zijn seriële poort zit (bijvoorbeeld /dev/pts/5):
make TARGET=MPS2_AN500 run
Richt vervolgens vanuit een andere shell de gepatchte mpremote op dat apparaat:
python3 lib/micropython/tools/mpremote/mpremote.py connect /dev/pts/5 \
mount scripts/unittest/ run scripts/unittest/run.py
Voor MPS3_AN547 onder de FVP is de seriële poort in plaats daarvan een telnet-socket op poort 5555:
make TARGET=MPS3_AN547 run
python3 lib/micropython/tools/mpremote/mpremote.py connect socket://localhost:5555 \
mount scripts/unittest/ run scripts/unittest/run.py
run.py ontdekt en voert elke test uit en print per test een PASSED / FAILED-regel met timing en een samenvatting aan het eind.
14.1.1.3.3. Een test toevoegen#
Tests worden automatisch ontdekt. Om er een toe te voegen, plaats je een bestand in scripts/unittest/tests/ dat een unittest(data_path, temp_path)-functie definieert die True teruggeeft wanneer de test slaagt en False wanneer hij faalt:
# scripts/unittest/tests/circles.py
def unittest(data_path, temp_path):
import image
img = image.Image(data_path + "/shapes.ppm", copy_to_fb=True)
circles = img.find_circles(threshold=5000, x_margin=30, y_margin=30, r_margin=30)
return len(circles) == 1 and circles[0][0:] == (118, 56, 22, 5856)
De argumenten data_path en temp_path wijzen naar de twee bestandssystemen die de simulator ziet terwijl de suite draait:
Path | Backed by |
|---|---|
| De |
| Het alleen-lezen ROM-bestandssysteem van het board, ingebouwd in de firmware-image vanuit |
Een nieuwe test heeft dus geen herbouw nodig, maar een nieuwe fixture wel: de ROM-image is gekoppeld aan romfs_config.json in plaats van aan de individuele databestanden, dus forceer de herbouw door de romfs_config.json van het board te touchen (of make TARGET=<TARGET> clean) en opnieuw te draaien.
Verwachte waarden worden inline in de test geassert, dus er is geen apart bestand met verwachte uitvoer om te onderhouden. Om een test tijdens runtime over te slaan – bijvoorbeeld wanneer die hardware nodig heeft die de simulator niet modelleert – gooi je een uitzondering waarvan de boodschap "SKIPPED" bevat.