14.1.1.3. Simulatoren#
Zwei TARGET-Werte bauen die Firmware so, dass sie innerhalb eines Simulators auf deinem Host läuft, ohne angeschlossene Hardware. Sie existieren, damit die Firmware überall ausgeführt und getestet werden kann.
| Kern | NPU | Simulator |
|---|---|---|---|
| Cortex-M7 | Keine | QEMU |
| Cortex-M55 | Ethos-U55 (256 MACs) | Arm FVP – Corstone SSE-300 |
MPS2_AN500 ist das Basis-Cortex-M7-Target ohne NPU. Es läuft unter QEMU, das schnell startet und der leichtgewichtige Weg ist, den plattformunabhängigen Code und die Testsuite auszuführen. Außerdem verfügt es über eine Netzwerkanbindung durch die User-Mode-NIC von QEMU, sodass socket-, requests- und mqtt-Skripte vom Simulator aus das Internet erreichen können.
MPS3_AN547 ist ein Cortex-M55 mit der Ethos-U55-NPU, ausgeführt auf Arms Fast Models – dem FVP, der das Corstone-SSE-300-Referenzsubsystem modelliert. Dies ist das Target, um die NPU und den ML-Modellpfad in der Simulation zu durchlaufen.
Beide stellen das ROM-Dateisystem und reichlich RAM bereit (und die NPU auf dem M55), sodass Vision- und ML-Skripte unverändert laufen.
Es gibt keinen echten Sensor, aber das csi-Modul funktioniert trotzdem gegen einen virtuellen – csi.CSI.snapshot() liefert ein synthetisches, animiertes Testmuster (ein scrollendes Schachbrett in Graustufen, ein Verlauf in RGB565), keine Live-Szene. Um echte Bildinhalte zu verarbeiten, lade sie stattdessen aus einer Datei: ein image.Image aus einer Fixture im ROM-Dateisystem oder einen image.ImageIO-Stream für aufgezeichnete Frames.
14.1.1.3.1. Bauen und ausführen#
Jeder Simulator ist ein Host-Werkzeug, das du selbst installierst. Du baust ein Target wie jedes andere (siehe Die Firmware bauen) und führst es dann mit run unter dem passenden Simulator aus – run baut das ROMFS-Image, bootet die Firmware und lässt sie mit einer seriellen Verbindung laufen, an die du dich anhängen kannst.
14.1.1.3.1.1. MPS2_AN500 (QEMU)#
QEMU wird in den meisten Paketmanagern als Arm-System-Emulator ausgeliefert:
Linux (Debian / Ubuntu) – installiere es mit
apt:sudo apt install qemu-system-armmacOS – installiere es mit Homebrew:
brew install qemu
Baue und führe dann das Target aus:
make -j$(nproc) TARGET=MPS2_AN500
make TARGET=MPS2_AN500 run
14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#
Das FVP ist Arms Fixed Virtual Platform für das Corstone SSE-300, ausgeliefert als Teil von Arm Virtual Hardware. Es ist nur für Linux verfügbar – verwende auf einem Mac stattdessen das obige QEMU-Target.
Lade das Bundle herunter, entpacke es und füge sein bin/-Verzeichnis zu deinem PATH hinzu:
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"
Das FVP benötigt außerdem die Python-Bibliotheken des SDK im LD_LIBRARY_PATH, wenn es läuft. Exportiere ihn einmal pro Shell vom Repo-Stammverzeichnis aus – das Lesen von SDK_VERSION hält ihn korrekt, während das Repo das fest verankerte SDK aktualisiert:
export LD_LIBRARY_PATH="$HOME/openmv-sdk-$(cat SDK_VERSION)/python/lib:$LD_LIBRARY_PATH"
Baue und führe dann das Target aus:
make -j$(nproc) TARGET=MPS3_AN547
make TARGET=MPS3_AN547 run
14.1.1.3.2. Die Test-Suite ausführen#
Die Unit-Tests befinden sich in scripts/unittest/tests/, mit ihren Fixture-Bildern und -Daten in scripts/unittest/data/. Sie werden mit mpremote ausgeführt, das scripts/unittest/ in den laufenden Simulator einhängt und dessen run.py ausführt.
Die Simulator-Verbindung ist mit dem Standard-mpremote langsam, verwende daher die im Repo mitgelieferte Kopie mit angewendetem Serial-Patch (wende ihn einmal an):
patch -N -p1 -d lib/micropython < tools/mpremote-qemu-serial.patch
Für MPS2_AN500 unter QEMU starte das Target – es gibt das Pseudo-Terminal aus, an dem sich sein serieller Port befindet (zum Beispiel /dev/pts/5):
make TARGET=MPS2_AN500 run
Richte dann aus einer anderen Shell das gepatchte mpremote auf dieses Gerät:
python3 lib/micropython/tools/mpremote/mpremote.py connect /dev/pts/5 \
mount scripts/unittest/ run scripts/unittest/run.py
Für MPS3_AN547 unter dem FVP ist der serielle Port stattdessen ein Telnet-Socket auf Port 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 findet und führt jeden Test aus und gibt pro Test eine PASSED / FAILED-Zeile mit Zeitangabe sowie am Ende eine Zusammenfassung aus.
14.1.1.3.3. Einen Test hinzufügen#
Tests werden automatisch gefunden. Um einen hinzuzufügen, lege eine Datei in scripts/unittest/tests/ ab, die eine Funktion unittest(data_path, temp_path) definiert, die True zurückgibt, wenn der Test besteht, und False, wenn er fehlschlägt:
# 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)
Die Argumente data_path und temp_path verweisen in die zwei Dateisysteme, die der Simulator sieht, während die Suite läuft:
Pfad | Gestützt durch |
|---|---|
| Das |
| Das schreibgeschützte ROM-Dateisystem des Boards, aus |
Ein neuer Test benötigt also keinen Neubau, eine neue Fixture jedoch schon: Das ROM-Image ist an romfs_config.json gebunden statt an die einzelnen Datendateien, also erzwinge den Neubau, indem du die romfs_config.json des Boards berührst (oder make TARGET=<TARGET> clean) und es erneut ausführst.
Erwartete Werte werden inline im Test geprüft, sodass es keine separate Datei mit erwarteter Ausgabe zu pflegen gibt. Um einen Test zur Laufzeit zu überspringen – zum Beispiel, wenn er Hardware benötigt, die der Simulator nicht modelliert – löse eine Exception aus, deren Nachricht "SKIPPED" enthält.