Trabalhar com ROMFS¶
Visão Geral¶
ROMFS (Sistema de Ficheiros em Memória Apenas de Leitura) é um sistema de ficheiros leve e somente de leitura concebido para dispositivos MicroPython. É optimizado para microcontroladores e sistemas embebidos onde o código e os dados precisam de ser armazenados em memória flash e acedidos de forma eficiente sem serem copiados para a RAM.
As principais vantagens do ROMFS são:
Importações sem cópia: os ficheiros de bytecode
.mpyarmazenados num ROMFS podem ser executados directamente a partir da memória flash (mapeada em memória) em vez de serem primeiro copiados para a RAM. Isto é semelhante ao funcionamento dos módulos congelados, mas não requer a re-escrita de todo o firmware.Baixa sobrecarga de RAM: os objectos constantes (strings, bytes, etc.) nos ficheiros
.mpycarregados a partir de ROMFS são referenciados directamente a partir da flash, sem duplicação na RAM.Implementação flexível: uma imagem ROMFS pode ser construída num PC anfitrião e implementada no dispositivo utilizando mpremote, sem necessidade de reconstruir o firmware.
Interface de sistema de ficheiros padrão: um ROMFS é montado no VFS e acedido através de operações normais de ficheiros Python (
open,os.listdir,import, etc.).
O ROMFS é complementar tanto aos sistemas de ficheiros FAT/LittleFS de leitura-escrita (que residem noutras partições flash) como aos módulos congelados (que são compilados no próprio firmware).
Suporte de placas¶
O ROMFS está activado no firmware OpenMV em todas as placas de câmara que têm uma partição ROMFS reservada no seu esquema de flash. Nestas placas, a partição ROMFS é detectada automaticamente no arranque e montada em /rom; tanto /rom como /rom/lib são adicionados ao sys.path para que os módulos aí armazenados possam ser importados directamente.
Placa |
Suporte ROMFS |
|---|---|
OpenMV Cam N6 |
Sim |
OpenMV AE3 |
Sim |
OpenMV Cam RT1062 |
Sim |
OpenMV Cam Pure Thermal |
Sim |
OpenMV Cam M4 / M7 / H7 / H7 Plus |
Sim |
Arduino Giga |
Sim |
Arduino Portenta H7 |
Sim |
Arduino Nicla Vision |
Sim |
Arduino Nano 33 BLE Sense |
Não (sem partição ROMFS) |
Arduino Nano RP2040 Connect |
Não (sem partição ROMFS) |
Consulte romfs para um utilitário específico do OpenMV que inspeciona o ROMFS montado em /rom.
Fluxo de Trabalho¶
O fluxo de trabalho típico para utilizar o ROMFS é:
Crie um directório no seu PC com os ficheiros Python (ou ficheiros
.mpy) que pretende implementar.Utilize
mpremote romfs deploy <directory>para construir e implementar a imagem ROMFS no dispositivo.O ROMFS será montado em
/romno próximo arranque (ou pode ser montado imediatamente se o dispositivo for reiniciado).O código Python no dispositivo pode então usar
importpara importar módulos do ROMFS tal como de qualquer outro sistema de ficheiros.
Por exemplo:
# On the host PC, with a directory "myapp/" containing app.py:
$ mpremote romfs deploy myapp/
Após uma reinicialização suave, o dispositivo terá /rom/app.py (ou /rom/app.mpy se o mpy_cross estiver instalado) disponível para importação.
Consulte a secção sub-comandos romfs do mpremote abaixo para detalhes completos dos sub-comandos do mpremote.
API Python¶
A API Python do ROMFS é fornecida através do módulo vfs.
- class vfs.VfsRom(buffer)
Cria um objecto de sistema de ficheiros ROMFS a partir de buffer, que deve ser um objecto que suporte o protocolo de buffer (p.ex. um objecto
bytes,bytearrayoumemoryview) contendo uma imagem ROMFS válida.O construtor valida que buffer começa com os bytes mágicos do ROMFS (
b"\xd2\xcd\x31"). Se o buffer for demasiado pequeno ou não for um ROMFS válido, é lançadoOSError(ENODEV).Os objectos criados por este construtor podem ser montados utilizando
vfs.mount().Exemplo:
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')
Ou, para montar uma imagem ROMFS armazenada num ficheiro:
import vfs with open('/flash/app.romfs', 'rb') as f: romfs_data = f.read() fs = vfs.VfsRom(romfs_data) vfs.mount(fs, '/rom2')
Os seguintes métodos estão disponíveis num objecto
VfsRom:- VfsRom.open(path, mode)
Abre um ficheiro do ROMFS. Apenas os modos de leitura (
'','r','rt','rb') são suportados. Tentar abrir um ficheiro para escrita lançaráOSError(EROFS).O objecto de ficheiro retornado suporta
read(),seek(),tell()eclose(). Para ficheiros binários abertos em modo de leitura, o objecto retornado também suporta o protocolo de buffer, pelo que se pode obter umamemoryviewdos dados do ficheiro, que referencia directamente a memória do ROMFS (sem cópia).
- VfsRom.ilistdir(path)
Retorna um iterador sobre as entradas no directório path. Cada entrada é um tuplo
(name, type, inode, size)onde type é0x8000para um ficheiro ou0x4000para um directório.
- VfsRom.stat(path)
Retorna um tuplo de 10 elementos semelhante a
os.statpara path. LançaOSError(ENOENT)se o caminho não existir.
- VfsRom.statvfs(path)
Retorna estatísticas do sistema de ficheiros. O tamanho do bloco é indicado como 1 e a contagem de blocos representa o tamanho total da imagem ROMFS em bytes. Os blocos livres e os ficheiros livres são sempre 0 (sistema de ficheiros somente de leitura).
- VfsRom.chdir(path)
Muda de directório dentro do ROMFS. Apenas a raiz (
'/') é suportada; mudar para qualquer subdirectório lançaOSError(EOPNOTSUPP).
- VfsRom.getcwd()
Retorna o directório de trabalho actual dentro do ROMFS. Retorna sempre
'/'.
- vfs.rom_ioctl(op, ...)
Interface de baixo nível para aceder às partições de memória somente de leitura (ROM) do dispositivo.
As operações suportadas são:
vfs.rom_ioctl(1)– Retorna o número de partições ROM disponíveis.vfs.rom_ioctl(2, id)– Retorna a partição ROM com o índice id como um objectomemoryview. A memória pode ser lida mas não escrita directamente.vfs.rom_ioctl(3, id, length)– Prepara uma partição ROM para escrita. Apaga os primeiros length bytes da partição com índice id. Retorna o tamanho mínimo de escrita em bytes (o alinhamento necessário para escritas subsequentes).vfs.rom_ioctl(4, id, offset, buf)– Escreve buf (um objecto tipo bytes) na partição ROM com índice id no byte offset.vfs.rom_ioctl(5, id)– Conclui uma sequência de escrita na partição id (realiza qualquer finalização necessária após a escrita, como a limpeza de cache).
Estas operações são utilizadas internamente pelo
mpremotepara implementar imagens ROMFS. A maioria dos utilizadores não precisa de chamarvfs.rom_ioctl()directamente.Exemplo (consultar partições disponíveis):
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")
Montagem automática no arranque¶
Quando o suporte ROMFS está activado no firmware, o MicroPython tentará automaticamente montar a primeira partição ROM em /rom durante a inicialização. Se a partição contiver uma imagem ROMFS válida, esta é montada e tanto /rom como /rom/lib são adicionados ao sys.path automaticamente.
Isto significa que após implementar uma imagem ROMFS com mpremote, uma reinicialização suave é suficiente para tornar os novos módulos importáveis.
Se não for encontrada uma imagem ROMFS válida na partição (p.ex. numa placa recém-programada), a montagem é silenciosamente ignorada.
Utilizar o mpremote para gerir ROMFS¶
A ferramenta mpremote fornece três sub-comandos para gerir imagens ROMFS num dispositivo ligado.
romfs query¶
$ mpremote romfs query
Lista todas as partições ROMFS disponíveis no dispositivo e os seus tamanhos. Mostra também os primeiros 12 bytes de cada partição em hexadecimal e indica se está presente uma imagem ROMFS válida.
Exemplo de saída:
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>
Constrói uma imagem ROMFS a partir do directório source no PC anfitrião. A imagem é escrita em output (predefinição: <source>.romfs).
Opções:
-o <output>,--output <output>: Especifica o caminho do ficheiro de saída.-m,--mpy(predefinição): Compila automaticamente ficheiros.pypara.mpyutilizandompy_crossantes de os adicionar à imagem. Requer o pacote Pythonmpy_cross(pip install mpy_cross).--no-mpy: Desactiva a compilação automática de ficheiros.py.
Exemplo:
$ 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>
Implementa uma imagem ROMFS no dispositivo. source pode ser:
Um directório no anfitrião: a imagem ROMFS é construída em memória e implementada directamente.
Um ficheiro
.romfsou.img: a imagem é lida do disco e implementada.
Opções:
-p <partition>,--partition <partition>: Especifica o índice da partição de destino (predefinição:0).-m,--mpy(predefinição): Compila.pypara.mpyquando source é um directório.--no-mpy: Desactiva a compilação automática de ficheiros.py.
Após a implementação, o dispositivo deve ser reiniciado de forma suave para que o novo ROMFS seja montado em /rom.
Exemplo:
$ 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
Exemplos¶
Implementar uma aplicação simples¶
Suponha que tem um directório de projecto myapp/ com a seguinte estrutura:
myapp/
main.py
utils.py
lib/
helper.py
Para implementá-lo no ROMFS do dispositivo:
$ mpremote romfs deploy myapp/
Após uma reinicialização suave, os módulos são importáveis a partir do ROMFS:
import main
import utils
from lib import helper
Listar conteúdos do ROMFS a partir de Python¶
Após a montagem, os conteúdos do ROMFS podem ser explorados como qualquer outro sistema de ficheiros:
import os
for entry in os.ilistdir('/rom'):
print(entry)
# Or simply:
print(os.listdir('/rom'))
O OpenMV também inclui um pequeno utilitário romfs que imprime uma listagem formatada incluindo o endereço mapeado em memória e o alinhamento de cada ficheiro:
from omv import romfs
romfs.ls_romfs()
Aninhar um ROMFS dentro de um ROMFS¶
Uma imagem ROMFS armazenada como ficheiro dentro de um ROMFS externo pode ser montada como um sistema de ficheiros aninhado. Por exemplo, se /rom/inner.romfs existir. Como /rom é um ROMFS, os objectos de ficheiro abertos a partir dele suportam o protocolo de buffer, pelo que se pode obter directamente uma memoryview sem cópia:
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 imagem ROMFS¶
O formato de imagem ROMFS é um formato binário compacto concebido para acesso mapeado em memória em microcontroladores. Uma breve descrição:
A imagem começa com os bytes mágicos
0xd2 0xcd 0x31(codificados como"RM1"com os bits mais significativos dos dois primeiros bytes definidos).O resto da imagem é composto por registos, cada um com uma etiqueta de tipo (varuint), um comprimento (varuint) e uma carga útil.
Os tipos de registo incluem: preenchimento, dados literais, ponteiro de dados indirecto, directório, ficheiro.
Os nomes de directório e de ficheiro são armazenados como strings de bytes prefixadas com comprimento.
Os dados de ficheiro podem ser armazenados literalmente (inline) ou através de um ponteiro indirecto para outro local na imagem, o que permite o alinhamento para acesso mapeado em memória.
Os tipos de registo desconhecidos são silenciosamente ignorados, garantindo compatibilidade futura.
Este formato está definido em extmod/vfs_rom.c no código-fonte do MicroPython. A implementação Python utilizada pelo mpremote para construir imagens encontra-se em tools/mpremote/mpremote/romfs.py.
Veja também
Trabalhar com sistemas de ficheiros – Visão geral do VFS do MicroPython e dos tipos de sistemas de ficheiros disponíveis.
Ficheiros de manifesto MicroPython – Como congelar módulos Python no firmware.
Ficheiros .mpy do MicroPython – Formato de ficheiro binário .mpy do MicroPython.
Controlo remoto do MicroPython: mpremote – A referência completa do comando mpremote.
romfs – Utilitário OpenMV para inspecionar o sistema de ficheiros /rom montado.