14.1.1.3. 模擬器#

有兩個 TARGET 值會把韌體建置成在你主機上的模擬器內執行,不需接上任何硬體。它們的存在讓韌體能在任何地方執行與測試。

TARGET

核心

NPU

模擬器

MPS2_AN500

Cortex-M7

None

QEMU

MPS3_AN547

Cortex-M55

Ethos-U55 (256 MACs)

Arm FVP -- Corstone SSE-300

MPS2_AN500 是不含 NPU 的基準 Cortex-M7 目標。它在 QEMU 下執行,啟動快速,是用來操練與平台無關的程式碼以及測試套件的輕量方式。

MPS3_AN547 是搭配 Ethos-U55 NPU 的 Cortex-M55,在 Arm 的 Fast Models——即 FVP 上執行,它模擬 Corstone SSE-300 參考子系統。這是在模擬中操練 NPU 與 ML 模型路徑的目標。

兩者都提供 ROM 檔案系統與充足的 RAM(M55 上還有 NPU),因此視覺與 ML 指令碼無需修改即可執行。

沒有真實的感測器,但 csi 模組仍能對著一個虛擬感測器運作——csi.CSI.snapshot() 會回傳一個合成的動態測試圖樣(灰階下為捲動的棋盤格,RGB565 下為漸層),而非實景。若要處理真實的影像內容,請改從檔案載入:來自 ROM 檔案系統中夾具的 image.Image,或用於已錄製影格的 image.ImageIO 串流。

14.1.1.3.1. 建置與執行#

每個模擬器都是你自行安裝的主機工具。你像建置其他任何目標一樣建置一個目標(參見 建置韌體),然後在對應的模擬器下 run 它——run 會建置 ROMFS 映像、啟動韌體,並讓它持續執行,附帶一個你可以連接的序列埠連線。

14.1.1.3.1.1. MPS2_AN500 (QEMU)#

QEMU 在大多數套件管理員中以 Arm 系統模擬器的形式提供:

  • Linux(Debian / Ubuntu)——以 apt 安裝它:

    sudo apt install qemu-system-arm
    
  • macOS——以 Homebrew 安裝它:

    brew install qemu
    

接著建置並執行該目標:

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

14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#

FVP 是 Arm 針對 Corstone SSE-300 的固定虛擬平台(Fixed Virtual Platform),作為 Arm Virtual Hardware 的一部分發布。它僅限 Linux 可用——在 Mac 上,請改用上面的 QEMU 目標。

下載該套件包、解壓縮,並把它的 bin/ 目錄放到你的 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 在執行時還需要 SDK 的 Python 函式庫位於 LD_LIBRARY_PATH 上。請在每個 shell 中從儲存庫根目錄匯出一次——讀取 SDK_VERSION 可在儲存庫更新所釘選的 SDK 時讓它保持正確:

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

接著建置並執行該目標:

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

14.1.1.3.2. 執行測試套件#

單元測試位於 scripts/unittest/tests/,其夾具影像與資料則位於 scripts/unittest/data/。它們以 mpremote 執行,它會把 scripts/unittest/ 掛載到執行中的模擬器上,並執行其 run.py

在現成的 mpremote 下模擬器連線很慢,因此請使用儲存庫中已套用序列埠修補的內附版本(套用一次即可):

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

對於 QEMU 下的 MPS2_AN500,啟動該目標——它會印出其序列埠所在的偽終端機(例如 /dev/pts/5):

make TARGET=MPS2_AN500 run

接著,從另一個 shell 中,讓已修補的 mpremote 指向該裝置:

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

對於 FVP 下的 MPS3_AN547,序列埠改為 5555 埠上的 telnet socket:

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 會探索並執行每一項測試,每項測試印出一行 PASSED / FAILED 並附上計時,最後再加上一份摘要。

14.1.1.3.3. 新增測試#

測試會被自動探索。若要新增一項,請在 scripts/unittest/tests/ 中放入一個檔案,其中定義一個 unittest(data_path, temp_path) 函式,測試通過時回傳 True,失敗時回傳 False

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

data_pathtemp_path 引數指向套件執行期間模擬器所看見的兩個檔案系統:

Path

Backed by

/remote

主機的 scripts/unittest/ 目錄,透過 mpremote 連線即時掛載。run.py 與它探索到的 tests/ 都位於此處,因此新增或編輯測試會在下一次執行時生效,無需重新建置。temp_path 在裝置上是 /remote/temp,即你主機的 scripts/unittest/temp/——這是供建立檔案的測試使用的可寫入暫存目錄。

/rom

開發板的唯讀 ROM 檔案系統,由 romfs_config.json 建入韌體映像:包含測試夾具(來自 scripts/unittest/data/)與內附的 ML 模型。data_path/rom——以 data_path + "/<file>" 來取得某個夾具。

因此新增一項測試不需重新建置,但新增一個夾具則需要:ROM 映像是依 romfs_config.json 而非各別資料檔來判定的,因此請藉由 touch 開發板的 romfs_config.json(或執行 make TARGET=<TARGET> clean)來強制重新建置,然後再次執行。

預期值是在測試中以行內方式斷言的,因此沒有另外要維護的預期輸出檔案。若要在執行期略過某項測試——例如當它需要模擬器並未建模的硬體時——請拋出一個訊息中含有 "SKIPPED" 的例外。