14.1.1.3. Simulators#

ค่า TARGET สองค่าจะสร้างเฟิร์มแวร์ให้รันภายใน simulator บนโฮสต์ของคุณ โดยไม่ต้องต่อฮาร์ดแวร์ มันมีอยู่เพื่อให้สามารถรันและทดสอบเฟิร์มแวร์ได้ทุกที่

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 คือเป้าหมาย Cortex-M7 พื้นฐานที่ไม่มี NPU มันรันภายใต้ QEMU ซึ่งเริ่มทำงานได้เร็วและเป็นวิธีแบบเบาในการทดสอบโค้ดที่เป็นอิสระจากแพลตฟอร์มและชุดทดสอบ

MPS3_AN547 คือ Cortex-M55 พร้อม NPU แบบ Ethos-U55 รันบน Fast Models ของ Arm -- คือ FVP ซึ่งจำลองระบบย่อยอ้างอิง Corstone SSE-300 นี่คือเป้าหมายสำหรับการทดสอบ NPU และเส้นทางโมเดล ML ในการจำลอง

ทั้งสองให้ระบบไฟล์ ROM และ RAM จำนวนมาก (และ NPU บน M55) ดังนั้นสคริปต์ vision และ ML จึงรันได้โดยไม่ต้องแก้ไข

ไม่มีเซนเซอร์จริง แต่โมดูล csi ยังคงทำงานกับเซนเซอร์เสมือนได้ -- csi.CSI.snapshot() คืนค่ารูปแบบทดสอบสังเคราะห์แบบเคลื่อนไหว (กระดานหมากรุกที่เลื่อนได้ในแบบ grayscale, gradient ในแบบ RGB565) ไม่ใช่ฉากสด ในการประมวลผลเนื้อหาภาพจริง ให้โหลดจากไฟล์แทน: image.Image จาก fixture ในระบบไฟล์ ROM หรือสตรีม image.ImageIO สำหรับเฟรมที่บันทึกไว้

14.1.1.3.1. การสร้างและการรัน#

simulator แต่ละตัวเป็นเครื่องมือโฮสต์ที่คุณติดตั้งเอง คุณสร้างเป้าหมายเหมือนกับเป้าหมายอื่น ๆ (ดู การสร้างเฟิร์มแวร์) จากนั้น run มันภายใต้ simulator ที่ตรงกัน -- run จะสร้างภาพ ROMFS บูตเฟิร์มแวร์ และปล่อยให้มันรันต่อพร้อมการเชื่อมต่อ serial ที่คุณสามารถเชื่อมต่อได้

14.1.1.3.1.1. MPS2_AN500 (QEMU)#

QEMU มาพร้อมกับ package manager ส่วนใหญ่ในฐานะ Arm system emulator:

  • 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 คือ Fixed Virtual Platform ของ Arm สำหรับ Corstone SSE-300 จัดส่งมาเป็นส่วนหนึ่งของ Arm Virtual Hardware มันมีให้สำหรับ Linux เท่านั้น -- บน Mac ให้ใช้เป้าหมาย QEMU ด้านบนแทน

ดาวน์โหลด bundle แตกไฟล์ และนำไดเรกทอรี 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 ยังต้องการ Python libraries ของ SDK บน LD_LIBRARY_PATH เมื่อมันรัน export มันครั้งเดียวต่อ shell จาก root ของ repo -- การอ่าน SDK_VERSION จะทำให้มันถูกต้องเมื่อ repo อัปเดต 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/ พร้อมภาพ fixture และข้อมูลใน scripts/unittest/data/ มันถูกรันด้วย mpremote ซึ่ง mount scripts/unittest/ ลงบน simulator ที่กำลังรันและรัน run.py ของมัน

การเชื่อมต่อ simulator ช้าด้วย mpremote มาตรฐาน ดังนั้นให้ใช้สำเนาที่มาพร้อมใน repo ที่ใช้ serial patch แล้ว (ใช้มันครั้งเดียว):

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

สำหรับ MPS2_AN500 ภายใต้ QEMU เริ่มเป้าหมาย -- มันจะพิมพ์ pseudo-terminal ที่พอร์ต serial ของมันอยู่ (เช่น /dev/pts/5):

make TARGET=MPS2_AN500 run

จากนั้น จาก shell อื่น ชี้ mpremote ที่ patch แล้วไปยังอุปกรณ์นั้น:

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

สำหรับ MPS3_AN547 ภายใต้ FVP พอร์ต serial เป็น telnet socket บนพอร์ต 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 ค้นหาและรันทุกการทดสอบ โดยพิมพ์บรรทัด 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_path และ temp_path ชี้ไปยังระบบไฟล์สองระบบที่ simulator เห็นในขณะที่ชุดทดสอบรัน:

Path

Backed by

/remote

ไดเรกทอรี scripts/unittest/ ของโฮสต์ ที่ mount แบบสดผ่านการเชื่อมต่อ mpremote run.py และ tests/ ที่มันค้นพบอยู่ที่นี่ ดังนั้นการเพิ่มหรือแก้ไขการทดสอบจะมีผลในการรันครั้งถัดไปโดยไม่ต้องสร้างใหม่ temp_path คือ /remote/temp บนอุปกรณ์ ซึ่งก็คือ scripts/unittest/temp/ ของโฮสต์ -- ไดเรกทอรีชั่วคราวที่เขียนได้สำหรับการทดสอบที่สร้างไฟล์

/rom

ระบบไฟล์ ROM แบบอ่านอย่างเดียวของบอร์ด ที่สร้างเข้าไปในภาพเฟิร์มแวร์จาก romfs_config.json: test fixtures (จาก scripts/unittest/data/) และโมเดล ML ที่มาพร้อม data_path คือ /rom -- เข้าถึง fixture ในรูปแบบ data_path + "/<file>"

ดังนั้น test ใหม่ไม่ต้องสร้างใหม่ แต่ fixture ใหม่ต้อง: ภาพ ROM ถูกอ้างอิงจาก romfs_config.json มากกว่าไฟล์ข้อมูลแต่ละไฟล์ ดังนั้นให้บังคับการสร้างใหม่โดย touch romfs_config.json ของบอร์ด (หรือ make TARGET=<TARGET> clean) และรันอีกครั้ง

ค่าที่คาดหวังจะถูก assert แบบ inline ในการทดสอบ ดังนั้นจึงไม่มีไฟล์ expected-output แยกต่างหากที่ต้องดูแล ในการข้ามการทดสอบขณะรันไทม์ -- เช่น เมื่อมันต้องการฮาร์ดแวร์ที่ simulator ไม่ได้จำลอง -- ให้ raise exception ที่ข้อความมี "SKIPPED"