Slijed resetiranja i pokretanja

Uređaj koji izvodi MicroPython slijedi određeni slijed pokretanja kako bi se pokrenuo i inicijalizirao nakon resetiranja.

Napomena

Slijed _boot.pyboot.pymain.py → REPL opisan u nastavku je ono što ugrađeni program (firmware) izvodi pri svakom resetiranju, bez obzira na to kako se povezujete — pa se stoga uvijek primjenjuje. Kada izvodite skriptu iz OpenMV IDE-a, IDE prekida trenutno pokrenuti main.py i umjesto njega izvodi skriptu otvorenu u uređivaču, putem vlastitog protokola za otklanjanje pogrešaka. Ne koristi REPL na uređaju (REPL), pa se reference specifične za REPL na ovoj stranici (interaktivni upit, Ctrl-D / Ctrl-C na serijskom terminalu itd.) odnose na samostalni rad i izravne sesije serijskog terminala — no sam slijed pokretanja primjenjuje se u svim slučajevima.

Tvrdo resetiranje

Pokretanje iz tvrdog resetiranja događa se kada se ploča prvi put uključi, hladno pokretanje. Ovo je potpuno resetiranje sklopovlja MCU-a.

Kod MicroPython porta inicijalizira sve osnovno sklopovlje (uključujući ugrađene satove i regulatore napajanja, interni serijski UART itd.), a zatim pokreće MicroPython okruženje. Postojeća RTC konfiguracija može biti zadržana nakon tvrdog resetiranja, ali svo ostalo stanje sklopovlja se briše.

Isti slijed pokretanja iz tvrdog resetiranja može pokrenuti niz događaja kao što su:

  • Python kod koji izvršava machine.reset().

  • Korisnik pritisne fizički gumb za resetiranje na ploči (gdje je to primjenjivo).

  • Buđenje iz dubokog mirovanja (na većini portova).

  • Resetiranje hardverskim nadzornim mehanizmom (watchdog) MCU-a.

  • Hardverski detektor pada napona (brown out) MCU-a.

Detalji okidača resetiranja specifičnih za sklopovlje ovise o portu i pripadajućem sklopovlju. Funkcija machine.reset_cause() može se koristiti za dodatno utvrđivanje uzroka resetiranja.

Meko resetiranje

Kada je MicroPython već pokrenut, moguće je pokrenuti meko resetiranje tipkanjem Ctrl-D u REPL-u ili izvršavanjem machine.soft_reset().

Meko resetiranje briše Python interpreter, oslobađa svu Python memoriju i ponovno pokreće MicroPython okruženje.

Stanje koje se briše mekim resetiranjem uključuje:

  • Sve Python varijable, objekte, uvezene module itd.

  • Većinu periferija konfiguriranih pomoću machine modula. Postoje vrlo ograničene iznimke, na primjer načini rada machine.Pin (tj. je li pin ulaz ili izlaz, visok ili nizak) ne resetiraju se na većini portova. Naprednija konfiguracija poput Pin.irq() uvijek se resetira.

  • Bluetooth.

  • Mrežne utičnice. Otvorene TCP utičnice uredno se zatvaraju u odnosu na drugu stranu.

  • Otvorene datoteke. Datotečni sustav ostaje u valjanom stanju.

Neka stanja sustava ostaju ista nakon mekog resetiranja, uključujući:

  • Sve postojeće mrežne veze (Ethernet, Wi-Fi itd.) ostaju aktivne na razini IP mreže. Ispitivanje mrežnog sučelja iz koda može pokazati da je mrežno sučelje još uvijek aktivno s konfiguriranom IP adresom itd.

  • Aktivan REPL izgleda neprekinuto prije i nakon mekog resetiranja, osim u nekim neuobičajenim slučajevima:

    • Serijski UART REPL vratit će svoju zadanu hardversku konfiguraciju (brzina prijenosa (baud) itd.).

  • Brzina takta procesora obično se ne mijenja mekim resetiranjem.

  • RTC konfiguracija (tj. postavljanje trenutnog vremena) ne mijenja se mekim resetiranjem.

