Arbeta med ROMFS

Översikt

ROMFS (Read-Only Memory Filesystem) är ett lättviktigt, skrivskyddat filsystem utformat för MicroPython-enheter. Det är optimerat för mikrokontroller och inbyggda system där kod och data behöver lagras i flashminne och nås effektivt utan att kopieras in i RAM.

De viktigaste fördelarna med ROMFS är:

  • Nollkopieringsimporter: .mpy-bytekodfiler som lagras i ett ROMFS kan köras direkt från flashminnet (minnesmappade) i stället för att först kopieras in i RAM. Detta liknar hur frysta moduler fungerar, men kräver inte att hela den fasta programvaran flashas om.

  • Låg RAM-belastning: Konstanta objekt (strängar, byte osv.) i .mpy-filer som läses in från ROMFS refereras direkt från flashminnet och dupliceras inte i RAM.

  • Flexibel driftsättning: En ROMFS-avbild kan byggas på en värddator och driftsättas på enheten med mpremote, utan att bygga om den fasta programvaran.

  • Standardiserat filsystemsgränssnitt: Ett ROMFS monteras i VFS och nås via vanliga Python-filoperationer (open, os.listdir, import osv.).

ROMFS kompletterar både de läs- och skrivbara FAT/LittleFS-filsystemen (som ligger i andra flashpartitioner) och frysta moduler (som kompileras in i själva den fasta programvaran).

Kortstöd

ROMFS är aktiverat i den fasta OpenMV-programvaran på varje kamerakort som har en ROMFS-partition reserverad i sin flashlayout. På dessa kort detekteras ROMFS-partitionen automatiskt vid uppstart och monteras vid /rom; både /rom och /rom/lib läggs till i sys.path så att moduler som lagras där kan importeras direkt.

Kort

ROMFS-stöd

OpenMV Cam N6

Ja

OpenMV AE3

Ja

OpenMV Cam RT1062

Ja

OpenMV Cam Pure Thermal

Ja

OpenMV Cam M4 / M7 / H7 / H7 Plus

Ja

Arduino Giga

Ja

Arduino Portenta H7

Ja

Arduino Nicla Vision

Ja

Arduino Nano 33 BLE Sense

Nej (ingen ROMFS-partition)

Arduino Nano RP2040 Connect

Nej (ingen ROMFS-partition)

Se romfs för en OpenMV-specifik hjälpfunktion som inspekterar det monterade ROMFS vid /rom.

Arbetsflöde

Det typiska arbetsflödet för att använda ROMFS är:

  1. Skapa en katalog på din dator med de Python-filer (eller .mpy-filer) som du vill driftsätta.

  2. Använd mpremote romfs deploy <directory> för att bygga och driftsätta ROMFS-avbilden på enheten.

  3. ROMFS monteras vid /rom vid nästa uppstart (eller kan monteras omedelbart om enheten startas om).

  4. Python-kod på enheten kan sedan import-era moduler från ROMFS precis som från vilket annat filsystem som helst.

Till exempel:

# On the host PC, with a directory "myapp/" containing app.py:
$ mpremote romfs deploy myapp/

Efter en mjuk omstart kommer enheten att ha /rom/app.py (eller /rom/app.mpy om mpy_cross är installerat) tillgängligt för import.

Se avsnittet mpremote romfs-underkommandon nedan för fullständiga detaljer om mpremote-underkommandona.

Python-API

ROMFS Python-API:et tillhandahålls via modulen vfs.

class vfs.VfsRom(buffer)

Skapar ett ROMFS-filsystemsobjekt från buffer, som måste vara ett objekt som stöder buffertprotokollet (t.ex. ett bytes-, bytearray- eller memoryview-objekt) som innehåller en giltig ROMFS-avbild.

Konstruktorn validerar att buffer börjar med ROMFS magiska byte (b"\xd2\xcd\x31"). Om bufferten är för liten eller inte är ett giltigt ROMFS genereras OSError(ENODEV).

Objekt som skapas av denna konstruktor kan monteras med vfs.mount().

Exempel:

import vfs

# Load a ROMFS image from flash into a memoryview.
dev = vfs.rom_ioctl(2, 0)   # get partition 0 as a memoryview
fs = vfs.VfsRom(dev)
vfs.mount(fs, '/rom')

Eller, för att montera en ROMFS-avbild som lagras i en fil:

import vfs

with open('/flash/app.romfs', 'rb') as f:
    romfs_data = f.read()
fs = vfs.VfsRom(romfs_data)
vfs.mount(fs, '/rom2')

Följande metoder finns tillgängliga på ett VfsRom-objekt:

