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 та перепрошивка. Збірка мікропрограми залишається незмінною протягом усього терміну служби продукту, якщо щось у замороженій частині справді не потребує змін.