Reset- und Boot-Sequenz

Ein Gerät, auf dem MicroPython läuft, durchläuft nach einem Reset eine bestimmte Boot-Sequenz, um sich zu starten und zu initialisieren.

Bemerkung

Die unten beschriebene Sequenz _boot.pyboot.pymain.py → REPL ist das, was die Firmware bei jedem Reset ausführt, unabhängig davon, wie Sie sich verbinden — sie gilt also immer. Wenn Sie ein Skript aus der OpenMV IDE ausführen, unterbricht die IDE die gerade laufende main.py und führt stattdessen das im Editor geöffnete Skript über ihr eigenes Debug-Protokoll aus. Sie verwendet nicht die geräteinterne REPL, sodass die REPL-spezifischen Hinweise auf dieser Seite (die interaktive Eingabeaufforderung, Ctrl-D / Ctrl-C an einem seriellen Terminal usw.) für den eigenständigen Betrieb und direkte serielle Terminal-Sitzungen gelten — die Boot-Sequenz selbst gilt jedoch in allen Fällen.

Hard-Reset

Das Booten aus einem Hard-Reset ist das, was passiert, wenn ein Board zum ersten Mal eingeschaltet wird, ein Kaltstart. Dies ist ein vollständiges Zurücksetzen der MCU-Hardware.

Der MicroPython-Port-Code initialisiert die gesamte essenzielle Hardware (einschließlich eingebetteter Taktgeber und Spannungsregler, des internen seriellen UART usw.) und startet anschließend die MicroPython-Umgebung. Eine bestehende RTC-Konfiguration kann nach einem Hard-Reset erhalten bleiben, doch alle anderen Hardware-Zustände werden gelöscht.

Dieselbe Hard-Reset-Boot-Sequenz kann durch eine Reihe von Ereignissen ausgelöst werden, wie zum Beispiel:

  • Python-Code, der machine.reset() ausführt.

  • Der Benutzer drückt eine physische Reset-Taste am Board (sofern vorhanden).

  • Aufwachen aus dem Deep Sleep (auf den meisten Ports).

  • Reset durch den Hardware-Watchdog der MCU.

  • Brown-out-Detektor der MCU-Hardware.

Die Details der hardwarespezifischen Reset-Auslöser hängen vom Port und der zugehörigen Hardware ab. Mit der Funktion machine.reset_cause() lässt sich die Ursache eines Resets genauer bestimmen.

Soft-Reset

Wenn MicroPython bereits läuft, kann ein Soft-Reset ausgelöst werden, indem man Ctrl-D in der REPL eingibt oder machine.soft_reset() ausführt.

Ein Soft-Reset löscht den Python-Interpreter, gibt den gesamten Python-Speicher frei und startet die MicroPython-Umgebung erneut.

Zu dem Zustand, der durch einen Soft-Reset gelöscht wird, gehören:

  • Alle Python-Variablen, Objekte, importierten Module usw.

  • Die meisten Peripheriegeräte, die mit dem machine-Modul konfiguriert wurden. Es gibt sehr begrenzte Ausnahmen, zum Beispiel werden die machine.Pin-Modi (d. h. ob ein Pin Eingang oder Ausgang ist, high oder low) auf den meisten Ports nicht zurückgesetzt. Erweiterte Konfigurationen wie Pin.irq() werden hingegen immer zurückgesetzt.

  • Bluetooth.

  • Netzwerk-Sockets. Offene TCP-Sockets werden gegenüber der Gegenstelle sauber geschlossen.

  • Geöffnete Dateien. Das Dateisystem bleibt in einem gültigen Zustand.

Ein Teil des Systemzustands bleibt nach einem Soft-Reset unverändert, darunter:

  • Alle bestehenden Netzwerkverbindungen (Ethernet, Wi-Fi usw.) bleiben auf der IP-Netzwerkebene aktiv. Eine Abfrage der Netzwerkschnittstelle aus dem Code kann anzeigen, dass die Netzwerkschnittstelle weiterhin aktiv ist und über eine konfigurierte IP-Adresse usw. verfügt.

  • Eine aktive REPL erscheint vor und nach einem Soft-Reset durchgängig, außer in einigen ungewöhnlichen Fällen:

    • Eine serielle UART-REPL stellt ihre Standard-Hardwarekonfiguration (Baudrate usw.) wieder her.

  • Die CPU-Taktfrequenz wird durch einen Soft-Reset normalerweise nicht geändert.

  • Die RTC-Konfiguration (d. h. das Einstellen der aktuellen Zeit) wird durch einen Soft-Reset nicht geändert.