VfsRom.open(path, mode)

Öppnar en fil från ROMFS. Endast läslägen ('', 'r', 'rt', 'rb') stöds. Att försöka öppna en fil för skrivning genererar OSError(EROFS).

Det returnerade filobjektet stöder read(), seek(), tell() och close(). För binära filer som öppnas i läsläge stöder det returnerade objektet även buffertprotokollet så att en memoryview av fildatan kan erhållas, vilken refererar direkt in i ROMFS-minnet (nollkopiering).

VfsRom.ilistdir(path)

Returnerar en iterator över posterna i katalogen path. Varje post är en tupel (name, type, inode, size) där type är 0x8000 för en fil eller 0x4000 för en katalog.

VfsRom.stat(path)

Returnerar en os.stat-liknande 10-tupel för path. Genererar OSError(ENOENT) om sökvägen inte existerar.

VfsRom.statvfs(path)

Returnerar filsystemsstatistik. Blockstorleken rapporteras som 1 och blockantalet representerar den totala storleken på ROMFS-avbilden i byte. Lediga block och lediga filer är alltid 0 (skrivskyddat filsystem).

VfsRom.chdir(path)

Byter katalog inom ROMFS. Endast roten ('/') stöds; att byta till någon underkatalog genererar OSError(EOPNOTSUPP).

VfsRom.getcwd()

Returnerar den aktuella arbetskatalogen inom ROMFS. Returnerar alltid '/'.

vfs.rom_ioctl(op, ...)

Lågnivågränssnitt för åtkomst till enhetens skrivskyddade minnespartition(er) (ROM).

De operationer som stöds är:

  • vfs.rom_ioctl(1) – Returnerar antalet tillgängliga ROM-partitioner.

  • vfs.rom_ioctl(2, id) – Returnerar ROM-partitionen med index id som ett memoryview-objekt. Minnet kan läsas men inte skrivas direkt.

  • vfs.rom_ioctl(3, id, length) – Förbereder en ROM-partition för skrivning. Raderar de första length byten i partitionen med index id. Returnerar den minsta skrivstorleken i byte (den justering som krävs för efterföljande skrivningar).

  • vfs.rom_ioctl(4, id, offset, buf) – Skriver buf (ett byteliknande objekt) till ROM-partitionen med index id vid byteoffset offset.

  • vfs.rom_ioctl(5, id) – Slutför en skrivsekvens till partition id (utför eventuell finalisering som behövs efter skrivning, såsom cachetömning).

Dessa operationer används internt av mpremote för att driftsätta ROMFS-avbilder. De flesta användare behöver inte anropa vfs.rom_ioctl() direkt.

Exempel (förfrågan om tillgängliga partitioner):

import vfs

n = vfs.rom_ioctl(1)
print("Number of ROM partitions:", n)
for i in range(n):
    dev = vfs.rom_ioctl(2, i)
    print(f"  Partition {i}: {len(dev)} bytes")

Automatisk montering vid uppstart

När ROMFS-stöd är aktiverat i den fasta programvaran kommer MicroPython automatiskt att försöka montera den första ROM-partitionen vid /rom under initialiseringen. Om partitionen innehåller en giltig ROMFS-avbild monteras den och både /rom och /rom/lib läggs automatiskt till i sys.path.

Detta innebär att efter att en ROMFS-avbild har driftsatts med mpremote räcker en mjuk omstart för att göra de nya modulerna importerbara.

Om ingen giltig ROMFS-avbild hittas i partitionen (t.ex. på ett nyprogrammerat kort) hoppas monteringen över utan meddelande.

Använda mpremote för att hantera ROMFS

Verktyget mpremote tillhandahåller tre underkommandon för att hantera ROMFS-avbilder på en ansluten enhet.

romfs query

$ mpremote romfs query

Listar alla tillgängliga ROMFS-partitioner på enheten och deras storlekar. Visar även de första 12 byten av varje partition i hex och rapporterar om en giltig ROMFS-avbild finns.

Exempelutdata:

ROMFS0 partition has size 131072 bytes (32 blocks of 4096 bytes each)
  Raw contents: d2:cd:31:XX:XX:XX:XX:XX:XX:XX:XX:XX ...
  ROMFS image size: 1234

romfs build

$ mpremote romfs [-o <output>] build <source>

Bygger en ROMFS-avbild från katalogen source på värddatorn. Avbilden skrivs till output (standard: <source>.romfs).

Alternativ:

  • -o <output>, --output <output>: Anger sökvägen till utdatafilen.

  • -m, --mpy (standard): Kompilerar automatiskt .py-filer till .mpy med mpy_cross innan de läggs till i avbilden. Kräver Python-paketet mpy_cross (pip install mpy_cross).

  • --no-mpy: Inaktiverar automatisk kompilering av .py-filer.

