Återställnings- och startsekvens

En enhet som kör MicroPython följer en särskild startsekvens för att starta upp och initiera sig själv efter en återställning.

Anteckning

Sekvensen _boot.pyboot.pymain.py → REPL som beskrivs nedan är vad den fasta programvaran kör vid varje återställning, oavsett hur du ansluter — så den gäller alltid. När du kör ett skript från OpenMV IDE avbryter IDE:n den main.py som för tillfället körs och kör i stället skriptet som är öppet i editorn, via sitt eget felsökningsprotokoll. Den använder inte enhetens REPL, så de REPL-specifika referenserna på den här sidan (den interaktiva prompten, Ctrl-D / Ctrl-C vid en seriell terminal o.s.v.) gäller fristående drift och direkta seriella terminalsessioner — men själva startsekvensen gäller i samtliga fall.

Hård återställning

Att starta från en hård återställning är vad som händer när ett kort startas upp för första gången, en kallstart. Detta är en fullständig återställning av MCU-hårdvaran.

MicroPython-portens kod initierar all väsentlig hårdvara (inklusive inbyggda klockor och spänningsregulatorer, intern seriell UART o.s.v.) och startar sedan MicroPython-miljön. Befintlig RTC-konfiguration kan behållas efter en hård återställning, men allt annat hårdvarutillstånd nollställs.

Samma startsekvens för hård återställning kan utlösas av ett antal händelser, till exempel:

  • Python-kod som kör machine.reset().

  • Användaren trycker på en fysisk Reset-knapp på kortet (där sådan finns).

  • Uppvaknande från djupsömn (på de flesta portar).

  • Återställning av MCU:ns hårdvaruwatchdog.

  • MCU:ns hårdvarudetektor för spänningsfall (brown out).

Detaljerna kring hårdvaruspecifika återställningsutlösare beror på porten och tillhörande hårdvara. Funktionen machine.reset_cause() kan användas för att närmare avgöra orsaken till en återställning.

Mjuk återställning

När MicroPython redan körs är det möjligt att utlösa en mjuk återställning genom att trycka Ctrl-D i REPL:en eller köra machine.soft_reset().

En mjuk återställning rensar Python-tolken, frigör allt Python-minne och startar MicroPython-miljön på nytt.

Tillstånd som rensas av en mjuk återställning omfattar:

  • Alla Python-variabler, objekt, importerade moduler o.s.v.

  • De flesta kringutrustningar som konfigurerats med machine-modulen. Det finns mycket begränsade undantag, till exempel återställs inte machine.Pin-lägen (d.v.s. om ett stift är ingång eller utgång, högt eller lågt) på de flesta portar. Mer avancerad konfiguration som Pin.irq() återställs alltid.

  • Bluetooth.

  • Nätverkssocketar. Öppna TCP-socketar stängs på ett korrekt sätt med hänsyn till motparten.

  • Öppna filer. Filsystemet lämnas i ett giltigt tillstånd.

Visst systemtillstånd förblir detsamma efter en mjuk återställning, däribland:

  • Eventuella befintliga nätverksanslutningar (Ethernet, Wi-Fi o.s.v.) förblir aktiva på IP-nätverkslagret. En förfrågan till nätverksgränssnittet från kod kan indikera att nätverksgränssnittet fortfarande är aktivt med en konfigurerad IP-adress o.s.v.

  • En aktiv REPL framstår som kontinuerlig före och efter en mjuk återställning, utom i vissa ovanliga fall:

    • En seriell UART-REPL återställer sin standardhårdvarukonfiguration (baudhastighet o.s.v.).

  • CPU:ns klockfrekvens ändras vanligtvis inte av en mjuk återställning.

  • RTC-konfiguration (d.v.s. inställning av aktuell tid) ändras inte av en mjuk återställning.

Startsekvens

När MicroPython startar upp efter antingen en hård eller mjuk återställning följer den denna startsekvens i ordning:

_boot.py

Detta är ett internt skript som är fryst in i MicroPython-firmware. Det tillhandahålls av MicroPython på många portar för att utföra väsentlig initiering.

På de flesta portar kommer _boot.py till exempel att upptäcka den första uppstarten av en ny enhet och formatera det interna flashfilsystemet så att det är klart att använda.

Om du inte skapar ett anpassat MicroPython-bygge eller lägger till en ny port behöver du förmodligen inte bekymra dig om _boot.py. Det är bäst att inte ändra innehållet om du inte verkligen vet vad du gör.

boot.py

En fil med namnet boot.py kan kopieras till kortets interna filsystem med hjälp av mpremote.

Om boot.py hittas körs den. Du kan lägga till kod i boot.py för att utföra anpassad engångsinitiering (till exempel för att konfigurera kortets hårdvara).

En vanlig praxis är att konfigurera ett korts nätverksanslutning i boot.py så att den alltid är tillgänglig efter återställning för användning med REPL, mpremote o.s.v.

Varning

boot.py bör alltid avslutas och inte köras i oändlighet.

