14.2.2.1. Szkriptek befagyasztása a firmware-be¶
A befagyasztott (frozen) modul olyan .py fájl, amelyet bájtkóddá fordítanak, és build-időben a firmware-képbe linkelnek. A futtatókörnyezet a befagyasztott modult közvetlenül a flash memóriából importálja, anélkül hogy egyáltalán megnézné a lemezen lévő fájlrendszert. Egy szállított termék esetén ez a megfelelő hely az alkalmazás kódjának: a végfelhasználónak nincs mit törölnie, nincs olyan elavult .py az SD-kártyán, amely felülírhatná, és a kamera minden indításkor ugyanazt a kódot futtatja, függetlenül attól, hogy mi van (ha van egyáltalán) a meghajtóin.
Ez az oldal bemutatja a kamera által követett indítási sorrendet, majd azt, hogy a manifest.py és a freeze direktíva hogyan süti bele az alkalmazást a buildbe.
14.2.2.1.1. Az indítási sorrend¶
Mi fut, és mikor, egy reset után induló kamerán:
A rendszerbetöltő. A bekapcsoláskor egy rövid DFU-ablakba lép, amelyet az IDE a firmware-frissítések feltöltésére használ. Az ablak néhány másodperc után bezárul, és a rendszerbetöltő átadja a vezérlést a MicroPythonnak. Egy futó szkript igény szerint újra beléphet ebbe az ablakba a
machine.bootloader()hívásával.Befagyasztott fájlrendszer inicializálása. Mielőtt bármilyen alkalmazáskód futna, a futtatókörnyezet elindítja a fájlrendszereket. A belső flash memória a
/flashponton csatolódik (és üresre formázódik, ha nincs ott semmi). Ha SD-kártya van jelen, és a belső flash memórián nem létezikSKIPSDnevű jelölőfájl, akkor az SD-kártya a/sdcardponton csatolódik. A ROMFS, ha a build tartalmazza, automatikusan a/romponton csatolódik. A munkakönyvtár az indítási könyvtárra áll be (/sdcard, ha a kártya csatolódott, egyébként/flash), asys.pathpedig a/flash,/flash/lib,/sdcard,/sdcard/lib,/romés/rom/libelemekkel töltődik fel. A flash memóriában lévő beállítást egy_boot.pynevű befagyasztott modul kezeli – ez port- és kártyainfrastruktúra, nem alkalmazás-horog. Az alkalmazások nem testreszabják a_boot.pyfájlt; ezt a build teszi. ASKIPSDfájl flash memóriára ejtése az IDE-ből a támogatott módja annak, hogy a kamera az SD-kártya helyett a belső flash memóriáról induljon.REPL előtti beállítás. A
boot.pyminden szoftveres resetkor lefut – hidegindítás,Ctrl-Da REPL-ből, a futó szkript visszatérése és watchdog-helyreállítás esetén – mielőtt a REPL elérhetővé válik. Feladata, hogy előkészítse azt a környezetet, amelyben a rendszer többi része fut: az a fajta beállítás, amelyre a REPL-nek, az alkalmazásnak és bármely helyreállító eszköznek egyaránt szüksége van a működéshez. Nem itt él maga az alkalmazás. Amain.pyaz alkalmazás belépési pontja.Fő ciklus. A
main.pyaz alkalmazás fő ciklusa. Hidegindításkor egyszer fut le, közvetlenül aboot.pyután. A későbbi szoftveres reseteknél nem fut le újra – a kamera helyette a REPL-be kerül. Ez az aszimmetria a fejlesztés szempontjából számít (egy Ctrl-D a REPL-be visz a ciklus újrafuttatása nélkül, így a fejlesztő megvizsgálhatja az állapotot), de a produkció szempontjából nem: egy terepen lévő kamera bekapcsolást, watchdogot és kemény reseteket lát, amelyek mind hardveres resetek, és ezek újra belépnek a hidegindítási útvonalba, és ismét lefuttatják amain.pyfájlt.
14.2.2.1.2. Befagyasztás a firmware-be¶
Egy kártya befagyasztott modulkészletét a firmware-fában lévő boards/<TARGET>/manifest.py fájl deklarálja. A manifest egy kis Python-fájl, amely néhány direktívát hív meg:
freeze("$(OMV_LIB_DIR)/", "foo.py")– egyetlenfoo.pyfájlt süt bele a buildbe.package("mylib", base_path="...")– egy több fájlból álló Python-csomagot süt bele, megőrizve annak könyvtárszerkezetét a megadott alapútvonal alatt.include("...")– behúz egy másik manifest fájlt. A kártya-manifestek ezt használják a közös modulkészletek megosztására.require("logging")– név szerint behúz egy megnevezett upstreammicropython-libmodult.
Egy minimális alkalmazás-manifest top-szintű szkriptenként egy freeze sort, az alkalmazás által használt csomagonként pedig egy package sort ad hozzá.
14.2.2.1.2.1. Hol található a forrás¶
Az alkalmazás forrása a firmware-fában lévő scripts/libraries/ alatt található, azon modulok mellett, amelyeket a build már befagyaszt. A $(OMV_LIB_DIR) manifest-változó erre az útvonalra bővül ki, így a manifest bejegyzései rövidek maradnak. A manifest szerkesztése amúgy is fában belüli művelet, így a forrás fában tartása megspórolja egy külön projekt-repó zsonglőrködését az útvonalfeloldásnál.
Egy tipikus elrendezés olyan alkalmazáshoz, amely egyetlen main.py fájlt és egy kiegészítő csomagot szállít:
scripts/libraries/
main.py
my_lib/
__init__.py
helpers.py
A kártya boards/<TARGET>/manifest.py fájljában pedig egy freeze sor a szkripthez és egy package sor a csomaghoz:
freeze("$(OMV_LIB_DIR)/", "main.py")
package("my_lib", base_path="$(OMV_LIB_DIR)/my_lib")
Egyfájlos szkriptek – itt a main.py, de ugyanez a szabály vonatkozik a boot.py fájlra vagy bármely önálló segédfájlra – a freeze direktívát használják. A több fájlból álló csomagok a package direktívát használják. Egy újabb szkript hozzáadása egy újabb freeze sor; egy újabb csomag hozzáadása egy újabb package sor.
14.2.2.1.2.2. Buildelés és flashelés¶
Miután a manifest a helyén van, buildeld a firmware-t pontosan úgy, ahogyan a firmware fejezet leírja:
make -j$(nproc) -C lib/micropython/mpy-cross # once, builds the cross-compiler
make -j$(nproc) TARGET=<TARGET> # builds the firmware
A kimenet a build/<TARGET>/bin/ könyvtárba kerül:
build/<TARGET>/bin/
firmware.bin # flash through the IDE
romfs0.img # flash through the IDE in a separate step
A .bin és .img fájlok IDE-n keresztüli flashelése olyan kamerát eredményez, amelynek alkalmazása a build része.
A fenti indítási sorrend az, ami a belesütést hatékonnyá teszi: a futtatókörnyezet a boot.py és main.py fájlokat a befagyasztott példányokra oldja fel, mielőtt egyáltalán megnézné a fájlrendszert, így egy szállított kamera akkor is a build kódját futtatja, ha az SD-kártyán egy fejlesztésből ottmaradt, elavult boot.py található.
14.2.2.1.2.3. Keresési sorrend¶
A felülírási szemantika eltérő a boot.py / main.py végrehajtási útvonal és a közönséges import utasítások esetén. Annak ismerete, hogy melyik melyik, a produkció és a fejlesztés szempontjából is számít:
A
boot.pyésmain.pyesetén: a futtatókörnyezet először a befagyasztott példányt keresi, majd a fájlrendszert. Egy befagyasztottboot.pyfájlt nem lehet felülírni egy SD-kártyára ejtett másikkal – aki a kamerát birtokolja, nem tudja megváltoztatni a belépési pontot újraflashelés nélkül.Az
import fooesetén: a futtatókörnyezet először asys.pathútvonalat keresi – amely lefedi a/flash,/sdcard,/romkönyvtárakat és azoklibalkönyvtárait –, majd a befagyasztott modulokat. Egy flash memórián vagy SD-kártyán lévő, azonos nevűfoo.pyvalóban felülír egy befagyasztottfoomodult. Ez a fejlesztési könnyítés: ejts egy javított modult a kártyára, végezz szoftveres resetet, és lásd a változást újraflashelés nélkül.
Egy szállított termék, amely el akarja nyomni a fájlrendszer-felülírja-a-befagyasztottat viselkedést az importoknál, korán a boot.py fájlban kiürítheti a sys.path útvonalat:
import sys
sys.path.clear()
Ha a sys.path üres, minden import kizárólag a befagyasztott modulokból oldódik fel; semmi a flash memórián, az SD-kártyán vagy a ROMFS-en nem árnyékolhatja be őket.
14.2.2.1.2.4. Az eszköz-probléma¶
A befagyasztás kiváló a kódhoz. Nem kiváló viszont a nagy bináris eszközökhöz: gépi tanulási modellfájlokhoz, címketáblázatokhoz, JSON-konfigurációhoz, képsablonokhoz. Ezek Python-literálként való beágyazása felfújja a forrást, lassan fordul újra, és az adatokra pazarolja a bájtkód-tárolót, amelyeket az értelmező amúgy is csak nyersen fog beolvasni. A ROMFS-kép buildelése oldal bemutatja az ezt a hiányt betöltő, csak olvasható flash-fájlrendszert.