Slijed pokretanja

Kada se MicroPython pokrene nakon tvrdog ili mekog resetiranja, slijedi ovaj slijed pokretanja redom:

_boot.py

Ovo je interna skripta zamrznuta u MicroPython ugrađeni program (firmware). Pruža je MicroPython na mnogim portovima radi obavljanja osnovne inicijalizacije.

Na primjer, na većini portova _boot.py će otkriti prvo pokretanje novog uređaja i formatirati interni flash datotečni sustav spreman za uporabu.

Osim ako ne stvarate prilagođenu MicroPython gradnju ili dodajete novi port, vjerojatno se ne morate brinuti o _boot.py. Najbolje je ne mijenjati sadržaj osim ako stvarno znate što radite.

boot.py

Datoteka pod nazivom boot.py može se kopirati na interni datotečni sustav ploče pomoću mpremote.

Ako se pronađe boot.py, on se izvršava. U boot.py možete dodati kod za izvođenje prilagođene jednokratne inicijalizacije (na primjer, za konfiguriranje sklopovlja ploče).

Uobičajena praksa je konfiguriranje mrežne veze ploče u boot.py tako da je uvijek dostupna nakon resetiranja za uporabu s REPL, mpremote itd.

Upozorenje

boot.py bi se uvijek trebao završiti i ne smije se izvoditi neograničeno.

Ovisno o ploči, dio inicijalizacije sklopovlja odgađa se dok se ne završi boot.py. To uključuje inicijalizaciju USB-a na OpenMV Cam uređajima temeljenim na STM32. Na tim pločama, ispis ispisan iz boot.py možda neće biti vidljiv na ugrađenom USB serijskom priključku dok boot.py ne završi s izvođenjem.

Svrha ove odgođene inicijalizacije je omogućiti unaprijed konfiguriranje određenog sklopovlja u boot.py, a zatim ga pokrenuti s ispravnom konfiguracijom.

Napomena

Ponekad je jednostavnije ne imati boot.py datoteku, već umjesto toga smjestiti bilo koji inicijalizacijski kod na vrh main.py.

main.py

Slično kao boot.py, datoteka pod nazivom main.py može se kopirati na interni datotečni sustav ploče. Ako se pronađe, ona se izvršava sljedeća u procesu pokretanja.

main.py je za bilo koji Python kod koji želite izvoditi svaki put kada se vaš uređaj pokrene.

Nekoliko savjeta za uporabu main.py:

  • main.py ne mora završiti, slobodno tamo stavite beskonačnu while True petlju.

  • Za složene Python aplikacije ne morate sav svoj kod stavljati u main.py. main.py može biti jednostavna ulazna točka koja uvozi vašu aplikaciju i pokreće izvođenje:

    import my_app
    my_app.main()
    

    Ovo može pomoći da struktura vaše aplikacije ostane jasna. Također olakšava instaliranje više aplikacija na ploču i prebacivanje između njih.

  • Dobra je praksa pri pisanju robusnih aplikacija omotati kod u main.py rukovateljem iznimaka kako bi se poduzela odgovarajuća radnja ako se kod sruši. Na primjer:

    import machine, sys
    import my_app
    try:
        my_app.main()
    except Exception as e:
        print("Fatal error in main:")
        sys.print_exception(e)
    
    # Following a normal Exception or main() exiting, reset the board.
    # Following a non-Exception error such as KeyboardInterrupt (Ctrl-C),
    # this code will drop to a REPL. Place machine.reset() in a finally
    # block to always reset, instead.
    machine.reset()
    

    U protivnom će MicroPython pasti u REPL nakon bilo kakvog rušenja ili ako se main završi (vidi u nastavku).

  • Sve globalne varijable koje su postavljene u boot.py i dalje će biti postavljene u globalnom kontekstu main.py.

  • Za potpunu optimizaciju uporabe flash memorije i potrošnje memorije, možete kopirati unaprijed kompilirane main.mpy i/ili boot.mpy datoteke u datotečni sustav, ili ih čak zamrznuti u gradnju ugrađenog programa (firmware).

  • Izvođenje main.py preskače se kada se meko resetiranje pokrene iz sirovog REPL načina rada (na primjer, kada mpremote ili neki drugi program izravno komunicira s MicroPythonom).

