14.1.1.3. Symulatory#
Dwie wartości TARGET budują oprogramowanie układowe do uruchomienia wewnątrz symulatora na twoim hoście, bez podłączonego sprzętu. Istnieją po to, aby oprogramowanie układowe można było uruchamiać i testować w dowolnym miejscu.
| Rdzeń | NPU | Symulator |
|---|---|---|---|
| Cortex-M7 | None | QEMU |
| Cortex-M55 | Ethos-U55 (256 MACs) | Arm FVP – Corstone SSE-300 |
MPS2_AN500 to bazowy cel Cortex-M7 bez NPU. Działa pod QEMU, który szybko się uruchamia i jest lekkim sposobem na sprawdzanie kodu niezależnego od platformy oraz zestawu testów.
MPS3_AN547 to Cortex-M55 z NPU Ethos-U55, uruchamiany na Arm Fast Models – FVP, który modeluje referencyjny podsystem Corstone SSE-300. To cel do sprawdzania NPU oraz ścieżki modelu ML w symulacji.
Oba zapewniają system plików ROM oraz mnóstwo RAM (a M55 także NPU), więc skrypty wizyjne i ML działają bez modyfikacji.
Nie ma prawdziwego sensora, ale moduł csi nadal działa z wirtualnym – csi.CSI.snapshot() zwraca syntetyczny, animowany wzorzec testowy (przewijająca się szachownica w skali szarości, gradient w RGB565), a nie scenę na żywo. Aby przetwarzać prawdziwą zawartość obrazu, wczytaj ją zamiast tego z pliku: image.Image z osprzętu testowego w systemie plików ROM albo strumień image.ImageIO dla nagranych klatek.
14.1.1.3.1. Budowanie i uruchamianie#
Każdy symulator to narzędzie hosta, które instalujesz samodzielnie. Budujesz cel jak każdy inny (zobacz Budowanie oprogramowania układowego), a następnie run uruchamia go pod odpowiednim symulatorem – run buduje obraz ROMFS, uruchamia oprogramowanie układowe i pozostawia je działające z połączeniem szeregowym, do którego możesz się podłączyć.
14.1.1.3.1.1. MPS2_AN500 (QEMU)#
QEMU jest dostępny w większości menedżerów pakietów jako emulator systemu Arm:
Linux (Debian / Ubuntu) – zainstaluj go za pomocą
apt:sudo apt install qemu-system-armmacOS – zainstaluj go za pomocą Homebrew:
brew install qemu
Następnie zbuduj i uruchom cel:
make -j$(nproc) TARGET=MPS2_AN500
make TARGET=MPS2_AN500 run
14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#
FVP to Fixed Virtual Platform firmy Arm dla Corstone SSE-300, dostarczana jako część Arm Virtual Hardware. Jest dostępna wyłącznie dla Linuksa – na Macu użyj zamiast tego celu QEMU powyżej.
Pobierz pakiet, rozpakuj go i umieść jego katalog bin/ w 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 podczas działania potrzebuje również bibliotek Pythona z SDK w LD_LIBRARY_PATH. Wyeksportuj go raz na powłokę z katalogu głównego repozytorium – odczyt SDK_VERSION utrzymuje go poprawnym, gdy repozytorium aktualizuje przypięty SDK:
export LD_LIBRARY_PATH="$HOME/openmv-sdk-$(cat SDK_VERSION)/python/lib:$LD_LIBRARY_PATH"
Następnie zbuduj i uruchom cel:
make -j$(nproc) TARGET=MPS3_AN547
make TARGET=MPS3_AN547 run
14.1.1.3.2. Uruchamianie zestawu testów#
Testy jednostkowe znajdują się w scripts/unittest/tests/, a ich obrazy osprzętu testowego oraz dane w scripts/unittest/data/. Są uruchamiane za pomocą mpremote, który montuje scripts/unittest/ na działającym symulatorze i wykonuje jego run.py.
Łącze symulatora jest powolne ze standardowym mpremote, więc użyj kopii dołączonej do repozytorium z zastosowaną łatką szeregową (zastosuj ją raz):
patch -N -p1 -d lib/micropython < tools/mpremote-qemu-serial.patch
Dla MPS2_AN500 pod QEMU uruchom cel – wypisuje on pseudoterminal, na którym znajduje się jego port szeregowy (na przykład /dev/pts/5):
make TARGET=MPS2_AN500 run
Następnie, z innej powłoki, wskaż załatany mpremote na to urządzenie:
python3 lib/micropython/tools/mpremote/mpremote.py connect /dev/pts/5 \
mount scripts/unittest/ run scripts/unittest/run.py
Dla MPS3_AN547 pod FVP port szeregowy jest zamiast tego gniazdem telnet na porcie 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 wykrywa i wykonuje każdy test, wypisując linię PASSED / FAILED na test wraz z czasem oraz podsumowaniem na końcu.
14.1.1.3.3. Dodawanie testu#
Testy są wykrywane automatycznie. Aby dodać jeden, umieść w scripts/unittest/tests/ plik definiujący funkcję unittest(data_path, temp_path) zwracającą True, gdy test przechodzi, i False, gdy się nie powiedzie:
# 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)
Argumenty data_path oraz temp_path wskazują na dwa systemy plików, które symulator widzi podczas działania zestawu:
Ścieżka | Oparte na |
|---|---|
| Katalog |
| System plików ROM płytki tylko do odczytu, wbudowany w obraz oprogramowania układowego z |
Zatem nowy test nie wymaga ponownej kompilacji, ale nowy element osprzętu testowego już tak: obraz ROM jest kluczowany na podstawie romfs_config.json, a nie poszczególnych plików danych, więc wymuś ponowną kompilację, dotykając romfs_config.json płytki (lub make TARGET=<TARGET> clean) i uruchamiając ponownie.
Oczekiwane wartości są asercjonowane bezpośrednio w teście, więc nie ma osobnego pliku oczekiwanego wyniku do utrzymywania. Aby pominąć test w czasie działania – na przykład gdy potrzebuje on sprzętu, którego symulator nie modeluje – zgłoś wyjątek, którego komunikat zawiera "SKIPPED".