14.2.2.2. Costruire un’immagine ROMFS¶
Un”immagine ROMFS è un filesystem di sola lettura residente in flash che il runtime monta automaticamente su /rom. Risolve il problema degli asset su cui si è chiusa la pagina precedente: file di modelli di machine learning, tabelle di etichette, configurazioni JSON, template di immagini – tutto ciò che l’applicazione apre e legge ma non scrive mai – viene incluso nella build senza pagare il costo di essere incorporato come literal Python.
Tre aspetti rendono la ROMFS lo strumento giusto per gli asset distribuiti:
Il filesystem è parte dell’immagine del firmware. Gli utenti finali non possono cancellare un file da
/rom, modificarne uno o sostituirne uno con il proprio.I file in
/romsono accessibili in loco. I consumatori come il modulomlche carica un file di modello ottengono una vista diretta nella flash senza copia in RAM – un modello di diversi megabyte su/romviene «caricato» essenzialmente a costo zero, mentre lo stesso file su/sdcardviene letto in RAM al momento del caricamento e vi rimane per tutta la durata del riferimento. Una normaleopen()+readcopia su richiesta: ogni chiamataread(n)copianbyte dalla flash alla RAM nel momento della chiamata, con unread()nudo che richiede l’intero file./rome/rom/libvengono aggiunti asys.pathall’avvio. I pacchetti Python inseriti nell’immagine sono importabili per nome; nulla di particolare nel punto di chiamata.
14.2.2.2.1. Costruire un’immagine¶
Le immagini ROMFS vengono create, modificate e flashate tramite l’IDE. Usalo come fonte di verità per il contenuto di ogni partizione ROMFS distribuita.
Il motivo per cui questo è importante: i file di modello hanno requisiti di allineamento che il loader applica a runtime. I file .tflite devono essere riempiti fino a confini di 16 byte, e la NPU dell’N6 richiede un allineamento a 32 byte per i modelli compilati. L’IDE applica automaticamente questo riempimento quando scrive l’immagine. Gli strumenti che attraversano l’albero dei sorgenti senza applicare il riempimento – mpremote romfs in particolare – producono un’immagine che si monta correttamente ma i cui modelli falliscono alla prima chiamata di inferenza.
L’editor ROMFS dell’IDE è una vista interattiva del contenuto dell’immagine. File e cartelle possono essere aggiunti, rinominati ed eliminati in memoria; il salvataggio scrive il risultato come file .img pronto per il flashing. Una struttura tipica per un’applicazione che distribuisce un modello insieme ad alcuni asset e a un pacchetto Python è simile a:
model.tflite
labels.txt
config.json
templates/
calibration.jpg
lib/
mylib/
__init__.py
helpers.py
Suggerimento
Sia l’IDE che mpremote cross-compilano i file .py in bytecode .mpy durante l’inserimento in un’immagine ROMFS, così la cam li importa senza pagare il costo del parsing al caricamento. I file sorgente nell’editor restano .py; l’immagine contiene file .mpy.
Una volta flashata l’immagine, l’albero è visibile da MicroPython in /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. Gran parte dell’applicazione risiede nella ROMFS¶
La ROMFS è la casa giusta per quasi tutto ciò che un’applicazione distribuisce: le librerie che importa, i file di modello che carica, la configurazione che legge, qualsiasi asset il cui output proviene da uno strumento di build che genera un albero di file (convertitori di modelli, pipeline di immagini, packer di asset) e – aspetto importante – il codice dell’applicazione stesso.
Il lato dei moduli congelati dovrebbe restare ridotto: boot.py per la configurazione pre-REPL, main.py come punto di ingresso leggero e solo le librerie senza cui la cam davvero non può avviarsi. Tutto il resto va nella ROMFS, dove iterare significa salvare un nuovo file .img dall’IDE e riflashare – nessuna ricostruzione del firmware richiesta, nessun toolchain a portata di mano per farlo.
Lo schema che ne deriva è un main.py che non fa altro che delegare all’applicazione residente nella ROMFS:
# main.py (frozen)
import app
app.run()
# /rom/app/__init__.py (in ROMFS)
def run():
...
Una modifica ad app è una modifica della ROMFS e un reflash. La build del firmware resta invariata per tutta la vita del prodotto, a meno che qualcosa sul lato congelato debba effettivamente cambiare.