14.2.2.2. Створення образу ROMFS¶
Образ ROMFS – це файлова система у флеш-пам’яті, доступна лише для читання, яку середовище виконання автоматично монтує в /rom. Вона вирішує проблему з ресурсами, порушену на попередній сторінці: файли моделей машинного навчання, таблиці міток, конфігурація JSON, шаблони зображень – усе, що застосунок відкриває та читає, але ніколи не записує – потрапляє у збірку без витрат на вбудовування у вигляді літералів Python.
Три речі роблять ROMFS правильним інструментом для ресурсів у готовому продукті:
Файлова система є частиною образу мікропрограми. Кінцеві користувачі не можуть видалити, редагувати або замінити жоден файл у
/rom.Файли в
/romдоступні безпосередньо. Споживачі на кшталт модуляml, що завантажує файл моделі, отримують пряме відображення флеш-пам’яті без копіювання в оперативну пам’ять – багатомегабайтна модель з/rom«завантажується» фактично безкоштовно, тоді як той самий файл з/sdcardчитається в оперативну пам’ять під час завантаження і залишається там протягом усього часу існування посилання. Звичайнийopen()+readкопіює за потребою: кожен викликread(n)копіюєnбайт з флеш-пам’яті в оперативну пам’ять у момент виклику, а голийread()запитує весь файл./romта/rom/libдодаються доsys.pathпри завантаженні. Пакети Python, розміщені в образі, можна імпортувати за іменем; місце виклику не потребує нічого особливого.
14.2.2.2.1. Створення образу¶
Образи ROMFS створюються, редагуються та прошиваються через IDE. Використовуйте IDE як основне джерело істини щодо вмісту кожного постачального розділу ROMFS.
Чому це важливо: файли моделей мають вимоги до вирівнювання, які завантажувач під час виконання перевіряє. Файли .tflite повинні бути доповнені до кратності 16 байт, а NPU мікросхеми N6 вимагає вирівнювання по 32 байти для скомпільованих моделей. IDE автоматично застосовує це доповнення під час запису образу. Інструменти, що обходять дерево вихідних файлів без застосування доповнення – зокрема mpremote romfs – створюють образ, який монтується без помилок, але моделі якого не спрацьовують при першому виклику інференсу.
Редактор ROMFS в IDE – це інтерактивний перегляд вмісту образу. Файли та папки можна додавати, перейменовувати та видаляти в пам’яті; збереження записує результат як файл .img, готовий до прошивки. Типова структура для застосунку, що постачається з моделлю разом із деякими ресурсами та пакетом Python, виглядає так:
model.tflite
labels.txt
config.json
templates/
calibration.jpg
lib/
mylib/
__init__.py
helpers.py
Порада
Як IDE, так і mpremote крос-компілюють файли .py у байткод .mpy під час включення до образу ROMFS, тому камера імпортує їх без витрат на синтаксичний аналіз під час завантаження. Вихідні файли в редакторі залишаються .py; образ містить .mpy.
Після прошивки образу дерево стає доступним з MicroPython за шляхом /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. Більша частина застосунку знаходиться в ROMFS¶
ROMFS – це правильне місце для майже всього, що постачається з застосунком: бібліотеки, які він імпортує, файли моделей, які він завантажує, конфігурація, яку він читає, будь-який ресурс, вихід якого отримано з інструменту збирання, що генерує дерево файлів (конвертери моделей, конвеєри зображень, пакувальники ресурсів), і – що важливо – сам код застосунку.
Частина заморожених модулів повинна залишатися невеликою: boot.py для налаштування перед REPL, main.py як тонка точка входу, і лише ті бібліотеки, без яких камера справді не може завантажитись. Все інше переходить до ROMFS, де ітерування – це збереження нового .img з IDE та перепрошивка – без необхідності перебирати мікропрограму, без наявного набору інструментів для цього.
Патерн, що з цього виходить, – це main.py, який нічого не робить, крім делегування до застосунку в ROMFS:
# main.py (frozen)
import app
app.run()
# /rom/app/__init__.py (in ROMFS)
def run():
...
Зміна в app – це редагування ROMFS та перепрошивка. Збірка мікропрограми залишається незмінною протягом усього терміну служби продукту, якщо щось у замороженій частині справді не потребує змін.