Boot-Sequenz

Wenn MicroPython nach einem Hard- oder Soft-Reset bootet, durchläuft es diese Boot-Sequenz in folgender Reihenfolge:

_boot.py

Dies ist ein internes Skript, das in die MicroPython-Firmware eingefroren ist. Es wird von MicroPython auf vielen Ports bereitgestellt, um wesentliche Initialisierungen durchzuführen.

Auf den meisten Ports erkennt _boot.py beispielsweise den ersten Boot-Vorgang eines neuen Geräts und formatiert das interne Flash-Dateisystem, um es einsatzbereit zu machen.

Sofern Sie nicht einen eigenen MicroPython-Build erstellen oder einen neuen Port hinzufügen, müssen Sie sich wahrscheinlich nicht um _boot.py kümmern. Es ist am besten, den Inhalt nicht zu ändern, es sei denn, Sie wissen wirklich, was Sie tun.

boot.py

Eine Datei namens boot.py kann mit mpremote auf das interne Dateisystem des Boards kopiert werden.

Wenn boot.py gefunden wird, wird es ausgeführt. Sie können in boot.py Code hinzufügen, um eine benutzerdefinierte einmalige Initialisierung durchzuführen (zum Beispiel, um die Hardware des Boards zu konfigurieren).

Eine gängige Praxis ist es, die Netzwerkverbindung eines Boards in boot.py zu konfigurieren, sodass sie nach einem Reset stets für die Verwendung mit der REPL, mpremote usw. verfügbar ist.

Warnung

boot.py sollte immer beendet werden und nicht unbegrenzt laufen.

Je nach Board wird ein Teil der Hardware-Initialisierung verzögert, bis boot.py beendet ist. Dazu gehört die Initialisierung von USB auf den STM32-basierten OpenMV Cams. Auf diesen Boards ist die von boot.py ausgegebene Ausgabe möglicherweise erst sichtbar, nachdem boot.py zu Ende gelaufen ist, am eingebauten seriellen USB-Port.

Der Zweck dieser späten Initialisierung besteht darin, dass es möglich ist, bestimmte Hardware in boot.py vorzukonfigurieren und sie dann mit der korrekten Konfiguration starten zu lassen.

Bemerkung

Manchmal ist es einfacher, keine boot.py-Datei zu verwenden und jeglichen Initialisierungscode stattdessen an den Anfang von main.py zu stellen.

main.py

Ähnlich wie boot.py kann eine Datei namens main.py auf das interne Dateisystem des Boards kopiert werden. Wird sie gefunden, so wird sie als Nächstes im Startvorgang ausgeführt.

main.py ist für beliebigen Python-Code gedacht, den Sie bei jedem Start Ihres Geräts ausführen möchten.

Einige Tipps zur Verwendung von main.py:

  • main.py muss nicht beendet werden, Sie können dort gerne eine endlose while True-Schleife einbauen.

  • Bei komplexen Python-Anwendungen müssen Sie nicht Ihren gesamten Code in main.py unterbringen. main.py kann ein einfacher Einstiegspunkt sein, der Ihre Anwendung importiert und die Ausführung startet:

    import my_app
    my_app.main()
    

    Dies kann dazu beitragen, die Struktur Ihrer Anwendung klar zu halten. Es macht es außerdem einfach, mehrere Anwendungen auf einem Board zu installieren und zwischen ihnen zu wechseln.

  • Beim Schreiben robuster Anwendungen ist es eine gute Praxis, den Code in main.py mit einem Exception-Handler zu umschließen, um angemessen zu reagieren, falls der Code abstürzt. Zum Beispiel:

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

    Andernfalls fällt MicroPython nach jedem Absturz oder wenn main beendet wird in die REPL zurück (siehe unten).

  • Alle globalen Variablen, die in boot.py gesetzt wurden, sind im globalen Kontext von main.py weiterhin gesetzt.

  • Um die Flash-Nutzung und den Speicherverbrauch vollständig zu optimieren, können Sie vorkompilierte main.mpy- und/oder boot.mpy-Dateien in das Dateisystem kopieren oder sie sogar einfrieren und in den Firmware-Build aufnehmen.

  • Die Ausführung von main.py wird übersprungen, wenn ein Soft-Reset aus dem Raw-REPL-Modus heraus eingeleitet wird (zum Beispiel, wenn mpremote oder ein anderes Programm direkt mit MicroPython interagiert).

