MicroPython-manifestitiedostot

Yhteenveto

MicroPythonissa on ominaisuus, jonka avulla Python-koodi voidaan ”jäädyttää” laiteohjelmistoon vaihtoehtona koodin lataamiselle tiedostojärjestelmästä.

Tällä on seuraavat hyödyt:

  • koodi on esikäännetty tavukoodiksi, joten Python-lähdekoodia ei tarvitse kääntää lataushetkellä.

  • tavukoodi voidaan suorittaa suoraan ROM-muistista (eli flash-muistista) sen sijaan, että se kopioitaisiin RAM-muistiin. Vastaavasti myös vakio-objektit (merkkijonot, monikot jne.) ladataan ROM-muistista. Tämä voi tarjota huomattavasti enemmän muistia sovelluksesi käyttöön.

  • laitteilla, joissa ei ole tiedostojärjestelmää, tämä on ainoa tapa ladata Python-koodia.

Kehitysvaiheessa jäädyttämistä ei yleensä suositella, koska se hidastaa merkittävästi kehityssykliäsi: jokainen päivitys edellyttää koko laiteohjelmiston uudelleenflashaamista. Silti voi olla hyödyllistä jäädyttää valikoivasti joitakin harvoin muuttuvia riippuvuuksia (kuten kolmannen osapuolen kirjastoja).

Tapa luetella laiteohjelmistoon jäädytettävät Python-tiedostot on ”manifesti”, joka on Python-tiedosto, jonka koontiprosessi tulkitsee. Tyypillisesti kirjoitat manifestitiedoston osana levyn määrittelyä, mutta voit myös kirjoittaa erillisen manifestitiedoston ja käyttää sitä olemassa olevan levyn määrittelyn kanssa.

Manifestitiedostot voivat määritellä riippuvuuksia micropython-lib-kirjastoihin sekä tiedostojärjestelmässä oleviin Python-tiedostoihin ja myös muihin manifestitiedostoihin.

Manifestitiedostojen kirjoittaminen

Manifestitiedosto on Python-tiedosto, joka sisältää sarjan funktiokutsuja. Katso alla määritellyt käytettävissä olevat funktiot.

Manifestitiedostoissa käytetyt polut voivat sisältää seuraavia muuttujia. Nämä kaikki muuntuvat absoluuttisiksi poluiksi.

  • $(MPY_DIR) – polku micropython-repositorioon.

  • $(MPY_LIB_DIR) – polku micropython-lib-alimoduuliin. Suosi require()-funktion käyttöä.

  • $(PORT_DIR) – polku nykyiseen porttiin (esim. ports/stm32)

  • $(BOARD_DIR) – polku nykyiseen levyyn (esim. ports/stm32/boards/OPENMV4)

Mukautettujen manifestitiedostojen ei tulisi sijaita pääasiallisessa MicroPython-repositoriossa. Säilytä ne versionhallinnassa muun projektisi kanssa.

Tyypillisesti laiteohjelmiston kääntämiseen käytetyn manifestin on sisällettävä portin manifesti, joka saattaa sisältää jäädytettyjä moduuleja, joita levy tarvitsee toimiakseen. Jos haluat vain lisätä uusia moduuleja olemassa olevaan levyyn, sisällytä levyn manifesti (joka puolestaan sisältää portin manifestin).

Kääntäminen mukautetulla manifestilla

Manifestisi voidaan määrittää make-komentorivillä seuraavasti:

$ make BOARD=MYBOARD FROZEN_MANIFEST=/path/to/my/project/manifest.py

Tämä koskee kaikkia portteja, mukaan lukien CMake-pohjaiset (esim. rp2), koska Makefile-kääre välittää tämän CMake-koontiin.

Manifestin lisääminen levyn määrittelyyn

Jos sinulla on mukautettu levyn määrittely, voit saada sen sisällyttämään mukautetun manifestisi automaattisesti. Make-pohjaisilla porteilla (useimmilla porteilla) aseta FROZEN_MANIFEST-muuttuja tiedostossa mpconfigboard.mk.

FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py

CMake-pohjaisilla porteilla (esim. rp2) käytä sen sijaan mpconfigboard.cmake-tiedostoa

set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)

Korkean tason funktiot

Näitä funktioita käytät tavallisesti. Ne lisäävät koodin joukkoon, joka esikäännetään tavukoodiksi ja jäädytetään laiteohjelmistokuvaan:

  • module ja package jäädyttävät oman paikallisen lähdekoodisi — vastaavasti yksittäisen tiedoston tai koko pakettihakemiston.

  • require jäädyttää julkaistun paketin (ja sen riippuvuudet) micropython-lib-kirjastosta nimen perusteella.

  • include vetää mukaan toisen manifestin, jolloin myös sen jäädytetyt moduulit lisätään.

  • add_library ja metadata ovat tukifunktioita (require-funktion ylimääräisten hakupolkujen rekisteröinti ja paketin metatietojen määrittely).

