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.

TARGET

Rdzeń

NPU

Symulator

MPS2_AN500

Cortex-M7

None

QEMU

MPS3_AN547

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-arm
    
  • macOS – 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

/remote

Katalog scripts/unittest/ hosta, montowany na żywo przez połączenie mpremote. run.py oraz wykrywane przez niego tests/ znajdują się tutaj, więc dodanie lub edycja testu zaczyna obowiązywać przy następnym uruchomieniu bez ponownej kompilacji. temp_path to /remote/temp na urządzeniu, czyli scripts/unittest/temp/ twojego hosta – zapisywalny katalog roboczy dla testów, które tworzą pliki.

/rom

System plików ROM płytki tylko do odczytu, wbudowany w obraz oprogramowania układowego z romfs_config.json: osprzęt testowy (z scripts/unittest/data/) oraz dołączone modele ML. data_path to /rom – sięgnij po element osprzętu testowego jako data_path + "/<file>".

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".