Munka a ROMFS-sel

Áttekintés

A ROMFS (Read-Only Memory Filesystem) egy könnyűsúlyú, csak olvasható fájlrendszer, amelyet MicroPython eszközökhöz terveztek. Mikrokontrollerekre és beágyazott rendszerekre van optimalizálva, ahol a kódot és az adatokat flash memóriában kell tárolni, és hatékonyan kell hozzájuk férni anélkül, hogy RAM-ba másolnánk őket.

A ROMFS fő előnyei a következők:

  • Másolás nélküli importálás: a ROMFS-ben tárolt .mpy bájtkód-fájlok közvetlenül a flash memóriából (memóriába leképezve) futtathatók, ahelyett, hogy előbb RAM-ba másolnánk őket. Ez hasonló ahhoz, ahogyan a befagyasztott modulok működnek, de nem igényli a teljes firmware újraflashelését.

  • Alacsony RAM-igény: a ROMFS-ből betöltött .mpy fájlokban lévő állandó objektumokra (sztringek, bájtok stb.) közvetlenül a flash memóriából hivatkozunk, nem duplikálódnak a RAM-ban.

  • Rugalmas telepítés: a ROMFS-kép gazdagépen (PC-n) is felépíthető, és a mpremote segítségével telepíthető az eszközre, a firmware újrafordítása nélkül.

  • Szabványos fájlrendszer-interfész: a ROMFS a VFS rendszerbe van csatolva, és normál Python fájlműveletekkel (open, os.listdir, import stb.) érhető el.

A ROMFS kiegészíti mind az írható-olvasható FAT/LittleFS fájlrendszereket (amelyek más flash partíciókon helyezkednek el), mind a befagyasztott modulokat (amelyek magába a firmware-be vannak fordítva).

Eszköztámogatás

A ROMFS az OpenMV firmware-ben minden olyan kameramodulon engedélyezve van, amelynek a flash elrendezésében fenn van tartva egy ROMFS partíció. Ezeken a modulokon a ROMFS partíciót a rendszer indításkor automatikusan felismeri és a /rom útvonalra csatolja; mind a /rom, mind a /rom/lib hozzáadásra kerül a sys.path listához, így az ott tárolt modulok közvetlenül importálhatók.

Eszköz

ROMFS-támogatás

OpenMV Cam N6

Igen

OpenMV AE3

Igen

OpenMV Cam RT1062

Igen

OpenMV Cam Pure Thermal

Igen

OpenMV Cam M4 / M7 / H7 / H7 Plus

Igen

Arduino Giga

Igen

Arduino Portenta H7

Igen

Arduino Nicla Vision

Igen

Arduino Nano 33 BLE Sense

Nem (nincs ROMFS partíció)

Arduino Nano RP2040 Connect

Nem (nincs ROMFS partíció)

Lásd a romfs modult egy OpenMV-specifikus segédeszközhöz, amely a /rom útvonalra csatolt ROMFS-t vizsgálja.

Munkafolyamat

A ROMFS használatának tipikus munkafolyamata a következő:

  1. Hozz létre egy könyvtárat a PC-den a telepíteni kívánt Python fájlokkal (vagy .mpy fájlokkal).

  2. Használd az mpremote romfs deploy <directory> parancsot a ROMFS-kép felépítéséhez és az eszközre történő telepítéséhez.

  3. A ROMFS a következő indításkor a /rom útvonalra lesz csatolva (vagy azonnal csatolható, ha az eszközt újraindítod).

  4. Az eszközön futó Python kód ezután ugyanúgy import-álhat modulokat a ROMFS-ből, mint bármely más fájlrendszerből.

Például:

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

Soft-reset után az eszközön a /rom/app.py (vagy a /rom/app.mpy, ha az mpy_cross telepítve van) elérhető lesz importáláshoz.

Az mpremote alparancsainak teljes részleteiért lásd az alábbi mpremote romfs alparancsok szakaszt.

Python API

A ROMFS Python API-ját a vfs modul biztosítja.

class vfs.VfsRom(buffer)

Létrehoz egy ROMFS fájlrendszer-objektumot a buffer alapján, amelynek a pufferprotokollt támogató objektumnak kell lennie (pl. egy bytes, bytearray vagy memoryview objektum), és egy érvényes ROMFS-képet kell tartalmaznia.

A konstruktor ellenőrzi, hogy a buffer a ROMFS varázsbájtjaival (b"\xd2\xcd\x31") kezdődik-e. Ha a puffer túl kicsi, vagy nem érvényes ROMFS, akkor OSError(ENODEV) kivétel keletkezik.