Tyypillinen laiteohjelmiston manifesti ensin includeaa portin tai levyn manifestin (jotta levyn tarvitsemat moduulit pysyvät jäädytettyinä), ja lisää sitten omat module/package/require-rivinsä.

Huomautus: opt-avainsana-argumentti voidaan asettaa eri funktioissa, ja se hallitsee ristikääntäjän käyttämää optimointitasoa. Katso micropython.opt_level().

add_library(library, library_path, prepend=False)

Rekisteröi polku ulkoiseen nimettyyn library-kirjastoon.

Käytä tätä, kun haluat require-funktion ratkaisevan paketteja muusta hakemistosta kuin micropython-lib-kirjastosta — esimerkiksi omasta ajurikokoelmastasi tai kolmannen osapuolen kirjaston haarauksesta.

Polkua library_path haetaan automaattisesti require-funktiota käytettäessä. Oletusarvoisesti lisätty kirjasto lisätään haettavien kirjastojen listan loppuun. Välitä True, jos haluat lisätä alkuun eli sijoittaa sen listan alkuun.

Lisäksi lisätty kirjasto voidaan pyytää nimenomaisesti käyttämällä require("name", library="library").

package(package_path, files=None, base_path='.', opt=None)

Jäädytä kokonainen paketti — hakemisto, jossa on .py-tiedostoja (valinnaisesti alipaketteineen) — niin että se voidaan tuoda muodossa import <package>. Käytä module-funktiota yksittäiselle erillistiedostolle.

Tämä vastaa ”package_path”-hakemiston kopioimista laitteeseen (paitsi jäädytettynä koodina).

Yksinkertaisimmassa tapauksessa, jäädyttääksesi paketin ”foo” nykyisessä hakemistossa:

package("foo")

sisällyttää rekursiivisesti kaikki foo-hakemiston .py-tiedostot, ja ne jäädytetään muodossa foo/**/*.py.

Jos paketti ei ole samassa hakemistossa kuin manifestitiedosto, käytä base_path:

package("foo", base_path="path/to/libraries")

Voit käyttää yllä mainittuja muuttujia, kuten $(PORT_DIR) parametrissa base_path.

Rajataksesi tiettyihin paketin tiedostoihin käytä files (huom.: polkujen tulee olla paketin suhteen suhteellisia): package("foo", files=["bar/baz.py"]).

module(module_path, base_path='.', opt=None)

Jäädytä yksittäinen erillinen .py-tiedosto niin että se voidaan tuoda nimellään (module("foo.py") saa import foo -kutsun toimimaan). Käytä package-funktiota hakemistolle/paketille.

Jos tiedosto on nykyisessä hakemistossa:

module("foo.py")

Muutoin käytä base_path-parametria tiedoston paikantamiseen:

module("foo.py", base_path="src/drivers")

Voit käyttää yllä mainittuja muuttujia, kuten $(PORT_DIR) parametrissa base_path.

require(name, library=None)

Vaadi paketti nimen perusteella (ja sen riippuvuudet) micropython-lib-kirjastosta.

Näin standardikirjaston laajennukset ja yhteisön ajurit jäädytetään mukaan: nimetty paketti haetaan micropython-lib-alimoduulista ja jäädytetään yhdessä kaiken sen riippuvan kanssa. Käytä module- tai package-funktiota sen sijaan, kun haluat jäädyttää omaa lähdekoodiasi julkaistun paketin sijaan.

Määritä valinnaisesti library (merkkijono) viitataksesi pakettiin kirjastosta, joka on aiemmin rekisteröity add_library-funktiolla. Muussa tapauksessa käytetään kirjastopolkujen listaa.

include(manifest_path)

Sisällytä toinen manifesti. Näin manifestit koostetaan: mukautetun laiteohjelmiston manifestin tulisi include-funktiolla sisällyttää portin (tai levyn) manifesti, jotta levyn tarvitsemat moduulit pysyvät jäädytettyinä, ja sitten lisätä omat merkintänsä.

Tyypillisesti laiteohjelmiston kääntämiseen käytetyn manifestin on sisällettävä portin manifesti, joka saattaa sisältää jäädytettyjä moduuleja, joita levy tarvitsee toimiakseen.

manifest-argumentti voi olla merkkijono (tiedostonimi) tai merkkijonojen iteroitava kokoelma.

Suhteelliset polut ratkaistaan suhteessa nykyiseen manifestitiedostoon.

Jos polku osoittaa hakemistoon, se sisältää implisiittisesti kyseisen hakemiston manifest.py-tiedoston.

Voit käyttää yllä mainittuja muuttujia, kuten $(PORT_DIR) parametrissa manifest_path.

metadata(description=None, version=None, license=None, author=None)

Määritä metatiedot tälle manifestitiedostolle. Tämä on hyödyllistä micropython-lib-pakettien manifesteille.

