MicroPython manifest fájlok¶
Összefoglaló¶
A MicroPython rendelkezik egy olyan funkcióval, amely lehetővé teszi, hogy a Python kódot „befagyasszuk” a firmware-be, alternatívaként a kód fájlrendszerből történő betöltéséhez képest.
Ennek a következő előnyei vannak:
a kód előre bájtkóddá van fordítva, így nincs szükség a Python forrás betöltéskori fordítására.
a bájtkód közvetlenül a ROM-ból (azaz a flash memóriából) futtatható ahelyett, hogy a RAM-ba másolnánk. Hasonlóképpen minden konstans objektum (sztringek, tuple-ök stb.) is a ROM-ból töltődik be. Ez jelentősen több memóriát tehet elérhetővé az alkalmazásod számára.
olyan eszközökön, amelyeken nincs fájlrendszer, ez az egyetlen módja a Python kód betöltésének.
A fejlesztés során a befagyasztás általában nem ajánlott, mivel jelentősen lelassítja a fejlesztési ciklust, hiszen minden egyes frissítés a teljes firmware újraflashelését igényli. Ennek ellenére hasznos lehet bizonyos, ritkán változó függőségek (például harmadik féltől származó könyvtárak) szelektív befagyasztása.
A firmware-be befagyasztandó Python fájlok felsorolásának módja egy „manifest”, amely egy Python fájl, amelyet az építési folyamat értelmez. Jellemzően egy manifest fájlt egy lap definíciójának részeként írnál, de írhatsz önálló manifest fájlt is, és használhatod azt egy meglévő lap definícióval.
A manifest fájlok meghatározhatnak függőségeket a micropython-lib könyvtáraira, valamint a fájlrendszeren lévő Python fájlokra, és más manifest fájlokra is.
Manifest fájlok írása¶
A manifest fájl egy Python fájl, amely függvényhívások sorozatát tartalmazza. Lásd az alább definiált elérhető függvényeket.
A manifest fájlokban használt bármely útvonal tartalmazhatja a következő változókat. Ezek mind abszolút útvonalakra oldódnak fel.
$(MPY_DIR)– a micropython repó útvonala.$(MPY_LIB_DIR)– a micropython-lib almodul útvonala. Inkább arequire()használatát részesítsd előnyben.$(PORT_DIR)– az aktuális port útvonala (pl.ports/stm32)$(BOARD_DIR)– az aktuális lap útvonala (pl.ports/stm32/boards/OPENMV4)
Az egyéni manifest fájlok ne a fő MicroPython repóban legyenek. A projekted többi részével együtt verziókövetésben kell tartanod őket.
A firmware fordításához használt manifest jellemzően tartalmaznia kell a port manifestet, amely olyan befagyasztott modulokat foglalhat magában, amelyek a lap működéséhez szükségesek. Ha csak további modulokat szeretnél hozzáadni egy meglévő laphoz, akkor a lap manifestjét vond be (amely viszont magában foglalja a port manifestet).
Fordítás egyéni manifesttel¶
A manifested a make parancssorban a következővel adhatod meg:
$ make BOARD=MYBOARD FROZEN_MANIFEST=/path/to/my/project/manifest.py
Ez minden portra vonatkozik, beleértve a CMake-alapúakat is (pl. rp2), mivel a Makefile-burkoló ezt továbbítja a CMake buildbe.
Manifest hozzáadása egy lap definícióhoz¶
Ha van egyéni lap definíciód, beállíthatod, hogy automatikusan tartalmazza az egyéni manifestedet. A make-alapú portokon (a legtöbb porton) a mpconfigboard.mk fájlban állítsd be a FROZEN_MANIFEST változót.
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
A CMake-alapú portokon (pl. rp2) ehelyett az mpconfigboard.cmake fájlt használd
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
Magas szintű függvények¶
Ezek azok a függvények, amelyeket általában használni fogsz. Ezek kódot adnak ahhoz a halmazhoz, amely előre bájtkóddá van fordítva és befagyasztva a firmware-képbe:
A
moduleés apackagea saját helyi forrásodat fagyasztja be — egyetlen fájlt, illetve egy egész csomagkönyvtárat.A
requireegy közzétett csomagot (és annak függőségeit) fagyaszt be a micropython-lib-ből, név szerint.Az
includeegy másik manifestet húz be, így annak befagyasztott moduljai is hozzáadódnak.Az
add_libraryés ametadatatámogató függvények (extra keresési útvonalak regisztrálása arequireszámára, illetve csomag-metaadatok deklarálása).
Egy tipikus firmware manifest először include-olja a port vagy lap manifestjét (így a lapnak szükséges modulok befagyasztva maradnak), majd hozzáadja a saját module/package/require sorait.
Megjegyzés: Az opt kulcsszó argumentum a különböző függvényeken beállítható, ez vezérli a keresztfordító által használt optimalizálási szintet. Lásd: micropython.opt_level().
- add_library(library, library_path, prepend=False)¶
Regisztrálja egy külső, megnevezett library útvonalát.
Akkor használd ezt, amikor azt szeretnéd, hogy a
requirea micropython-lib-től eltérő könyvtárból oldja fel a csomagokat — például a saját illesztőprogram-gyűjteményedből vagy egy harmadik féltől származó könyvtár checkout-jából.A library_path útvonal automatikusan kerül átkutatásra a
requirehasználatakor. Alapértelmezés szerint a hozzáadott könyvtár a keresendő könyvtárak listájának végére kerül. Adj átTrueértéket, hogy a lista elejére fűzd, és így a lista elejére kerüljön.Ezenkívül a hozzáadott könyvtár kifejezetten kérhető a
require("name", library="library")használatával.
- package(package_path, files=None, base_path='.', opt=None)¶
Befagyaszt egy egész csomagot — egy
.pyfájlokat tartalmazó könyvtárat (opcionálisan alcsomagokkal) — hogy azimport <package>módon importálható legyen. Egyetlen önálló fájlhoz használd helyette amodulefüggvényt.Ez egyenértékű a „package_path” könyvtár eszközre másolásával (azzal a különbséggel, hogy befagyasztott kódként).
A legegyszerűbb esetben egy „foo” csomag befagyasztásához az aktuális könyvtárban:
package("foo")rekurzívan beemeli az összes .py fájlt a foo-ból, és
foo/**/*.pynéven lesz befagyasztva.Ha a csomag nem ugyanabban a könyvtárban van, mint a manifest fájl, használd a
base_path-t:package("foo", base_path="path/to/libraries")Használhatod a fenti változókat, például a
$(PORT_DIR)-t abase_path-ban.Ha bizonyos fájlokra szeretnéd korlátozni a csomagban, használd a
files-t (megjegyzés: az útvonalaknak a csomaghoz képest relatívnak kell lenniük):package("foo", files=["bar/baz.py"]).
- module(module_path, base_path='.', opt=None)¶
Befagyaszt egyetlen önálló
.pyfájlt, hogy a nevén importálható legyen (amodule("foo.py")azimport foo-t teszi működőképessé). Könyvtárhoz/csomaghoz használd apackagefüggvényt.Ha a fájl az aktuális könyvtárban van:
module("foo.py")Egyébként a fájl megtalálásához használd a base_path-t:
module("foo.py", base_path="src/drivers")Használhatod a fenti változókat, például a
$(PORT_DIR)-t abase_path-ban.
- require(name, library=None)¶
Megkövetel egy csomagot név szerint (és annak függőségeit) a micropython-lib-ből.
Így kerülnek befagyasztásra a standard könyvtári kiterjesztések és a közösségi illesztőprogramok: a megnevezett csomag a micropython-lib almodulból kerül lehívásra, és mindennel együtt befagyasztásra kerül, amitől függ. A saját forrásod befagyasztásához egy közzétett csomag helyett használd a
modulevagy apackagefüggvényt.Opcionálisan add meg a library-t (egy sztringet), hogy egy korábban az
add_libraryfüggvénnyel regisztrált könyvtárból hivatkozz egy csomagra. Egyébként a könyvtár-útvonalak listája lesz használva.
- include(manifest_path)¶
Beemel egy másik manifestet. Így állnak össze a manifestek: egy egyéni firmware manifestnek
include-olnia kell a port (vagy lap) manifestjét, hogy a lapnak szükséges modulok befagyasztva maradjanak, majd hozzá kell adnia a saját bejegyzéseit.A firmware fordításához használt manifest jellemzően tartalmaznia kell a port manifestet, amely olyan befagyasztott modulokat foglalhat magában, amelyek a lap működéséhez szükségesek.
A manifest argumentum lehet egy sztring (fájlnév) vagy sztringek iterálható gyűjteménye.
A relatív útvonalak az aktuális manifest fájlhoz képest oldódnak fel.
Ha az útvonal egy könyvtárra mutat, akkor implicit módon az adott könyvtáron belüli manifest.py fájlt foglalja magában.
Használhatod a fenti változókat, például a
$(PORT_DIR)-t amanifest_path-ban.
- metadata(description=None, version=None, license=None, author=None)¶
Metaadatokat definiál ehhez a manifest fájlhoz. Ez a micropython-lib csomagokhoz tartozó manifestek esetén hasznos.
Ezeket a mezőket akkor használja a rendszer, amikor egy csomagot közzétesznek a micropython-lib-be / telepítenek onnan a mip segítségével; ezekre nincs szükség egy lap firmware manifestjében.
Alacsony szintű függvények¶
Ezek a függvények a teljesség kedvéért vannak dokumentálva, de a freeze_as_str kivételével minden funkció elérhető a magas szintű függvényeken keresztül.
A freeze* függvények csak abban különböznek, hogy hogyan tárolódik a kód:
A
freeze_as_mpy/freeze_mpyelőre fordított bájtkódot (.mpy) tárol a flash memóriában. A kód közvetlenül a flash memóriából fut, minimális RAM-ot használ, és gyorsan importálódik. Ezt használja belsőleg amodule, apackageés arequire.A
freeze_as_strezzel szemben a Python forrást fagyasztja be, amely importáláskor kerül bájtkóddá fordításra (RAM-ot használva, és az eszközön lévő fordítót igényelve). Ez az egyetlen képesség, amelyet a magas szintű függvények nem tesznek elérhetővé, ezért szerepel a fent említett kivételként.
- freeze(path, script=None, opt=0)¶
Az alapprimitív, amelyre a magas szintű függvények épülnek; inkább azokat részesítsd előnyben. Befagyasztja a path által megadott bemenetet, automatikusan meghatározva annak típusát. Egy
.pyszkript előbb.mpy-vé lesz fordítva, majd befagyasztva, egy.mpyfájl pedig közvetlenül befagyasztva.A path-nak könyvtárnak kell lennie, amely a fájlok keresésének kiindulási alapkönyvtára. A létrejövő befagyasztott modulok importálásakor a modul neve a path után kezdődik, azaz a path ki van zárva a modul nevéből.
Ha a path relatív, akkor az aktuális
manifest.py-hoz képest oldódik fel.Ha a script None, akkor a path összes fájlja befagyasztásra kerül.
Ha a script egy iterálható gyűjtemény, akkor a
freeze()az iterálható gyűjtemény összes elemén meghívásra kerül (ugyanazzal a path-szal és opt-tal átadva).Ha a script egy sztring, akkor a befagyasztandó fájlt vagy könyvtárat adja meg, és tartalmazhat extra könyvtárakat a fájl vagy az utolsó könyvtár előtt. A fájl vagy könyvtár a path-ban lesz keresve. Ha a script egy könyvtár, akkor az adott könyvtár összes fájlja befagyasztásra kerül.
Az opt az az optimalizálási szint, amelyet a mpy-cross-nak kell átadni a
.py.mpy-vé fordításakor. Ezeket a szinteket amicropython.opt_level()ismerteti.
- freeze_as_str(path)¶
Befagyasztja a megadott path-ot és az abban lévő összes
.pyszkriptet sztringként, amely importáláskor kerül lefordításra. Csak akkor használd ezt, ha a befagyasztott kódnak Python forrásnak kell maradnia; a.mpyváltozatokhoz képest importáláskori RAM-ba kerül.
- freeze_as_mpy(path, script=None, opt=0)¶
Befagyasztja a bemenetet úgy, hogy először a
.pyszkripteket.mpyfájlokká fordítja, majd befagyasztja a létrejövő.mpyfájlokat. Ezt teszi a háttérben amoduleés apackage. Az argumentumokkal kapcsolatos további részletekért lásd afreeze()-t.
- freeze_mpy(path, script=None, opt=0)¶
Befagyasztja a bemenetet, amelynek
.mpyfájloknak kell lenniük, amelyek közvetlenül kerülnek befagyasztásra (fordítási lépés nélkül). Az argumentumokkal kapcsolatos további részletekért lásd afreeze()-t.
Példák¶
Egyetlen fájl befagyasztásához az aktuális könyvtárból, amely import mydriver módon lesz elérhető, használd:
module("mydriver.py")
Egy fájlokat tartalmazó könyvtár befagyasztásához az aktuális könyvtár „mydriver” alkönyvtárában, amely import mydriver módon lesz elérhető, használd:
package("mydriver")
A „hmac” könyvtár befagyasztásához a micropython-lib-ből, használd:
require("hmac")
Egy egyéni manifest.py fájl teljesebb példája (egy olyan laphoz, amelynek saját alapértelmezett manifestje van):
# Include the board's default manifest.
include("$(BOARD_DIR)/manifest.py")
# Add a custom driver
module("mydriver.py")
# Add aiorepl from micropython-lib
require("aiorepl")
Ekkor a lap a következővel fordítható
$ cd ports/stm32
$ make BOARD=MYBOARD FROZEN_MANIFEST=~/src/myproject/manifest.py
Vedd figyelembe, hogy a legtöbb lapnak nincs saját manifest.py-ja, hanem közvetlenül a port-félét használja, mely esetben a manifestednek csak include("$(PORT_DIR)/boards/manifest.py")-t kell tartalmaznia helyette.