Séquence de réinitialisation et de démarrage

Un appareil exécutant MicroPython suit une séquence de démarrage particulière pour s’allumer et s’initialiser après une réinitialisation.

Note

La séquence _boot.pyboot.pymain.py → REPL décrite ci-dessous est ce que le micrologiciel exécute à chaque réinitialisation, quel que soit votre mode de connexion — elle s’applique donc toujours. Lorsque vous exécutez un script depuis OpenMV IDE, l’IDE interrompt le fichier main.py en cours d’exécution et exécute à sa place le script ouvert dans l’éditeur, via son propre protocole de débogage. Il n’utilise pas le REPL embarqué sur l’appareil, de sorte que les références spécifiques au REPL présentes sur cette page (l’invite interactive, Ctrl-D / Ctrl-C dans un terminal série, etc.) s’appliquent au fonctionnement autonome et aux sessions directes via terminal série — mais la séquence de démarrage elle-même s’applique dans tous les cas.

Réinitialisation matérielle (hard reset)

Le démarrage à partir d’une réinitialisation matérielle est ce qui se produit lorsqu’une carte est mise sous tension pour la première fois, un démarrage à froid. Il s’agit d’une réinitialisation complète du matériel du MCU.

Le code du portage MicroPython initialise tout le matériel essentiel (y compris les horloges intégrées et les régulateurs de tension, l’UART série interne, etc.), puis démarre l’environnement MicroPython. La configuration RTC existante peut être conservée après une réinitialisation matérielle, mais tout autre état matériel est effacé.

La même séquence de démarrage par réinitialisation matérielle peut être déclenchée par un certain nombre d’événements tels que :

  • Le code Python exécutant machine.reset().

  • L’utilisateur appuie sur un bouton de réinitialisation physique sur la carte (le cas échéant).

  • Le réveil depuis la veille profonde (sur la plupart des portages).

  • La réinitialisation par le chien de garde matériel du MCU.

  • Le détecteur de baisse de tension (brown out) matériel du MCU.

Les détails des déclencheurs de réinitialisation spécifiques au matériel dépendent du portage et du matériel associé. La fonction machine.reset_cause() peut être utilisée pour déterminer plus précisément la cause d’une réinitialisation.

Réinitialisation logicielle (soft reset)

Lorsque MicroPython est déjà en cours d’exécution, il est possible de déclencher une réinitialisation logicielle en tapant Ctrl-D dans le REPL ou en exécutant machine.soft_reset().

Une réinitialisation logicielle réinitialise l’interpréteur Python, libère toute la mémoire Python et redémarre l’environnement MicroPython.

L’état effacé par une réinitialisation logicielle inclut :

  • Toutes les variables Python, les objets, les modules importés, etc.

  • La plupart des périphériques configurés à l’aide du module machine. Il existe de très rares exceptions ; par exemple, les modes machine.Pin (c’est-à-dire si une broche est en entrée ou en sortie, à l’état haut ou bas) ne sont pas réinitialisés sur la plupart des portages. Une configuration plus avancée telle que Pin.irq() est toujours réinitialisée.

  • Bluetooth.

  • Les sockets réseau. Les sockets TCP ouverts sont fermés proprement vis-à-vis de l’autre partie.

  • Les fichiers ouverts. Le système de fichiers est laissé dans un état valide.

Certains états du système restent identiques après une réinitialisation logicielle, notamment :

  • Toutes les connexions réseau existantes (Ethernet, Wi-Fi, etc.) restent actives au niveau de la couche réseau IP. L’interrogation de l”interface réseau depuis le code peut indiquer que l’interface réseau est toujours active avec une adresse IP configurée, etc.

  • Un REPL actif paraît continu avant et après une réinitialisation logicielle, sauf dans certains cas inhabituels :

    • Un REPL sur UART série restaurera sa configuration matérielle par défaut (débit en bauds, etc.).

  • La fréquence d’horloge du CPU n’est généralement pas modifiée par une réinitialisation logicielle.

  • La configuration RTC (c’est-à-dire le réglage de l’heure actuelle) n’est pas modifiée par une réinitialisation logicielle.

Séquence de démarrage

Lorsque MicroPython démarre après une réinitialisation matérielle ou logicielle, il suit cette séquence de démarrage dans l’ordre :

_boot.py

Il s’agit d’un script interne figé dans le micrologiciel MicroPython. Il est fourni par MicroPython sur de nombreux portages pour effectuer l’initialisation essentielle.

Par exemple, sur la plupart des portages, _boot.py détectera le premier démarrage d’un nouvel appareil et formatera le système de fichiers en mémoire flash interne afin qu’il soit prêt à l’emploi.

À moins que vous ne créiez une version personnalisée de MicroPython ou n’ajoutiez un nouveau portage, vous n’avez probablement pas à vous soucier de _boot.py. Il est préférable de ne pas en modifier le contenu, sauf si vous savez vraiment ce que vous faites.

boot.py

Un fichier nommé boot.py peut être copié sur le système de fichiers interne de la carte à l’aide de mpremote.

Si boot.py est trouvé, il est exécuté. Vous pouvez ajouter du code dans boot.py pour effectuer une initialisation ponctuelle personnalisée (par exemple, pour configurer le matériel de la carte).

Une pratique courante consiste à configurer la connexion réseau d’une carte dans boot.py afin qu’elle soit toujours disponible après une réinitialisation pour une utilisation avec le REPL, mpremote, etc.

Avertissement