Interaktivni interpreter (REPL)

Ako se main.py ne pronađe ili ako se main.py završi, tada će se Interaktivni način rada interpretera MicroPython (poznat i kao REPL) odmah pokrenuti.

Napomena

Čak i ako main.py sadrži beskonačnu petlju, tipkanje Ctrl-C na serijskom priključku REPL-a ubacit će KeyboardInterrupt. Ako ga nijedan rukovatelj iznimaka ne uhvati, tada će se main.py završiti i pokrenut će se REPL.

Sve globalne varijable koje su postavljene u boot.py i main.py i dalje će biti postavljene u globalnom kontekstu REPL-a.

REPL nastavlja s izvođenjem dok Python kod ne pokrene tvrdo ili meko resetiranje.

Meko zaglavljivanje (neuspjeh pokretanja)

Rijetko je, ali moguće, da MicroPython postane neodgovaran tijekom pokretanja, stanje koje se ponekad naziva „meko zaglavljen” (soft bricked). Na primjer:

  • Ako se izvođenje boot.py zaglavi i izvorni USB serijski priključak se nikada ne inicijalizira.

  • Ako Python kod ponovno konfigurira REPL sučelje, čineći ga nedostupnim.

Budite bez brige, oporavak je moguć!

Ako koristite OpenMV IDE, jednostavno povezivanje često je dovoljno — IDE zaustavlja pokrenuti main.py i preuzima kontrolu. Ako se kamera uopće ne želi povezati, upotrijebite Factory Reset u nastavku. Metoda Ctrl-C opisana sljedeća namijenjena je izravnim sesijama serijskog terminala — oslanja se na REPL na uređaju, koji OpenMV IDE ne koristi.

KeyboardInterrupt

U mnogim slučajevima, otvaranje serijskog priključka REPL-a i tipkanje Ctrl-C ubacit će KeyboardInterrupt i može uzrokovati završetak pokrenute skripte i pokretanje REPL-a. Iz REPL-a možete koristiti os.remove() za uklanjanje neispravne Python datoteke:

import os
os.remove('main.py')

Za potvrdu koje su datoteke još uvijek prisutne u internom datotečnom sustavu:

import os
os.listdir()

Factory Reset

Ako ne možete doći do REPL-a pomoću gornje metode, preostala opcija je tvorničko resetiranje: brisanje cjelokupnog sadržaja internog flash datotečnog sustava. Ovo je također rješenje ako se interni datotečni sustav oštetio.

OpenMV IDE ima nekoliko ugrađenih načina za to. Prvo postavite kameru u njezin način oporavka/pokretača (bootloader) — metoda se razlikuje ovisno o ploči, pa pogledajte odjeljak Recovery and debug pins u brzom pregledu vaše ploče za upute kako u njega ući. Zatim kliknite gumb za povezivanje u OpenMV IDE-u i slijedite upute za brisanje datotečnog sustava i ponovno upisivanje ugrađenog programa (firmware).

Upozorenje

Ponovno upisivanje ugrađenog programa (firmware) bez brisanja datotečnog sustava obično neće riješiti meko zaglavljivanje, jer normalno ažuriranje ugrađenog programa čuva sadržaj datotečnog sustava. Obavezno odaberite opciju brisanja kada vas OpenMV IDE za to upita.

Ako zapnete, pitajte na OpenMV forumima.