Sequenza di reset e avvio

Un dispositivo che esegue MicroPython segue una particolare sequenza di avvio per accendersi e inizializzarsi dopo un reset.

Nota

La sequenza _boot.pyboot.pymain.py → REPL descritta di seguito è ciò che il firmware esegue a ogni reset, indipendentemente da come ti connetti, quindi è sempre valida. Quando esegui uno script da OpenMV IDE, l’IDE interrompe il main.py attualmente in esecuzione ed esegue al suo posto lo script aperto nell’editor, tramite il proprio protocollo di debug. Non utilizza la REPL sul dispositivo, quindi i riferimenti specifici della REPL presenti in questa pagina (il prompt interattivo, Ctrl-D / Ctrl-C su un terminale seriale, ecc.) si applicano al funzionamento autonomo e alle sessioni dirette su terminale seriale, ma la sequenza di avvio in sé si applica in tutti i casi.

Hard reset

L’avvio da hard reset è ciò che avviene quando una scheda viene alimentata per la prima volta, un avvio a freddo. Si tratta di un reset completo dell’hardware dell’MCU.

Il codice del port MicroPython inizializza tutto l’hardware essenziale (compresi clock e regolatori di alimentazione integrati, UART seriale interna, ecc.) e quindi avvia l’ambiente MicroPython. La configurazione dell”RTC esistente può essere mantenuta dopo un hard reset, ma tutto il resto dello stato hardware viene cancellato.

La stessa sequenza di avvio da hard reset può essere innescata da diversi eventi, come:

  • Codice Python che esegue machine.reset().

  • L’utente preme un pulsante fisico di Reset sulla scheda (ove applicabile).

  • Il risveglio dal deep sleep (sulla maggior parte dei port).

  • Reset da watchdog hardware dell’MCU.

  • Rilevatore di brown out hardware dell’MCU.

I dettagli degli specifici trigger di reset hardware dipendono dal port e dall’hardware associato. La funzione machine.reset_cause() può essere utilizzata per determinare ulteriormente la causa di un reset.

Soft reset

Quando MicroPython è già in esecuzione, è possibile innescare un soft reset digitando Ctrl-D nella REPL o eseguendo machine.soft_reset().

Un soft reset azzera l’interprete Python, libera tutta la memoria Python e avvia nuovamente l’ambiente MicroPython.

Lo stato che viene cancellato da un soft reset include:

  • Tutte le variabili, gli oggetti, i moduli importati Python, ecc.

  • La maggior parte delle periferiche configurate utilizzando il modulo machine. Esistono pochissime eccezioni; ad esempio le modalità di machine.Pin (ossia se un pin è input o output, alto o basso) non vengono resettate sulla maggior parte dei port. Configurazioni più avanzate come Pin.irq() vengono invece sempre resettate.

  • Bluetooth.

  • I socket di rete. I socket TCP aperti vengono chiusi in modo pulito nei confronti dell’altra parte.

  • I file aperti. Il filesystem viene lasciato in uno stato valido.

Alcuni stati del sistema rimangono invariati dopo un soft reset, tra cui:

  • Qualsiasi connessione di rete esistente (Ethernet, Wi-Fi, ecc.) rimane attiva a livello di rete IP. Interrogando l”interfaccia di rete dal codice potrebbe risultare che l’interfaccia di rete è ancora attiva con un indirizzo IP configurato, ecc.

  • Una REPL attiva appare continua prima e dopo il soft reset, tranne in alcuni casi insoliti:

    • Una REPL su UART seriale ripristinerà la sua configurazione hardware predefinita (baud rate, ecc.).

  • La velocità di clock della CPU di solito non viene modificata da un soft reset.

  • La configurazione dell”RTC (ossia l’impostazione dell’ora corrente) non viene modificata dal soft reset.

Sequenza di avvio

Quando MicroPython si avvia in seguito a un hard o soft reset, segue questa sequenza di avvio nell’ordine indicato:

_boot.py

Questo è uno script interno congelato nel firmware MicroPython. Viene fornito da MicroPython su molti port per eseguire l’inizializzazione essenziale.

Ad esempio, sulla maggior parte dei port _boot.py rileverà il primo avvio di un nuovo dispositivo e formatterà il filesystem della flash interna pronto per l’uso.

A meno che tu non stia creando una build personalizzata di MicroPython o aggiungendo un nuovo port, probabilmente non hai bisogno di preoccuparti di _boot.py. È meglio non modificarne il contenuto a meno che tu non sappia davvero cosa stai facendo.

boot.py

Un file chiamato boot.py può essere copiato sul filesystem interno della scheda utilizzando mpremote.

Se boot.py viene trovato, viene eseguito. Puoi aggiungere codice in boot.py per eseguire un’inizializzazione personalizzata una tantum (ad esempio, per configurare l’hardware della scheda).

Una pratica comune è configurare la connessione di rete di una scheda in boot.py in modo che sia sempre disponibile dopo il reset per l’uso con la REPL, mpremote, ecc.

Avvertimento

boot.py dovrebbe sempre terminare e non essere eseguito indefinitamente.