Az ezzel a konstruktorral létrehozott objektumok a vfs.mount() függvénnyel csatolhatók.

Példa:

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

Vagy egy fájlban tárolt ROMFS-kép csatolásához:

import vfs

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

A VfsRom objektumon a következő metódusok érhetők el:

VfsRom.open(path, mode)

Megnyit egy fájlt a ROMFS-ből. Csak az olvasási módok ('', 'r', 'rt', 'rb') támogatottak. Egy fájl írásra történő megnyitásának kísérlete OSError(EROFS) kivételt vált ki.

A visszaadott fájlobjektum támogatja a read(), seek(), tell() és close() műveleteket. Az olvasási módban megnyitott bináris fájlok esetén a visszaadott objektum a pufferprotokollt is támogatja, így a fájl adataiból egy memoryview szerezhető, amely közvetlenül a ROMFS memóriájára hivatkozik (másolás nélkül).

VfsRom.ilistdir(path)

Visszaad egy iterátort a path könyvtár bejegyzésein. Minden bejegyzés egy (name, type, inode, size) tuple, ahol a type fájl esetén 0x8000, könyvtár esetén 0x4000.

VfsRom.stat(path)

Visszaad egy os.stat-szerű, 10 elemű tuple-t a path útvonalhoz. OSError(ENOENT) kivételt vált ki, ha az útvonal nem létezik.

VfsRom.statvfs(path)

Visszaadja a fájlrendszer statisztikáit. A blokkméret 1-ként van megadva, a blokkszám pedig a ROMFS-kép teljes méretét jelöli bájtban. A szabad blokkok és a szabad fájlok száma mindig 0 (csak olvasható fájlrendszer).

VfsRom.chdir(path)

Könyvtárat vált a ROMFS-en belül. Csak a gyökér ('/') támogatott; bármely alkönyvtárra való váltás OSError(EOPNOTSUPP) kivételt vált ki.

VfsRom.getcwd()

Visszaadja az aktuális munkakönyvtárat a ROMFS-en belül. Mindig '/'-t ad vissza.

vfs.rom_ioctl(op, ...)

Alacsony szintű interfész az eszköz csak olvasható memória- (ROM-) partíciójának/partícióinak eléréséhez.

A támogatott műveletek a következők:

  • vfs.rom_ioctl(1) – Visszaadja az elérhető ROM partíciók számát.

  • vfs.rom_ioctl(2, id) – Visszaadja az id indexű ROM partíciót memoryview objektumként. A memória olvasható, de közvetlenül nem írható.

  • vfs.rom_ioctl(3, id, length) – Előkészít egy ROM partíciót íráshoz. Törli az id indexű partíció első length bájtját. Visszaadja a minimális írási méretet bájtban (a későbbi írásokhoz szükséges igazítást).

  • vfs.rom_ioctl(4, id, offset, buf) – A buf-ot (egy bytes-szerű objektumot) az id indexű ROM partícióra írja a offset bájt eltolásnál.

  • vfs.rom_ioctl(5, id) – Befejez egy írási sorozatot az id partícióra (elvégzi az írás után szükséges véglegesítést, például a gyorsítótár kiürítését).

Ezeket a műveleteket az mpremote belsőleg használja ROMFS-képek telepítéséhez. A legtöbb felhasználónak nem kell közvetlenül meghívnia a vfs.rom_ioctl() függvényt.

Példa (az elérhető partíciók lekérdezése):

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

Automatikus csatolás indításkor

Ha a firmware-ben engedélyezve van a ROMFS-támogatás, a MicroPython az inicializálás során automatikusan megkísérli az első ROM partíciót a /rom útvonalra csatolni. Ha a partíció érvényes ROMFS-képet tartalmaz, csatolásra kerül, és mind a /rom, mind a /rom/lib automatikusan hozzáadódik a sys.path listához.

Ez azt jelenti, hogy egy ROMFS-kép mpremote segítségével történő telepítése után egy soft-reset elegendő ahhoz, hogy az új modulok importálhatóvá váljanak.

Ha a partícióban nem található érvényes ROMFS-kép (pl. egy frissen programozott modulon), a csatolás csendben kihagyásra kerül.

Az mpremote használata a ROMFS kezeléséhez

A mpremote eszköz három alparancsot biztosít a csatlakoztatott eszközön lévő ROMFS-képek kezeléséhez.

romfs query

$ mpremote romfs query

Felsorolja az eszközön elérhető összes ROMFS partíciót és azok méretét. Emellett megjeleníti az egyes partíciók első 12 bájtját hexadecimálisan, és jelzi, hogy van-e jelen érvényes ROMFS-kép.

