Робота з ROMFS¶
Огляд¶
ROMFS (Read-Only Memory Filesystem) — це легка файлова система лише для читання, розроблена для пристроїв MicroPython. Вона оптимізована для мікроконтролерів та вбудованих систем, де код і дані зберігаються у флеш-пам’яті та потребують ефективного доступу без копіювання в RAM.
Основні переваги ROMFS:
Імпорт без копіювання: файли байткоду
.mpy, що зберігаються у ROMFS, можуть виконуватися безпосередньо з флеш-пам’яті (з відображенням у пам’ять) без попереднього копіювання в RAM. Це схоже на те, як працюють заморожені модулі, проте не потребує повторного прошивання всієї мікропрограми.Мінімальне використання RAM: константні об’єкти (рядки, байти тощо) у файлах
.mpy, завантажених з ROMFS, посилаються безпосередньо на флеш-пам’ять, а не дублюються в RAM.Гнучке розгортання: образ ROMFS можна зібрати на хост-ПК та розгорнути на пристрої за допомогою mpremote без перебудови мікропрограми.
Стандартний інтерфейс файлової системи: ROMFS монтується у VFS та доступна через звичайні операції з файлами Python (
open,os.listdir,importтощо).
ROMFS доповнює як файлові системи FAT/LittleFS з доступом на читання та запис (що розташовані в інших розділах флеш-пам’яті), так і заморожені модулі (що компілюються безпосередньо у мікропрограму).
Підтримка плат¶
ROMFS увімкнена у мікропрограмі OpenMV на кожній платі камери, що має зарезервований розділ ROMFS у розкладці флеш-пам’яті. На таких платах розділ ROMFS автоматично визначається під час завантаження та монтується за адресою /rom; як /rom, так і /rom/lib додаються до sys.path, щоб модулі, що зберігаються там, можна було імпортувати безпосередньо.
Плата |
Підтримка ROMFS |
|---|---|
OpenMV Cam N6 |
Так |
OpenMV AE3 |
Так |
OpenMV Cam RT1062 |
Так |
OpenMV Cam Pure Thermal |
Так |
OpenMV Cam M4 / M7 / H7 / H7 Plus |
Так |
Arduino Giga |
Так |
Arduino Portenta H7 |
Так |
Arduino Nicla Vision |
Так |
Arduino Nano 33 BLE Sense |
Ні (немає розділу ROMFS) |
Arduino Nano RP2040 Connect |
Ні (немає розділу ROMFS) |
Дивіться romfs для OpenMV-специфічного допоміжного інструменту, що перевіряє змонтований ROMFS за адресою /rom.
Робочий процес¶
Типовий робочий процес використання ROMFS:
Створіть каталог на своєму ПК з файлами Python (або файлами
.mpy), які хочете розгорнути.Використайте
mpremote romfs deploy <directory>для побудови та розгортання образу ROMFS на пристрій.ROMFS буде змонтована за адресою
/romпісля наступного завантаження (або може бути змонтована негайно після перезавантаження пристрою).Код Python на пристрої зможе використовувати
importдля модулів з ROMFS так само, як з будь-якої іншої файлової системи.
Наприклад:
# On the host PC, with a directory "myapp/" containing app.py:
$ mpremote romfs deploy myapp/
Після м’якого скидання на пристрої буде доступний для імпорту файл /rom/app.py (або /rom/app.mpy, якщо встановлено mpy_cross).
Дивіться розділ підкоманди mpremote romfs нижче для отримання повних відомостей про підкоманди mpremote.
Python API¶
Python API для ROMFS надається через модуль vfs.
- class vfs.VfsRom(buffer)
Створює об’єкт файлової системи ROMFS з buffer, який має бути об’єктом, що підтримує буферний протокол (наприклад,
bytes,bytearrayабо об’єктmemoryview) і містить дійсний образ ROMFS.Конструктор перевіряє, що buffer починається з магічних байтів ROMFS (
b"\xd2\xcd\x31"). Якщо буфер занадто малий або не є дійсним ROMFS, виникає помилкаOSError(ENODEV).Об’єкти, створені цим конструктором, можна монтувати за допомогою
vfs.mount().Приклад:
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')
Або для монтування образу ROMFS, збереженого у файлі:
import vfs with open('/flash/app.romfs', 'rb') as f: romfs_data = f.read() fs = vfs.VfsRom(romfs_data) vfs.mount(fs, '/rom2')
Наступні методи доступні для об’єкта
VfsRom:- VfsRom.open(path, mode)
Відкриває файл з ROMFS. Підтримуються лише режими читання (
'','r','rt','rb'). Спроба відкрити файл для запису викличеOSError(EROFS).Повернений об’єкт файлу підтримує
read(),seek(),tell()таclose(). Для бінарних файлів, відкритих у режимі читання, повернений об’єкт також підтримує буферний протокол, тому можна отриматиmemoryviewданих файлу, що безпосередньо посилається на пам’ять ROMFS (без копіювання).
- VfsRom.ilistdir(path)
Повертає ітератор по записах у каталозі path. Кожен запис — це кортеж
(name, type, inode, size), де type має значення0x8000для файлу або0x4000для каталогу.
- VfsRom.stat(path)
Повертає 10-елементний кортеж, аналогічний
os.stat, для path. Виникає помилкаOSError(ENOENT), якщо шлях не існує.
- VfsRom.statvfs(path)
Повертає статистику файлової системи. Розмір блоку повідомляється як 1, а кількість блоків відображає загальний розмір образу ROMFS у байтах. Кількість вільних блоків і вільних файлів завжди дорівнює 0 (файлова система лише для читання).
- VfsRom.chdir(path)
Змінює каталог у межах ROMFS. Підтримується лише корінь (
'/'); спроба перейти до будь-якого підкаталогу викличеOSError(EOPNOTSUPP).
- VfsRom.getcwd()
Повертає поточний робочий каталог у межах ROMFS. Завжди повертає
'/'.
- vfs.rom_ioctl(op, ...)
Низькорівневий інтерфейс для доступу до розділу(ів) пам’яті лише для читання (ROM) пристрою.
Підтримуються такі операції:
vfs.rom_ioctl(1)– Повертає кількість доступних розділів ROM.vfs.rom_ioctl(2, id)– Повертає розділ ROM з індексом id як об’єктmemoryview. Пам’ять можна читати, але не записувати безпосередньо.vfs.rom_ioctl(3, id, length)– Підготовує розділ ROM до запису. Стирає перші length байтів розділу з індексом id. Повертає мінімальний розмір запису в байтах (вирівнювання, необхідне для наступних записів).vfs.rom_ioctl(4, id, offset, buf)– Записує buf (байтоподібний об’єкт) до розділу ROM з індексом id за байтовим зміщенням offset.vfs.rom_ioctl(5, id)– Завершує послідовність запису до розділу id (виконує будь-яке завершення після запису, наприклад скидання кешу).
Ці операції використовуються внутрішньо
mpremoteдля розгортання образів ROMFS. Більшості користувачів не потрібно безпосередньо викликатиvfs.rom_ioctl().Приклад (запит доступних розділів):
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")
Автоматичне монтування під час завантаження¶
Коли підтримку ROMFS увімкнено у мікропрограмі, MicroPython автоматично намагається змонтувати перший розділ ROM за адресою /rom під час ініціалізації. Якщо розділ містить дійсний образ ROMFS, він монтується, і до sys.path автоматично додаються як /rom, так і /rom/lib.
Це означає, що після розгортання образу ROMFS за допомогою mpremote достатньо виконати м’яке скидання, щоб нові модулі стали доступними для імпорту.
Якщо в розділі не знайдено дійсного образу ROMFS (наприклад, на щойно прошитій платі), монтування мовчки пропускається.
Використання mpremote для керування ROMFS¶
Інструмент mpremote надає три підкоманди для керування образами ROMFS на підключеному пристрої.
romfs query¶
$ mpremote romfs query
Виводить список усіх доступних розділів ROMFS на пристрої та їхні розміри. Також відображає перші 12 байтів кожного розділу в шістнадцятковому вигляді та повідомляє, чи присутній дійсний образ ROMFS.
Приклад виводу:
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>
Будує образ ROMFS з каталогу source на хост-ПК. Образ записується до output (за замовчуванням: <source>.romfs).
Параметри:
-o <output>,--output <output>: Вказує шлях до вихідного файлу.-m,--mpy(за замовчуванням): Автоматично компілює файли.pyдо.mpyза допомогоюmpy_crossперед додаванням до образу. Вимагає пакет Pythonmpy_cross(pip install mpy_cross).--no-mpy: Вимикає автоматичну компіляцію файлів.py.
Приклад:
$ 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 на пристрій. source може бути:
Каталогом на хості: образ ROMFS будується в пам’яті та розгортається безпосередньо.
Файлом
.romfsабо.img: образ зчитується з диска та розгортається.
Параметри:
-p <partition>,--partition <partition>: Вказує індекс цільового розділу (за замовчуванням:0).-m,--mpy(за замовчуванням): Компілює.pyдо.mpy, якщо source є каталогом.--no-mpy: Вимикає автоматичну компіляцію файлів.py.
Після розгортання пристрій необхідно м’яко скинути, щоб нова ROMFS була змонтована за адресою /rom.
Приклад:
$ 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
Приклади¶
Розгортання простого застосунку¶
Припустимо, що у вас є каталог проєкту myapp/ з такою структурою:
myapp/
main.py
utils.py
lib/
helper.py
Щоб розгорнути його у ROMFS пристрою:
$ mpremote romfs deploy myapp/
Після м’якого скидання модулі стають доступними для імпорту з ROMFS:
import main
import utils
from lib import helper
Перегляд вмісту ROMFS з Python¶
Після монтування вміст ROMFS можна переглядати як і будь-яку іншу файлову систему:
import os
for entry in os.ilistdir('/rom'):
print(entry)
# Or simply:
print(os.listdir('/rom'))
OpenMV також постачається з невеликим допоміжним інструментом romfs, що виводить форматований список із зазначенням адреси відображення в пам’ять та вирівнювання кожного файлу:
from omv import romfs
romfs.ls_romfs()
Вкладення ROMFS всередину ROMFS¶
Образ ROMFS, збережений як файл у зовнішній ROMFS, може бути змонтований як вкладена файлова система. Наприклад, якщо існує /rom/inner.romfs. Оскільки /rom є ROMFS, файлові об’єкти, відкриті з неї, підтримують буферний протокол, тому memoryview без копіювання можна отримати безпосередньо:
import vfs
with open('/rom/inner.romfs', 'rb') as f:
inner = vfs.VfsRom(memoryview(f))
vfs.mount(inner, '/inner')
print(os.listdir('/inner'))
Формат образу ROMFS¶
Формат образу ROMFS — це компактний бінарний формат, розроблений для доступу з відображенням у пам’ять на мікроконтролерах. Короткий огляд:
Образ починається з магічних байтів
0xd2 0xcd 0x31(закодованих як"RM1"з встановленими старшими бітами двох перших байтів).Решта образу складається з записів, кожен з яких має тег типу (varuint), довжину (varuint) та корисне навантаження.
Типи записів включають: заповнення, дослівні дані, непрямий покажчик даних, каталог, файл.
Імена каталогів та файлів зберігаються як байтові рядки з префіксом довжини.
Дані файлу можуть зберігатися дослівно (вбудовано) або через непрямий покажчик на іншу частину образу, що забезпечує вирівнювання для доступу з відображенням у пам’ять.
Невідомі типи записів мовчки пропускаються, забезпечуючи сумісність з майбутніми версіями.
Цей формат визначено у extmod/vfs_rom.c у вихідному коді MicroPython. Реалізація Python, яку використовує mpremote для побудови образів, знаходиться у tools/mpremote/mpremote/romfs.py.
Дивись також
Робота з файловими системами – Огляд VFS MicroPython та доступних типів файлових систем.
Файли маніфестів MicroPython – Як заморожувати модулі Python у мікропрограму.
MicroPython .mpy файли – Формат бінарного файлу MicroPython .mpy.
Дистанційне керування MicroPython: mpremote – Повний довідник команд mpremote.
romfs – Допоміжний інструмент OpenMV для перевірки змонтованої файлової системи /rom.