Interaktiver Interpreter (REPL)

Wenn main.py nicht gefunden wird oder wenn main.py beendet wird, dann startet Der interaktive Interpretermodus von MicroPython (auch REPL genannt) sofort.

Bemerkung

Selbst wenn main.py eine endlose Schleife enthält, wird durch Eingabe von Ctrl-C am seriellen REPL-Port ein KeyboardInterrupt ausgelöst. Wenn kein Exception-Handler ihn abfängt, wird main.py beendet und die REPL gestartet.

Alle globalen Variablen, die in boot.py und main.py gesetzt wurden, sind im globalen Kontext der REPL weiterhin gesetzt.

Die REPL läuft weiter, bis Python-Code einen Hard- oder Soft-Reset auslöst.

Soft Bricking (Boot-Fehler)

Es ist selten, aber möglich, dass MicroPython während des Startvorgangs nicht mehr reagiert, ein Zustand, der manchmal als „soft bricked“ bezeichnet wird. Zum Beispiel:

  • Wenn die Ausführung von boot.py hängen bleibt und der native serielle USB-Port nie initialisiert wird.

  • Wenn Python-Code die REPL-Schnittstelle neu konfiguriert und sie dadurch unzugänglich macht.

Seien Sie unbesorgt, eine Wiederherstellung ist möglich!

Wenn Sie die OpenMV IDE verwenden, reicht oft schon das Verbinden — die IDE stoppt die laufende main.py und übernimmt die Kontrolle. Wenn sich die Kamera überhaupt nicht verbinden lässt, verwenden Sie den unten beschriebenen Factory Reset. Die als Nächstes beschriebene Ctrl-C-Methode ist für direkte serielle Terminal-Sitzungen gedacht — sie beruht auf der geräteinternen REPL, die die OpenMV IDE nicht verwendet.

KeyboardInterrupt

In vielen Fällen löst das Öffnen des seriellen REPL-Ports und die Eingabe von Ctrl-C einen KeyboardInterrupt aus und kann dazu führen, dass das laufende Skript beendet und eine REPL gestartet wird. Von der REPL aus können Sie mit os.remove() die fehlerhafte Python-Datei entfernen:

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

Um zu überprüfen, welche Dateien noch im internen Dateisystem vorhanden sind:

import os
os.listdir()

Factory Reset

Wenn Sie mit der oben beschriebenen Methode keine REPL erreichen können, bleibt als Option ein Factory Reset: das Löschen des gesamten Inhalts des internen Flash-Dateisystems. Dies ist auch die Lösung, wenn das interne Dateisystem beschädigt wurde.

Die OpenMV IDE bietet hierfür mehrere eingebaute Möglichkeiten. Versetzen Sie zunächst die Kamera in ihren Recovery-/Bootloader-Modus — die Methode unterscheidet sich je nach Board, sehen Sie also im Abschnitt Recovery and debug pins der Kurzreferenz Ihres Boards nach, wie Sie ihn aktivieren. Klicken Sie dann in der OpenMV IDE auf die Verbinden-Schaltfläche und folgen Sie den Anweisungen, um das Dateisystem zu löschen und die Firmware neu zu flashen.

Warnung

Ein erneutes Flashen der Firmware ohne Löschen des Dateisystems behebt ein Soft Bricking in der Regel nicht, da ein normales Firmware-Update den Inhalt des Dateisystems erhält. Achten Sie darauf, die Lösch-Option zu wählen, wenn die OpenMV IDE Sie dazu auffordert.

Wenn Sie nicht weiterkommen, fragen Sie in den OpenMV-Foren.