Beroende på kortet fördröjs viss hårdvaruinitiering tills efter att boot.py har avslutats. Detta inkluderar initiering av USB på de STM32-baserade OpenMV Cam-enheterna. På dessa kort kanske utdata som skrivs ut från boot.py inte syns på den inbyggda USB-serieporten förrän efter att boot.py har kört klart.

Syftet med denna sena initiering är att det ska vara möjligt att förkonfigurera viss hårdvara i boot.py och sedan låta den starta med rätt konfiguration.

Anteckning

Det är ibland enklare att inte ha någon boot.py-fil och i stället placera all initieringskod högst upp i main.py.

main.py

I likhet med boot.py kan en fil med namnet main.py kopieras till kortets interna filsystem. Om den hittas körs den härnäst i uppstartsprocessen.

main.py är till för all Python-kod som du vill köra varje gång din enhet startar.

Några tips för användning av main.py:

  • main.py behöver inte avslutas, du kan gärna lägga en oändlig while True-loop där.

  • För komplexa Python-applikationer behöver du inte lägga all din kod i main.py. main.py kan vara en enkel ingångspunkt som importerar din applikation och startar körningen:

    import my_app
    my_app.main()
    

    Detta kan hjälpa till att hålla strukturen på din applikation tydlig. Det gör det också enkelt att installera flera applikationer på ett kort och växla mellan dem.

  • Det är god praxis när man skriver robusta appar att omsluta kod i main.py med en undantagshanterare för att vidta lämpliga åtgärder om koden kraschar. Till exempel:

    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()
    

    Annars faller MicroPython tillbaka till REPL:en efter en krasch eller om main avslutas (se nedan).

  • Eventuella globala variabler som sattes i boot.py kommer fortfarande att vara satta i den globala kontexten för main.py.

  • För att fullt ut optimera flashanvändning och minnesförbrukning kan du kopiera förkompilerade main.mpy- och/eller boot.mpy-filer till filsystemet, eller till och med frysa in dem i firmware-bygget.

  • Körning av main.py hoppas över när en mjuk återställning initieras från raw REPL-läge (till exempel när mpremote eller ett annat program interagerar direkt med MicroPython).

Interaktiv tolk (REPL)

Om main.py inte hittas, eller om main.py avslutas, startar MicroPythons interaktiva tolkläge (även kallat REPL) omedelbart.

Anteckning

Även om main.py innehåller en oändlig loop kommer Ctrl-C på REPL-serieporten att injicera ett KeyboardInterrupt. Om ingen undantagshanterare fångar det kommer main.py att avslutas och REPL:en att starta.

Eventuella globala variabler som sattes i boot.py och main.py kommer fortfarande att vara satta i den globala kontexten för REPL:en.

REPL:en fortsätter att köras tills Python-kod utlöser en hård eller mjuk återställning.

Mjuk låsning (misslyckad uppstart)

Det är sällsynt men möjligt att MicroPython blir svarslös under uppstarten, ett tillstånd som ibland kallas ”soft bricked”. Till exempel:

  • Om körningen av boot.py fastnar och den inbyggda USB-serieporten aldrig initieras.

  • Om Python-kod konfigurerar om REPL-gränssnittet så att det blir otillgängligt.

Var lugn, återhämtning är möjlig!

Om du använder OpenMV IDE räcker det ofta att bara ansluta — IDE:n stoppar den körande main.py och tar över. Om kameran inte vill ansluta alls, använd Factory Reset nedan. Metoden med Ctrl-C som beskrivs härnäst är för direkta seriella terminalsessioner — den förlitar sig på enhetens REPL, som OpenMV IDE inte använder.

KeyboardInterrupt

I många fall kommer det att injicera KeyboardInterrupt att öppna REPL-serieporten och skriva Ctrl-C, vilket kan få det körande skriptet att avslutas och en REPL att starta. Från REPL:en kan du använda os.remove() för att ta bort den felaktigt fungerande Python-filen:

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

För att bekräfta vilka filer som fortfarande finns i det interna filsystemet:

import os
os.listdir()

Fabriksåterställning

Om du inte kan nå en REPL med metoden ovan är det återstående alternativet en fabriksåterställning: att radera hela innehållet i det interna flashfilsystemet. Detta är också lösningen om det interna filsystemet har blivit skadat.

OpenMV IDE har flera inbyggda sätt att göra detta. Sätt först kameran i sitt återställnings-/startladdarläge (recovery/bootloader) — metoden skiljer sig åt mellan kort, så se avsnittet Recovery and debug pins i ditt korts snabbreferens för hur du går in i det. Klicka sedan på anslutningsknappen i OpenMV IDE och följ anvisningarna för att radera filsystemet och flasha om firmware.

Varning

Att flasha om firmware utan att radera filsystemet återhämtar sig vanligtvis inte från en mjuk låsning, eftersom en normal firmware-uppdatering bevarar innehållet i filsystemet. Se till att välja raderingsalternativet när OpenMV IDE frågar efter det.

Om du kör fast, fråga på OpenMV-forumen.