14.1.1.3. Simulator#

Dua nilai TARGET membangun firmware untuk dijalankan di dalam simulator pada host Anda, tanpa perangkat keras terpasang. Mereka ada agar firmware dapat dijalankan dan diuji di mana saja.

TARGET

Core

NPU

Simulator

MPS2_AN500

Cortex-M7

None

QEMU

MPS3_AN547

Cortex-M55

Ethos-U55 (256 MACs)

Arm FVP -- Corstone SSE-300

MPS2_AN500 adalah target Cortex-M7 dasar tanpa NPU. Ia berjalan di bawah QEMU, yang cepat untuk dimulai dan merupakan cara ringan untuk menguji kode yang independen platform dan suite pengujian.

MPS3_AN547 adalah Cortex-M55 dengan NPU Ethos-U55, dijalankan pada Fast Models milik Arm -- FVP, yang memodelkan subsistem referensi Corstone SSE-300. Ini adalah target untuk menguji NPU dan jalur model ML dalam simulasi.

Keduanya menyediakan filesystem ROM dan RAM yang berlimpah (dan NPU pada M55), sehingga skrip vision dan ML berjalan tanpa modifikasi.

Tidak ada sensor nyata, tetapi modul csi tetap bekerja terhadap sensor virtual -- csi.CSI.snapshot() mengembalikan pola pengujian sintetis yang dianimasikan (papan catur bergulir dalam grayscale, gradien dalam RGB565), bukan adegan langsung. Untuk memproses konten gambar nyata, muat dari sebuah file sebagai gantinya: sebuah image.Image dari fixture di filesystem ROM, atau aliran image.ImageIO untuk frame yang direkam.

14.1.1.3.1. Membangun dan menjalankan#

Setiap simulator adalah alat host yang Anda instal sendiri. Anda membangun sebuah target seperti yang lainnya (lihat Membangun firmware), lalu run di bawah simulator yang sesuai -- run membangun image ROMFS, mem-boot firmware, dan membiarkannya berjalan dengan koneksi serial yang dapat Anda lampirkan.

14.1.1.3.1.1. MPS2_AN500 (QEMU)#

QEMU tersedia di sebagian besar package manager sebagai emulator sistem Arm:

  • Linux (Debian / Ubuntu) -- instal dengan apt

    sudo apt install qemu-system-arm
    
  • macOS -- instal dengan Homebrew:

    brew install qemu
    

Kemudian bangun dan jalankan target:

make -j$(nproc) TARGET=MPS2_AN500
make TARGET=MPS2_AN500 run

14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#

FVP adalah Fixed Virtual Platform milik Arm untuk Corstone SSE-300, dikirimkan sebagai bagian dari Arm Virtual Hardware. Ia tersedia hanya untuk Linux -- pada Mac, gunakan target QEMU di atas sebagai gantinya.

Unduh bundle, ekstrak, dan tempatkan direktori bin/-nya pada PATH Anda:

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 juga membutuhkan library Python SDK pada LD_LIBRARY_PATH saat berjalan. Export sekali per shell dari root repo -- membaca SDK_VERSION menjaganya tetap benar saat repo memperbarui SDK yang disematkan:

export LD_LIBRARY_PATH="$HOME/openmv-sdk-$(cat SDK_VERSION)/python/lib:$LD_LIBRARY_PATH"

Kemudian bangun dan jalankan target:

make -j$(nproc) TARGET=MPS3_AN547
make TARGET=MPS3_AN547 run

14.1.1.3.2. Menjalankan suite pengujian#

Unit test berada di scripts/unittest/tests/, dengan gambar fixture dan datanya di scripts/unittest/data/. Mereka dijalankan dengan mpremote, yang me-mount scripts/unittest/ ke simulator yang sedang berjalan dan menjalankan run.py-nya.

Tautan simulator lambat dengan mpremote standar, jadi gunakan salinan yang dibundel dalam repo dengan patch serial diterapkan (terapkan sekali):

patch -N -p1 -d lib/micropython < tools/mpremote-qemu-serial.patch

Untuk MPS2_AN500 di bawah QEMU, jalankan target -- ia mencetak pseudo-terminal tempat port serialnya berada (misalnya /dev/pts/5):

make TARGET=MPS2_AN500 run

Kemudian, dari shell lain, arahkan mpremote yang telah dipatch ke perangkat tersebut:

python3 lib/micropython/tools/mpremote/mpremote.py connect /dev/pts/5 \
    mount scripts/unittest/ run scripts/unittest/run.py

Untuk MPS3_AN547 di bawah FVP, port serial adalah socket telnet pada port 5555 sebagai gantinya:

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 menemukan dan menjalankan setiap pengujian, mencetak baris PASSED / FAILED per pengujian dengan waktu dan ringkasan di akhir.

14.1.1.3.3. Menambahkan pengujian#

Pengujian ditemukan secara otomatis. Untuk menambahkan satu, letakkan sebuah file di scripts/unittest/tests/ yang mendefinisikan fungsi unittest(data_path, temp_path) yang mengembalikan True saat pengujian lulus dan False saat gagal:

# 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)

Argumen data_path dan temp_path menunjuk ke dua filesystem yang dilihat simulator saat suite berjalan:

Path

Backed by

/remote

Direktori scripts/unittest/ milik host, di-mount secara langsung melalui koneksi mpremote. run.py dan tests/ yang ditemukannya berada di sini, sehingga menambah atau mengedit pengujian berlaku pada run berikutnya tanpa rebuild. temp_path adalah /remote/temp pada perangkat, yang merupakan scripts/unittest/temp/ milik host Anda -- direktori scratch yang dapat ditulis untuk pengujian yang membuat file.

/rom

Filesystem ROM hanya-baca milik board, dibangun ke dalam image firmware dari romfs_config.json: fixture pengujian (dari scripts/unittest/data/) dan model ML yang dibundel. data_path adalah /rom -- jangkau sebuah fixture sebagai data_path + "/<file>".

Jadi sebuah pengujian baru tidak membutuhkan rebuild, tetapi sebuah fixture baru membutuhkannya: image ROM dikunci berdasarkan romfs_config.json alih-alih file data individual, jadi paksa rebuild dengan menyentuh romfs_config.json milik board (atau make TARGET=<TARGET> clean) dan jalankan kembali.

Nilai yang diharapkan diassert secara inline dalam pengujian, sehingga tidak ada file expected-output terpisah yang harus dipelihara. Untuk melewati pengujian saat runtime -- misalnya saat ia membutuhkan perangkat keras yang tidak dimodelkan simulator -- lemparkan sebuah exception yang pesannya berisi "SKIPPED".