14.1.1.3. Simuladores#

Dois valores de TARGET compilam o firmware para correr dentro de um simulador no seu anfitrião, sem hardware ligado. Existem para que o firmware possa ser executado e testado em qualquer lugar.

TARGET

Núcleo

NPU

Simulador

MPS2_AN500

Cortex-M7

None

QEMU

MPS3_AN547

Cortex-M55

Ethos-U55 (256 MACs)

Arm FVP – Corstone SSE-300

O MPS2_AN500 é o alvo Cortex-M7 base sem NPU. Corre sob o QEMU, que arranca rapidamente e é a forma leve de exercitar o código independente da plataforma e o conjunto de testes.

O MPS3_AN547 é um Cortex-M55 com o NPU Ethos-U55, executado nos Fast Models da Arm – o FVP, que modela o subsistema de referência Corstone SSE-300. Este é o alvo para exercitar o NPU e o caminho do modelo de ML em simulação.

Ambos fornecem o sistema de ficheiros ROM e bastante RAM (e o NPU no M55), pelo que os scripts de visão e de ML correm sem modificações.

Não existe um sensor real, mas o módulo csi continua a funcionar contra um virtual – csi.CSI.snapshot() devolve um padrão de teste sintético e animado (um tabuleiro de xadrez deslizante em escala de cinzentos, um gradiente em RGB565), não uma cena ao vivo. Para processar conteúdo de imagem real, carregue-o antes de um ficheiro: uma image.Image a partir de um fixture no sistema de ficheiros ROM, ou um fluxo image.ImageIO para frames gravados.

14.1.1.3.1. Compilar e executar#

Cada simulador é uma ferramenta de anfitrião que instala você mesmo. Compila um alvo como qualquer outro (consulte Compilar o firmware), depois fá-lo correr com run sob o simulador correspondente – o run compila a imagem ROMFS, arranca o firmware e deixa-o a correr com uma ligação série à qual se pode ligar.

14.1.1.3.1.1. MPS2_AN500 (QEMU)#

O QEMU vem na maioria dos gestores de pacotes como o emulador de sistema Arm:

  • Linux (Debian / Ubuntu) – instale-o com apt:

    sudo apt install qemu-system-arm
    
  • macOS – instale-o com o Homebrew:

    brew install qemu
    

Depois compile e execute o alvo:

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

14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#

O FVP é a Fixed Virtual Platform da Arm para o Corstone SSE-300, distribuída como parte do Arm Virtual Hardware. Está disponível apenas para Linux – num Mac, utilize antes o alvo QEMU acima.

Transfira o pacote, extraia-o e coloque o seu diretório bin/ no seu 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"

O FVP também necessita das bibliotecas Python do SDK no LD_LIBRARY_PATH quando corre. Exporte-o uma vez por shell a partir da raiz do repositório – ler SDK_VERSION mantém-no correto à medida que o repositório atualiza o SDK definido:

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

Depois compile e execute o alvo:

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

14.1.1.3.2. Executar o conjunto de testes#

Os testes unitários residem em scripts/unittest/tests/, com as suas imagens de fixture e dados em scripts/unittest/data/. São executados com o mpremote, que monta scripts/unittest/ no simulador em execução e executa o seu run.py.

A ligação ao simulador é lenta com o mpremote original, por isso utilize a cópia incluída no repositório com o patch de série aplicado (aplique-o uma vez):

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

Para o MPS2_AN500 sob o QEMU, inicie o alvo – este imprime o pseudo-terminal em que a sua porta série está (por exemplo /dev/pts/5):

make TARGET=MPS2_AN500 run

Depois, a partir de outra shell, aponte o mpremote corrigido para esse dispositivo:

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

Para o MPS3_AN547 sob o FVP, a porta série é antes um socket telnet na porta 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

O run.py descobre e executa cada teste, imprimindo uma linha PASSED / FAILED por teste com tempos e um resumo no final.

14.1.1.3.3. Adicionar um teste#

Os testes são descobertos automaticamente. Para adicionar um, coloque um ficheiro em scripts/unittest/tests/ que defina uma função unittest(data_path, temp_path) que devolva True quando o teste passa e False quando falha:

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

Os argumentos data_path e temp_path apontam para os dois sistemas de ficheiros que o simulador vê enquanto o conjunto corre:

Caminho

Suportado por

/remote

O diretório scripts/unittest/ do anfitrião, montado ao vivo sobre a ligação mpremote. O run.py e os tests/ que descobre residem aqui, pelo que adicionar ou editar um teste tem efeito na execução seguinte sem recompilação. temp_path é /remote/temp no dispositivo, que é o scripts/unittest/temp/ do seu anfitrião – um diretório de rascunho com permissão de escrita para testes que criam ficheiros.

/rom

O sistema de ficheiros ROM só de leitura da placa, integrado na imagem do firmware a partir de romfs_config.json: os fixtures de teste (de scripts/unittest/data/) e os modelos de ML incluídos. data_path é /rom – aceda a um fixture como data_path + "/<file>".

Assim, um novo teste não necessita de recompilação, mas um novo fixture sim: a imagem ROM é indexada a partir de romfs_config.json em vez dos ficheiros de dados individuais, pelo que force a recompilação ao tocar (touch) no romfs_config.json da placa (ou make TARGET=<TARGET> clean) e ao executar novamente.

Os valores esperados são verificados (assert) inline no teste, pelo que não há um ficheiro de saída esperada separado para manter. Para ignorar um teste em tempo de execução – por exemplo quando necessita de hardware que o simulador não modela – levante uma exceção cuja mensagem contenha "SKIPPED".