A seconda della scheda, alcune inizializzazioni hardware vengono ritardate fino a dopo la conclusione di boot.py. Questo include l’inizializzazione dell’USB sulle OpenMV Cam basate su STM32. Su queste schede, l’output stampato da boot.py potrebbe non essere visibile sulla porta seriale USB integrata fino a quando boot.py non termina la sua esecuzione.

Lo scopo di questa inizializzazione tardiva è rendere possibile pre-configurare un determinato hardware in boot.py, e poi farlo avviare con la configurazione corretta.

Nota

A volte è più semplice non avere un file boot.py e collocare invece l’eventuale codice di inizializzazione all’inizio di main.py.

main.py

Similmente a boot.py, un file chiamato main.py può essere copiato sul filesystem interno della scheda. Se trovato, viene eseguito come fase successiva nel processo di avvio.

main.py è destinato a qualsiasi codice Python che vuoi eseguire ogni volta che il tuo dispositivo si avvia.

Alcuni suggerimenti per l’utilizzo di main.py:

  • main.py non deve necessariamente terminare; sentiti libero di inserirvi un ciclo infinito while True.

  • Per applicazioni Python complesse non è necessario mettere tutto il codice in main.py. main.py può essere un semplice punto di ingresso che importa la tua applicazione e ne avvia l’esecuzione:

    import my_app
    my_app.main()
    

    Questo può aiutare a mantenere chiara la struttura della tua applicazione. Rende inoltre facile installare più applicazioni su una scheda e passare dall’una all’altra.

  • Quando si scrivono applicazioni robuste, è buona pratica avvolgere il codice in main.py con un gestore di eccezioni per intraprendere l’azione appropriata se il codice va in crash. Ad esempio:

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

    Altrimenti MicroPython passerà alla REPL in seguito a qualsiasi crash o se main termina (vedi sotto).

  • Qualsiasi variabile globale impostata in boot.py sarà ancora impostata nel contesto globale di main.py.

  • Per ottimizzare completamente l’utilizzo della flash e il consumo di memoria, puoi copiare sul filesystem file main.mpy e/o boot.mpy precompilati, o persino congelarli nella build del firmware.

  • L’esecuzione di main.py viene saltata quando un soft reset viene avviato dalla modalità raw REPL (ad esempio, quando mpremote o un altro programma interagisce direttamente con MicroPython).

Interprete interattivo (REPL)

Se main.py non viene trovato, o se main.py termina, allora la La modalità interprete interattivo di MicroPython (detta REPL) si avvierà immediatamente.

Nota

Anche se main.py contiene un ciclo infinito, digitando Ctrl-C sulla porta seriale della REPL si inietterà un KeyboardInterrupt. Se nessun gestore di eccezioni lo cattura, allora main.py terminerà e la REPL si avvierà.

Qualsiasi variabile globale impostata in boot.py e main.py sarà ancora impostata nel contesto globale della REPL.

La REPL continua l’esecuzione finché il codice Python non innesca un hard o soft reset.

Soft bricking (mancato avvio)

È raro ma possibile che MicroPython diventi non responsivo durante l’avvio, uno stato a volte chiamato «soft bricked». Ad esempio:

  • Se l’esecuzione di boot.py si blocca e la porta seriale USB nativa non si inizializza mai.

  • Se il codice Python riconfigura l’interfaccia REPL, rendendola inaccessibile.

Stai tranquillo, il recupero è possibile!

Se usi OpenMV IDE, spesso è sufficiente connettersi: l’IDE arresta il main.py in esecuzione e prende il controllo. Se la camera non si connette affatto, usa il Factory Reset descritto di seguito. Il metodo Ctrl-C descritto subito dopo è per le sessioni dirette su terminale seriale: si basa sulla REPL presente sul dispositivo, che OpenMV IDE non utilizza.

KeyboardInterrupt

In molti casi, aprendo la porta seriale della REPL e digitando Ctrl-C si inietterà un KeyboardInterrupt e questo può causare la terminazione dello script in esecuzione e l’avvio di una REPL. Dalla REPL, puoi usare os.remove() per rimuovere il file Python che si comporta in modo anomalo:

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

Per confermare quali file sono ancora presenti nel filesystem interno:

import os
os.listdir()

Factory Reset

Se non riesci a raggiungere una REPL con il metodo precedente, l’opzione rimanente è un factory reset: la cancellazione dell’intero contenuto del filesystem della flash interna. Questa è anche la soluzione se il filesystem interno si è danneggiato.

OpenMV IDE dispone di diversi modi integrati per farlo. Per prima cosa metti la camera nella sua modalità di recovery/bootloader: il metodo varia a seconda della scheda, quindi consulta la sezione Recovery and debug pins del riferimento rapido della tua scheda per sapere come entrarvi. Quindi fai clic sul pulsante di connessione in OpenMV IDE e segui le istruzioni per cancellare il filesystem e riprogrammare il firmware.

Avvertimento

Riprogrammare il firmware senza cancellare il filesystem di solito non risolve il soft bricking, poiché un normale aggiornamento del firmware preserva il contenuto del filesystem. Assicurati di scegliere l’opzione di cancellazione quando OpenMV IDE te la richiede.

Se rimani bloccato, chiedi aiuto sui forum OpenMV.