Trabajar con ROMFS¶
Descripción general¶
ROMFS (Read-Only Memory Filesystem, sistema de archivos de memoria de solo lectura) es un sistema de archivos ligero y de solo lectura diseñado para dispositivos MicroPython. Está optimizado para microcontroladores y sistemas embebidos donde el código y los datos deben almacenarse en memoria flash y accederse de forma eficiente sin copiarse en la RAM.
Las principales ventajas de ROMFS son:
Importaciones sin copia (zero-copy): los archivos de bytecode
.mpyalmacenados en un ROMFS pueden ejecutarse directamente desde la memoria flash (mapeada en memoria) en lugar de copiarse primero en la RAM. Esto es similar al funcionamiento de los módulos congelados, pero no requiere reflashear todo el firmware.Bajo consumo de RAM: los objetos constantes (cadenas, bytes, etc.) de los archivos
.mpycargados desde ROMFS se referencian directamente desde la memoria flash, sin duplicarse en la RAM.Despliegue flexible: una imagen ROMFS puede compilarse en un PC anfitrión y desplegarse en el dispositivo mediante mpremote, sin recompilar el firmware.
Interfaz de sistema de archivos estándar: un ROMFS se monta en el VFS y se accede a él mediante operaciones de archivo normales de Python (
open,os.listdir,import, etc.).
ROMFS es complementario tanto a los sistemas de archivos de lectura-escritura FAT/LittleFS (que residen en otras particiones de la memoria flash) como a los módulos congelados (que se compilan dentro del propio firmware).
Compatibilidad de placas¶
ROMFS está habilitado en el firmware de OpenMV en todas las placas de cámara que tienen una partición ROMFS reservada en su disposición de memoria flash. En estas placas, la partición ROMFS se detecta automáticamente al arrancar y se monta en /rom; tanto /rom como /rom/lib se añaden a sys.path para que los módulos almacenados allí puedan importarse directamente.
Placa |
Compatibilidad con ROMFS |
|---|---|
OpenMV Cam N6 |
Sí |
OpenMV AE3 |
Sí |
OpenMV Cam RT1062 |
Sí |
OpenMV Cam Pure Thermal |
Sí |
OpenMV Cam M4 / M7 / H7 / H7 Plus |
Sí |
Arduino Giga |
Sí |
Arduino Portenta H7 |
Sí |
Arduino Nicla Vision |
Sí |
Arduino Nano 33 BLE Sense |
No (sin partición ROMFS) |
Arduino Nano RP2040 Connect |
No (sin partición ROMFS) |
Consulte romfs para conocer un asistente específico de OpenMV que inspecciona el ROMFS montado en /rom.
Flujo de trabajo¶
El flujo de trabajo habitual para usar ROMFS es:
Cree un directorio en su PC con los archivos de Python (o archivos
.mpy) que desee desplegar.Use
mpremote romfs deploy <directory>para compilar y desplegar la imagen ROMFS en el dispositivo.El ROMFS se montará en
/romen el siguiente arranque (o puede montarse de inmediato si se reinicia el dispositivo).El código Python del dispositivo puede entonces hacer
importde los módulos del ROMFS igual que desde cualquier otro sistema de archivos.
Por ejemplo:
# On the host PC, with a directory "myapp/" containing app.py:
$ mpremote romfs deploy myapp/
Tras un reinicio por software, el dispositivo tendrá /rom/app.py (o /rom/app.mpy si mpy_cross está instalado) disponible para su importación.
Consulte la sección subcomandos de mpremote romfs más abajo para conocer todos los detalles de los subcomandos de mpremote.
API de Python¶
La API de Python de ROMFS se proporciona a través del módulo vfs.
- class vfs.VfsRom(buffer)
Crea un objeto de sistema de archivos ROMFS a partir de buffer, que debe ser un objeto compatible con el protocolo de búfer (por ejemplo, un objeto
bytes,bytearrayomemoryview) que contenga una imagen ROMFS válida.El constructor valida que buffer comience con los bytes mágicos de ROMFS (
b"\xd2\xcd\x31"). Si el búfer es demasiado pequeño o no es un ROMFS válido, se lanzaOSError(ENODEV).Los objetos creados por este constructor pueden montarse mediante
vfs.mount().Ejemplo:
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')
O bien, para montar una imagen ROMFS almacenada en un archivo:
import vfs with open('/flash/app.romfs', 'rb') as f: romfs_data = f.read() fs = vfs.VfsRom(romfs_data) vfs.mount(fs, '/rom2')
Los siguientes métodos están disponibles en un objeto
VfsRom:- VfsRom.open(path, mode)
Abre un archivo del ROMFS. Solo se admiten los modos de lectura (
'','r','rt','rb'). Intentar abrir un archivo para escritura lanzaráOSError(EROFS).El objeto de archivo devuelto admite
read(),seek(),tell()yclose(). Para archivos binarios abiertos en modo lectura, el objeto devuelto también admite el protocolo de búfer, de modo que puede obtenerse unmemoryviewde los datos del archivo, que apunta directamente a la memoria del ROMFS (sin copia).
- VfsRom.ilistdir(path)
Devuelve un iterador sobre las entradas del directorio path. Cada entrada es una tupla
(name, type, inode, size)donde type es0x8000para un archivo o0x4000para un directorio.
- VfsRom.stat(path)
Devuelve una 10-tupla similar a la de
os.statpara path. LanzaOSError(ENOENT)si la ruta no existe.
- VfsRom.statvfs(path)
Devuelve estadísticas del sistema de archivos. El tamaño de bloque se informa como 1 y el recuento de bloques representa el tamaño total de la imagen ROMFS en bytes. Los bloques libres y los archivos libres son siempre 0 (sistema de archivos de solo lectura).
- VfsRom.chdir(path)
Cambia de directorio dentro del ROMFS. Solo se admite la raíz (
'/'); cambiar a cualquier subdirectorio lanzaOSError(EOPNOTSUPP).
- VfsRom.getcwd()
Devuelve el directorio de trabajo actual dentro del ROMFS. Siempre devuelve
'/'.
- vfs.rom_ioctl(op, ...)
Interfaz de bajo nivel para acceder a la(s) partición(es) de memoria de solo lectura (ROM) del dispositivo.
Las operaciones admitidas son:
vfs.rom_ioctl(1)– Devuelve el número de particiones ROM disponibles.vfs.rom_ioctl(2, id)– Devuelve la partición ROM con índice id como un objetomemoryview. La memoria puede leerse pero no escribirse directamente.vfs.rom_ioctl(3, id, length)– Prepara una partición ROM para escritura. Borra los primeros length bytes de la partición con índice id. Devuelve el tamaño mínimo de escritura en bytes (la alineación requerida para las escrituras posteriores).vfs.rom_ioctl(4, id, offset, buf)– Escribe buf (un objeto de tipo bytes) en la partición ROM con índice id en el byte offset.vfs.rom_ioctl(5, id)– Completa una secuencia de escritura en la partición id (realiza cualquier finalización necesaria tras la escritura, como el vaciado de la caché).
Estas operaciones las usa internamente
mpremotepara desplegar imágenes ROMFS. La mayoría de los usuarios no necesitan llamar avfs.rom_ioctl()directamente.Ejemplo (consultando las particiones disponibles):
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")
Montaje automático al arrancar¶
Cuando la compatibilidad con ROMFS está habilitada en el firmware, MicroPython intentará montar automáticamente la primera partición ROM en /rom durante la inicialización. Si la partición contiene una imagen ROMFS válida, se monta y tanto /rom como /rom/lib se añaden automáticamente a sys.path.
Esto significa que, tras desplegar una imagen ROMFS con mpremote, basta con un reinicio por software para que los nuevos módulos sean importables.
Si no se encuentra ninguna imagen ROMFS válida en la partición (por ejemplo, en una placa recién programada), el montaje se omite de forma silenciosa.
Usar mpremote para gestionar ROMFS¶
La herramienta mpremote proporciona tres subcomandos para gestionar imágenes ROMFS en un dispositivo conectado.
romfs query¶
$ mpremote romfs query
Lista todas las particiones ROMFS disponibles en el dispositivo y sus tamaños. También muestra los primeros 12 bytes de cada partición en hexadecimal e informa de si hay presente una imagen ROMFS válida.
Salida de ejemplo:
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>
Compila una imagen ROMFS a partir del directorio source en el PC anfitrión. La imagen se escribe en output (predeterminado: <source>.romfs).
Opciones:
-o <output>,--output <output>: especifica la ruta del archivo de salida.-m,--mpy(predeterminado): compila automáticamente los archivos.pya.mpyusandompy_crossantes de añadirlos a la imagen. Requiere el paquete de Pythonmpy_cross(pip install mpy_cross).--no-mpy: desactiva la compilación automática de los archivos.py.
Ejemplo:
$ 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>
Despliega una imagen ROMFS en el dispositivo. source puede ser:
Un directorio en el anfitrión: la imagen ROMFS se compila en memoria y se despliega directamente.
Un archivo
.romfso.img: la imagen se lee del disco y se despliega.
Opciones:
-p <partition>,--partition <partition>: especifica el índice de la partición de destino (predeterminado:0).-m,--mpy(predeterminado): compila los archivos.pya.mpycuando source es un directorio.--no-mpy: desactiva la compilación automática de los archivos.py.
Tras el despliegue, el dispositivo debe reiniciarse por software para que el nuevo ROMFS se monte en /rom.
Ejemplo:
$ 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
Ejemplos¶
Desplegar una aplicación sencilla¶
Supongamos que tiene un directorio de proyecto myapp/ con la siguiente estructura:
myapp/
main.py
utils.py
lib/
helper.py
Para desplegarlo en el ROMFS del dispositivo:
$ mpremote romfs deploy myapp/
Tras un reinicio por software, los módulos pueden importarse desde el ROMFS:
import main
import utils
from lib import helper
Listar el contenido del ROMFS desde Python¶
Tras el montaje, el contenido del ROMFS puede explorarse como cualquier otro sistema de archivos:
import os
for entry in os.ilistdir('/rom'):
print(entry)
# Or simply:
print(os.listdir('/rom'))
OpenMV también incluye un pequeño asistente romfs que imprime un listado con formato que incluye la dirección mapeada en memoria y la alineación de cada archivo:
from omv import romfs
romfs.ls_romfs()
Anidar un ROMFS dentro de un ROMFS¶
Una imagen ROMFS almacenada como archivo dentro de un ROMFS exterior puede montarse como un sistema de archivos anidado. Por ejemplo, si /rom/inner.romfs existe. Como /rom es un ROMFS, los objetos de archivo abiertos desde él admiten el protocolo de búfer, por lo que puede obtenerse directamente un memoryview sin copia:
import vfs
with open('/rom/inner.romfs', 'rb') as f:
inner = vfs.VfsRom(memoryview(f))
vfs.mount(inner, '/inner')
print(os.listdir('/inner'))
Formato de imagen de ROMFS¶
El formato de imagen de ROMFS es un formato binario compacto diseñado para el acceso mapeado en memoria en microcontroladores. Una breve descripción general:
La imagen comienza con los bytes mágicos
0xd2 0xcd 0x31(codificados como"RM1"con los bits altos de los dos primeros bytes activados).El resto de la imagen se compone de registros, cada uno con una etiqueta de tipo (varuint), una longitud (varuint) y una carga útil.
Los tipos de registro incluyen: relleno, datos literales, puntero indirecto a datos, directorio y archivo.
Los nombres de directorios y archivos se almacenan como cadenas de bytes con prefijo de longitud.
Los datos de los archivos pueden almacenarse de forma literal (en línea) o mediante un puntero indirecto a otra parte de la imagen, lo que permite la alineación para el acceso mapeado en memoria.
Los tipos de registro desconocidos se omiten de forma silenciosa, lo que proporciona compatibilidad hacia adelante.
Este formato está definido en extmod/vfs_rom.c en el código fuente de MicroPython. La implementación de Python que usa mpremote para compilar imágenes se encuentra en tools/mpremote/mpremote/romfs.py.
Ver también
Trabajar con sistemas de archivos – Descripción general del VFS de MicroPython y de los tipos de sistema de archivos disponibles.
Archivos de manifiesto de MicroPython – Cómo congelar módulos de Python en el firmware.
Archivos .mpy de MicroPython – Formato de archivo binario .mpy de MicroPython.
Control remoto de MicroPython: mpremote – La referencia completa de comandos de mpremote.
romfs – Asistente de OpenMV para inspeccionar el sistema de archivos /rom montado.