boot.py doit toujours se terminer et ne pas s’exécuter indéfiniment.

Selon la carte, une partie de l’initialisation matérielle est différée jusqu’à la fin de l’exécution de boot.py. Cela inclut l’initialisation de l’USB sur les OpenMV Cams basées sur STM32. Sur ces cartes, la sortie imprimée depuis boot.py peut ne pas être visible sur le port série USB intégré avant la fin de l’exécution de boot.py.

Le but de cette initialisation tardive est de permettre de préconfigurer un matériel particulier dans boot.py, puis de le faire démarrer avec la configuration correcte.

Note

Il est parfois plus simple de ne pas avoir de fichier boot.py et de placer plutôt tout code d’initialisation en haut de main.py.

main.py

Comme pour boot.py, un fichier nommé main.py peut être copié sur le système de fichiers interne de la carte. S’il est trouvé, il est exécuté ensuite dans le processus de démarrage.

main.py est destiné à tout code Python que vous souhaitez exécuter à chaque démarrage de votre appareil.

Quelques conseils pour l’utilisation de main.py :

  • main.py n’est pas obligé de se terminer ; n’hésitez pas à y placer une boucle infinie while True.

  • Pour les applications Python complexes, vous n’avez pas besoin de mettre tout votre code dans main.py. main.py peut être un simple point d’entrée qui importe votre application et lance l’exécution

    import my_app
    my_app.main()
    

    Cela peut aider à garder claire la structure de votre application. Cela facilite également l’installation de plusieurs applications sur une carte et le passage de l’une à l’autre.

  • Lorsque vous écrivez des applications robustes, il est recommandé d’envelopper le code de main.py avec un gestionnaire d’exceptions afin de prendre les mesures appropriées si le code plante. Par exemple

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

    Sinon, MicroPython basculera vers le REPL à la suite de tout plantage ou si main se termine (voir ci-dessous).

  • Toutes les variables globales définies dans boot.py seront toujours définies dans le contexte global de main.py.

  • Pour optimiser pleinement l’utilisation de la mémoire flash et la consommation de mémoire, vous pouvez copier des fichiers main.mpy et/ou boot.mpy précompilés sur le système de fichiers, ou même les figer dans la version du micrologiciel.

  • L’exécution de main.py est ignorée lorsqu’une réinitialisation logicielle est lancée depuis le mode REPL brut (par exemple, lorsque mpremote ou un autre programme interagit directement avec MicroPython).

Interpréteur interactif (REPL)

Si main.py n’est pas trouvé, ou si main.py se termine, alors Le mode interpréteur interactif de MicroPython (alias REPL) démarrera immédiatement.

Note

Même si main.py contient une boucle infinie, taper Ctrl-C sur le port série du REPL injectera une KeyboardInterrupt. Si aucun gestionnaire d’exceptions ne l’intercepte, alors main.py se terminera et le REPL démarrera.

Toutes les variables globales définies dans boot.py et main.py seront toujours définies dans le contexte global du REPL.

Le REPL continue de s’exécuter jusqu’à ce que du code Python déclenche une réinitialisation matérielle ou logicielle.

Soft Bricking (échec du démarrage)

Il est rare mais possible que MicroPython devienne insensible pendant le démarrage, un état parfois appelé « soft bricked ». Par exemple :

  • Si l’exécution de boot.py se bloque et que le port série USB natif ne s’initialise jamais.

  • Si du code Python reconfigure l’interface REPL, la rendant inaccessible.

Soyez rassuré, la récupération est possible !

Si vous utilisez OpenMV IDE, il suffit souvent de se connecter — l’IDE arrête le main.py en cours d’exécution et prend le relais. Si la caméra ne se connecte pas du tout, utilisez la réinitialisation d’usine ci-dessous. La méthode Ctrl-C décrite ci-après est destinée aux sessions directes via terminal série — elle repose sur le REPL embarqué sur l’appareil, que OpenMV IDE n’utilise pas.

KeyboardInterrupt

Dans de nombreux cas, ouvrir le port série du REPL et taper Ctrl-C injectera une KeyboardInterrupt et peut entraîner la fin du script en cours d’exécution et le démarrage d’un REPL. Depuis le REPL, vous pouvez utiliser os.remove() pour supprimer le fichier Python défectueux

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

Pour confirmer quels fichiers sont encore présents dans le système de fichiers interne

import os
os.listdir()

Réinitialisation d’usine

Si vous ne parvenez pas à accéder à un REPL avec la méthode ci-dessus, l’option restante est une réinitialisation d’usine : effacer l’intégralité du contenu du système de fichiers en mémoire flash interne. C’est également la solution si le système de fichiers interne a été corrompu.

OpenMV IDE propose plusieurs moyens intégrés pour ce faire. Mettez d’abord la caméra dans son mode de récupération/programme d’amorçage — la méthode diffère selon la carte, alors consultez la section Recovery and debug pins de la référence rapide de votre carte pour savoir comment y accéder. Cliquez ensuite sur le bouton de connexion dans OpenMV IDE et suivez les invites pour effacer le système de fichiers et reflasher le micrologiciel.

Avertissement

Reflasher le micrologiciel sans effacer le système de fichiers ne permettra généralement pas de récupérer d’un soft bricking, car une mise à jour normale du micrologiciel préserve le contenu du système de fichiers. Veillez à choisir l’option d’effacement lorsque OpenMV IDE vous y invite.

Si vous êtes bloqué, demandez de l’aide sur les forums OpenMV.