14.2.2.2. Bygga en ROMFS-avbild

En ROMFS-avbild är ett flashresident, skrivskyddat filsystem som körningsmiljön monterar automatiskt vid /rom. Den löser tillgångsproblemet som föregående sida avslutade med: filer för maskininlärningsmodeller, etiketttabeller, JSON-konfiguration, bildmallar – allt som applikationen öppnar och läser men aldrig skriver – åker med in i bygget utan att betala kostnaden för att bäddas in som Python-literaler.

Tre saker gör ROMFS till rätt verktyg för levererade tillgångar:

  • Filsystemet är en del av avbilden av den fasta programvaran. Slutanvändare kan inte ta bort en fil ur /rom, redigera en, eller ersätta en med sin egen.

  • Filer i /rom är åtkomliga på plats. Konsumenter som ml-modulen, som laddar en modellfil, får en direkt vy in i flashminnet utan någon RAM-kopia – en flera megabyte stor modell på /rom ”laddas” i princip gratis, medan samma fil på /sdcard läses in i RAM vid laddningstillfället och stannar där under referensens livstid. Vanlig open() + read kopierar på begäran: varje read(n)-anrop kopierar n byte från flashminne till RAM i anropsögonblicket, medan ett naket read() begär hela filen.

  • /rom och /rom/lib läggs till i sys.path vid uppstart. Python-paket som placerats i avbilden är importerbara via namn; ingenting särskilt på anropsplatsen.

14.2.2.2.1. Bygga en avbild

ROMFS-avbilder skapas, redigeras och flashas via IDE:n. Använd den som sanningskällan för innehållet i varje levererad ROMFS-partition.

Anledningen till att detta spelar roll: modellfiler kommer med justeringskrav som laddaren upprätthåller vid körning. .tflite-filer måste fyllas ut till 16-bytegränser, och N6:ans NPU kräver 32-bytejustering för kompilerade modeller. IDE:n applicerar den utfyllnaden automatiskt när den skriver avbilden. Verktyg som går igenom källträdet utan att applicera utfyllnaden – mpremote romfs i synnerhet – producerar en avbild som monteras felfritt men vars modeller felar vid det första inferensanropet.

IDE:ns ROMFS-redigerare är en interaktiv vy av avbildens innehåll. Filer och mappar kan läggas till, döpas om och tas bort i minnet; vid sparande skrivs resultatet ut som en .img-fil redo att flashas. En typisk struktur för en applikation som levererar en modell tillsammans med några tillgångar och ett Python-paket ser ut så här:

model.tflite
labels.txt
config.json
templates/
    calibration.jpg
lib/
    mylib/
        __init__.py
        helpers.py

Tips

Både IDE:n och mpremote korskompilerar .py-filer till .mpy-bytekod på vägen in i en ROMFS-avbild, så att kameran importerar dem utan att betala tolkningskostnaden vid laddningstillfället. Källfiler i redigeraren förblir .py; avbilden innehåller .mpy.

När avbilden har flashats är trädet synligt från MicroPython vid /rom/

>>> import os
>>> os.listdir('/rom')
['model.tflite', 'labels.txt', 'config.json', 'templates', 'lib']
>>> import mylib
>>> mylib.helpers
<module 'mylib.helpers' from '/rom/lib/mylib/helpers.mpy'>

14.2.2.2.2. Det mesta av applikationen bor i ROMFS

ROMFS är det rätta hemmet för nästan allt en applikation levererar: biblioteken den importerar, modellfilerna den laddar, konfigurationen den läser, alla tillgångar vars utdata kom från ett byggverktyg som producerar ett filträd (modellkonverterare, bildpipelines, tillgångspackare), och – viktigt nog – applikationskoden själv.

Sidan med frysta moduler bör hållas liten: boot.py för uppsättning före REPL, main.py som en tunn startpunkt, och endast de bibliotek som kameran genuint inte kan starta utan. Allt annat hamnar i ROMFS, där iterering på det är en ny .img sparad ut ur IDE:n och omflashad – ingen ombyggnad av den fasta programvaran krävs, ingen verktygskedja behövs till hands för att göra det.

Mönstret som faller ut är en main.py som inte gör något annat än delegerar in i den ROMFS-residenta applikationen:

# main.py (frozen)
import app
app.run()

# /rom/app/__init__.py (in ROMFS)
def run():
    ...

En ändring av app är en ROMFS-redigering och en omflashning. Bygget av den fasta programvaran står stilla under produktens livstid om inte något på den frysta sidan faktiskt måste ändras.