14.1.1.3. Simulatoare#
Două valori TARGET construiesc firmware-ul pentru a rula într-un simulator pe gazda voastră, fără hardware atașat. Există pentru ca firmware-ul să poată fi rulat și testat oriunde.
| Nucleu | NPU | Simulator |
|---|---|---|---|
| Cortex-M7 | None | QEMU |
| Cortex-M55 | Ethos-U55 (256 MACs) | Arm FVP – Corstone SSE-300 |
MPS2_AN500 este ținta de bază Cortex-M7 fără NPU. Rulează sub QEMU, care pornește rapid și este modalitatea ușoară de a exersa codul independent de platformă și suita de teste.
MPS3_AN547 este un Cortex-M55 cu NPU-ul Ethos-U55, rulat pe Fast Models de la Arm – FVP, care modelează subsistemul de referință Corstone SSE-300. Aceasta este ținta pentru exersarea NPU-ului și a căii modelului ML în simulare.
Ambele oferă sistemul de fișiere ROM și multă RAM (și NPU-ul pe M55), astfel încât scripturile de viziune și ML rulează nemodificate.
Nu există un senzor real, dar modulul csi funcționează totuși cu unul virtual – csi.CSI.snapshot() returnează un model de test sintetic, animat (o tablă de șah derulantă în tonuri de gri, un gradient în RGB565), nu o scenă live. Pentru a procesa conținut de imagine real, încărcați-l dintr-un fișier în schimb: un image.Image dintr-un fixture din sistemul de fișiere ROM, sau un flux image.ImageIO pentru cadre înregistrate.
14.1.1.3.1. Construire și rulare#
Fiecare simulator este o unealtă gazdă pe care o instalați voi înșivă. Construiți o țintă ca oricare alta (vezi Construirea firmware-ului), apoi o run sub simulatorul corespunzător – run construiește imaginea ROMFS, pornește firmware-ul și îl lasă rulând cu o conexiune serială la care vă puteți atașa.
14.1.1.3.1.1. MPS2_AN500 (QEMU)#
QEMU este livrat în majoritatea managerilor de pachete ca emulatorul de sistem Arm:
Linux (Debian / Ubuntu) – instalați-l cu
aptsudo apt install qemu-system-armmacOS – instalați-l cu Homebrew:
brew install qemu
Apoi construiți și rulați ținta:
make -j$(nproc) TARGET=MPS2_AN500
make TARGET=MPS2_AN500 run
14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#
FVP este Fixed Virtual Platform de la Arm pentru Corstone SSE-300, livrat ca parte din Arm Virtual Hardware. Este disponibil doar pentru Linux – pe un Mac, folosiți în schimb ținta QEMU de mai sus.
Descărcați pachetul, extrageți-l și puneți directorul său bin/ în 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"
FVP are de asemenea nevoie de bibliotecile Python ale SDK-ului în LD_LIBRARY_PATH când rulează. Exportați-l o dată per shell din rădăcina depozitului – citirea SDK_VERSION îl menține corect pe măsură ce depozitul actualizează SDK-ul fixat:
export LD_LIBRARY_PATH="$HOME/openmv-sdk-$(cat SDK_VERSION)/python/lib:$LD_LIBRARY_PATH"
Apoi construiți și rulați ținta:
make -j$(nproc) TARGET=MPS3_AN547
make TARGET=MPS3_AN547 run
14.1.1.3.2. Rularea suitei de teste#
Testele unitare se află în scripts/unittest/tests/, cu imaginile lor fixture și datele în scripts/unittest/data/. Sunt rulate cu mpremote, care montează scripts/unittest/ pe simulatorul care rulează și execută run.py al acestuia.
Legătura cu simulatorul este lentă cu mpremote standard, așa că folosiți copia inclusă în depozit cu patch-ul serial aplicat (aplicați-l o dată):
patch -N -p1 -d lib/micropython < tools/mpremote-qemu-serial.patch
Pentru MPS2_AN500 sub QEMU, porniți ținta – aceasta afișează pseudo-terminalul pe care se află portul său serial (de exemplu /dev/pts/5):
make TARGET=MPS2_AN500 run
Apoi, dintr-un alt shell, îndreptați mpremote cu patch aplicat către acel dispozitiv:
python3 lib/micropython/tools/mpremote/mpremote.py connect /dev/pts/5 \
mount scripts/unittest/ run scripts/unittest/run.py
Pentru MPS3_AN547 sub FVP, portul serial este în schimb un socket telnet pe portul 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 descoperă și execută fiecare test, afișând o linie PASSED / FAILED per test cu cronometrare și un rezumat la final.
14.1.1.3.3. Adăugarea unui test#
Testele sunt descoperite automat. Pentru a adăuga unul, plasați un fișier în scripts/unittest/tests/ care definește o funcție unittest(data_path, temp_path) ce returnează True când testul trece și False când eșuează:
# 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)
Argumentele data_path și temp_path indică spre cele două sisteme de fișiere pe care le vede simulatorul în timp ce suita rulează:
Cale | Susținut de |
|---|---|
| Directorul |
| Sistemul de fișiere ROM doar-citire al plăcii, integrat în imaginea de firmware din |
Așadar un test nou nu necesită reconstruire, dar un fixture nou da: imaginea ROM este cheia după romfs_config.json mai degrabă decât după fișierele de date individuale, așa că forțați reconstruirea atingând romfs_config.json al plăcii (sau make TARGET=<TARGET> clean) și rulând din nou.
Valorile așteptate sunt verificate prin aserțiuni inline în test, așa că nu există un fișier separat de ieșire-așteptată de întreținut. Pentru a sări peste un test la rulare – de exemplu când are nevoie de hardware pe care simulatorul nu îl modelează – ridicați o excepție al cărei mesaj conține "SKIPPED".