Példakimenet:

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>

Felépít egy ROMFS-képet a gazdagépen (PC-n) lévő source könyvtárból. A kép a output helyre íródik (alapértelmezett: <source>.romfs).

Opciók:

  • -o <output>, --output <output>: A kimeneti fájl útvonalának megadása.

  • -m, --mpy (alapértelmezett): A .py fájlok automatikus fordítása .mpy formátumba az mpy_cross segítségével, mielőtt hozzáadná őket a képhez. Igényli az mpy_cross Python csomagot (pip install mpy_cross).

  • --no-mpy: A .py fájlok automatikus fordításának letiltása.

Példa:

$ 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>

ROMFS-kép telepítése az eszközre. A source a következők egyike lehet:

  • Egy könyvtár a gazdagépen: a ROMFS-kép a memóriában épül fel, és közvetlenül kerül telepítésre.

  • Egy .romfs vagy .img fájl: a kép lemezről kerül beolvasásra és telepítésre.

Opciók:

  • -p <partition>, --partition <partition>: A cél partíció indexének megadása (alapértelmezett: 0).

  • -m, --mpy (alapértelmezett): A .py fájlok .mpy formátumba fordítása, amikor a source egy könyvtár.

  • --no-mpy: A .py fájlok automatikus fordításának letiltása.

A telepítés után az eszközt soft-reset-elni kell, hogy az új ROMFS a /rom útvonalra csatolódjon.

Példa:

$ 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

Példák

Egy egyszerű alkalmazás telepítése

Tegyük fel, hogy van egy myapp/ projektkönyvtárad a következő szerkezettel:

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

Az eszköz ROMFS-ére történő telepítéshez:

$ mpremote romfs deploy myapp/

Soft-reset után a modulok importálhatók a ROMFS-ből:

import main
import utils
from lib import helper

A ROMFS tartalmának listázása Pythonból

A csatolás után a ROMFS tartalma bármely más fájlrendszerhez hasonlóan böngészhető:

import os

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

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

Az OpenMV egy kis romfs segédeszközt is szállít, amely formázott listát nyomtat, beleértve az egyes fájlok memóriába leképezett címét és igazítását:

from omv import romfs
romfs.ls_romfs()

ROMFS beágyazása egy ROMFS-be

Egy külső ROMFS-en belül fájlként tárolt ROMFS-kép beágyazott fájlrendszerként csatolható. Például, ha létezik a /rom/inner.romfs. Mivel a /rom egy ROMFS, az onnan megnyitott fájlobjektumok támogatják a pufferprotokollt, így közvetlenül egy másolás nélküli memoryview szerezhető:

import vfs

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

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

A ROMFS képformátuma

A ROMFS képformátuma egy kompakt bináris formátum, amelyet mikrokontrollereken történő, memóriába leképezett hozzáférésre terveztek. Rövid áttekintés:

  • A kép a 0xd2 0xcd 0x31 varázsbájtokkal kezdődik ("RM1"-ként kódolva, az első két bájt felső bitjeit beállítva).

  • A kép fennmaradó része rekordokból áll, mindegyik egy típuscímkével (varuint), egy hosszal (varuint) és egy hasznos adattal (payload).

  • A rekordtípusok közé tartozik: kitöltés, szó szerinti adat, közvetett adatmutató, könyvtár, fájl.

  • A könyvtár- és fájlnevek hossz-előtagos bájtsztringekként vannak tárolva.

  • A fájladatok tárolhatók szó szerint (beágyazva) vagy a képen belül máshova mutató közvetett mutatón keresztül, ami lehetővé teszi az igazítást a memóriába leképezett hozzáféréshez.

  • Az ismeretlen rekordtípusokat a rendszer csendben kihagyja, ami előremenő kompatibilitást biztosít.

Ez a formátum a MicroPython forráskódjában az extmod/vfs_rom.c fájlban van definiálva. Az mpremote által képek felépítéséhez használt Python implementáció a tools/mpremote/mpremote/romfs.py fájlban található.

Lásd még

Munka a fájlrendszerekkel – A MicroPython VFS és az elérhető fájlrendszer-típusok áttekintése.

MicroPython manifest fájlok – Hogyan fagyaszthatók be a Python modulok a firmware-be.

MicroPython .mpy fájlok – A MicroPython .mpy bináris fájlformátuma.

MicroPython távoli vezérlés: mpremote – A teljes mpremote parancsreferencia.

romfs – OpenMV segédeszköz a csatolt /rom fájlrendszer vizsgálatához.