Näitä kenttiä käytetään, kun paketti julkaistaan tai asennetaan micropython-lib-kirjastosta mip -työkalun kautta; niitä ei tarvita levyn laiteohjelmiston manifestissa.

Matalan tason funktiot

Nämä funktiot on dokumentoitu täydellisyyden vuoksi, mutta freeze_as_str-funktiota lukuun ottamatta kaikki toiminnallisuus on käytettävissä korkean tason funktioiden kautta.

freeze*-funktiot eroavat toisistaan vain siinä, miten koodi tallennetaan:

  • freeze_as_mpy / freeze_mpy tallentavat esikäännetyn tavukoodin (.mpy) flash-muistiin. Koodi suoritetaan suoraan flash-muistista, käyttää minimaalisesti RAM-muistia ja tuodaan nopeasti. Tätä module, package ja require käyttävät sisäisesti.

  • freeze_as_str sen sijaan jäädyttää Python-lähdekoodin, joka käännetään tavukoodiksi tuontihetkellä (käyttäen RAM-muistia ja edellyttäen laitteen sisäistä kääntäjää). Tämä on ainoa ominaisuus, jota korkean tason funktiot eivät tarjoa, minkä vuoksi se on yllä mainittu poikkeus.

freeze(path, script=None, opt=0)

Perusprimitiivi, jonka päälle korkean tason funktiot rakentuvat; suosi niitä. Jäädytä path-parametrilla määritetty syöte määrittäen automaattisesti sen tyypin. .py-skripti käännetään ensin .mpy-tiedostoksi ja sitten jäädytetään, ja .mpy-tiedosto jäädytetään suoraan.

path-parametrin on oltava hakemisto, joka on perushakemisto, josta tiedostojen haku aloitetaan. Tuotaessa tuloksena syntyviä jäädytettyjä moduuleja moduulin nimi alkaa path-osan jälkeen, eli path jätetään pois moduulin nimestä.

Jos path on suhteellinen, se ratkaistaan suhteessa nykyiseen manifest.py-tiedostoon.

Jos script on None, kaikki path-hakemiston tiedostot jäädytetään.

Jos script on iteroitava, freeze() kutsutaan kaikille iteroitavan alkioille (samalla path- ja opt-arvolla välitettynä).

Jos script on merkkijono, se määrittää jäädytettävän tiedoston tai hakemiston, ja se voi sisältää ylimääräisiä hakemistoja ennen tiedostoa tai viimeistä hakemistoa. Tiedostoa tai hakemistoa haetaan path-osasta. Jos script on hakemisto, kaikki kyseisen hakemiston tiedostot jäädytetään.

opt on optimointitaso, joka välitetään mpy-cross-työkalulle käännettäessä .py-tiedostoja .mpy-tiedostoiksi. Nämä tasot on kuvattu kohdassa micropython.opt_level().

freeze_as_str(path)

Jäädytä annettu path ja kaikki sen sisältämät .py-skriptit merkkijonona, joka käännetään tuonnin yhteydessä. Käytä tätä vain, kun jäädytetyn koodin on pysyttävä Python-lähdekoodina; se kuluttaa tuontihetken RAM-muistia .mpy-vaihtoehtoihin verrattuna.

freeze_as_mpy(path, script=None, opt=0)

Jäädytä syöte kääntämällä ensin .py-skriptit .mpy-tiedostoiksi ja jäädyttämällä sitten tuloksena syntyvät .mpy-tiedostot. Tätä module ja package tekevät kulissien takana. Katso lisätietoja argumenteista kohdasta freeze().

freeze_mpy(path, script=None, opt=0)

Jäädytä syöte, jonka on oltava suoraan jäädytettäviä .mpy-tiedostoja (ei käännösvaihetta). Katso lisätietoja argumenteista kohdasta freeze().

Esimerkkejä

Jäädyttääksesi yksittäisen tiedoston nykyisestä hakemistosta, joka on käytettävissä muodossa import mydriver, käytä:

module("mydriver.py")

Jäädyttääksesi tiedostohakemiston nykyisen hakemiston alihakemistossa ”mydriver”, joka on käytettävissä muodossa import mydriver, käytä:

package("mydriver")

Jäädyttääksesi ”hmac”-kirjaston micropython-lib-kirjastosta, käytä:

require("hmac")

Täydellisempi esimerkki mukautetusta manifest.py-tiedostosta (levylle, jolla on oma oletusmanifesti) on:

# 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")

Tämän jälkeen levy voidaan kääntää komennolla

$ cd ports/stm32
$ make BOARD=MYBOARD FROZEN_MANIFEST=~/src/myproject/manifest.py

Huomaa, että useimmilla levyillä ei ole omaa manifest.py-tiedostoa, vaan ne käyttävät portin manifestia suoraan, jolloin manifestisi tulisi vain include("$(PORT_DIR)/boards/manifest.py") sen sijaan.