Exempel:

$ mpremote romfs build myapp/
Building romfs filesystem, source directory: myapp/
/
|-- main.py -> .mpy
\-- lib/
    \-- helper.py -> .mpy
Writing 2048 bytes to output file myapp.romfs

romfs deploy

$ mpremote romfs [-p <partition>] deploy <source>

Driftsätter en ROMFS-avbild på enheten. source kan vara antingen:

  • En katalog på värddatorn: ROMFS-avbilden byggs i minnet och driftsätts direkt.

  • En .romfs- eller .img-fil: avbilden läses från disk och driftsätts.

Alternativ:

  • -p <partition>, --partition <partition>: Anger målpartitionens index (standard: 0).

  • -m, --mpy (standard): Kompilerar .py till .mpy när source är en katalog.

  • --no-mpy: Inaktiverar automatisk kompilering av .py-filer.

Efter driftsättning måste enheten startas om mjukt för att det nya ROMFS ska monteras vid /rom.

Exempel:

$ mpremote romfs deploy myapp/
Building romfs filesystem, source directory: myapp/
/
|-- main.py -> .mpy
\-- lib/
    \-- helper.py -> .mpy
Image size is 2048 bytes
ROMFS0 partition has size 131072 bytes (32 blocks of 4096 bytes each)
Preparing ROMFS0 partition for writing
Deploying ROMFS to ROMFS0 partition
ROMFS image deployed

$ mpremote soft-reset

Exempel

Driftsätta en enkel applikation

Anta att du har en projektkatalog myapp/ med följande struktur:

myapp/
    main.py
    utils.py
    lib/
        helper.py

För att driftsätta den på enhetens ROMFS:

$ mpremote romfs deploy myapp/

Efter en mjuk omstart är modulerna importerbara från ROMFS:

import main
import utils
from lib import helper

Lista ROMFS-innehåll från Python

Efter montering kan ROMFS-innehållet utforskas som vilket annat filsystem som helst:

import os

for entry in os.ilistdir('/rom'):
    print(entry)

# Or simply:
print(os.listdir('/rom'))

OpenMV levererar även en liten romfs-hjälpfunktion som skriver ut en formaterad listning inklusive varje fils minnesmappade adress och justering:

from omv import romfs
romfs.ls_romfs()

Nästla ett ROMFS inom ett ROMFS

En ROMFS-avbild som lagras som en fil inom ett yttre ROMFS kan monteras som ett nästlat filsystem. Till exempel, om /rom/inner.romfs existerar. Eftersom /rom är ett ROMFS stöder filobjekt som öppnas därifrån buffertprotokollet, så en nollkopierings-memoryview kan erhållas direkt:

import vfs

with open('/rom/inner.romfs', 'rb') as f:
    inner = vfs.VfsRom(memoryview(f))
vfs.mount(inner, '/inner')

print(os.listdir('/inner'))

ROMFS-avbildsformat

ROMFS-avbildsformatet är ett kompakt binärformat utformat för minnesmappad åtkomst på mikrokontroller. En kort översikt:

  • Avbilden börjar med de magiska byten 0xd2 0xcd 0x31 (kodade som "RM1" med de höga bitarna i de första två byten satta).

  • Resten av avbilden består av poster, var och en med en typtagg (varuint), en längd (varuint) och en nyttolast.

  • Posttyper inkluderar: utfyllnad, ordagrann data, indirekt datapekare, katalog, fil.

  • Katalog- och filnamn lagras som längdprefixade bytesträngar.

  • Fildata kan lagras ordagrant (inline) eller via en indirekt pekare till någon annan plats i avbilden, vilket möjliggör justering för minnesmappad åtkomst.

  • Okända posttyper hoppas över utan meddelande, vilket ger framåtkompatibilitet.

Detta format definieras i extmod/vfs_rom.c i MicroPython-källkoden. Python-implementeringen som används av mpremote för att bygga avbilder finns i tools/mpremote/mpremote/romfs.py.

Se även

Arbeta med filsystem – Översikt över MicroPython VFS och tillgängliga filsystemstyper.

MicroPython-manifestfiler – Hur man fryser Python-moduler in i den fasta programvaran.

MicroPython .mpy-filer – MicroPython .mpy-binärfilformat.

MicroPython fjärrstyrning: mpremote – Den fullständiga mpremote-kommandoreferensen.

romfs – OpenMV-hjälpfunktion för att inspektera det monterade /rom-filsystemet.