Secuencia de reinicio y arranque¶
Un dispositivo que ejecuta MicroPython sigue una secuencia de arranque particular para iniciarse e inicializarse después de un reinicio.
Nota
La secuencia _boot.py → boot.py → main.py → REPL que se describe a continuación es lo que el firmware ejecuta en cada reinicio, independientemente de cómo te conectes, por lo que siempre se aplica. Cuando ejecutas un script desde OpenMV IDE, el IDE interrumpe el main.py que se está ejecutando y ejecuta en su lugar el script abierto en el editor, a través de su propio protocolo de depuración. No usa el REPL del dispositivo, por lo que las referencias específicas del REPL de esta página (el indicador interactivo, Ctrl-D / Ctrl-C en un terminal serie, etc.) se aplican al funcionamiento autónomo y a las sesiones directas de terminal serie, pero la secuencia de arranque en sí se aplica en todos los casos.
Reinicio en frío¶
El arranque desde un reinicio en frío es lo que ocurre cuando una placa se enciende por primera vez, un arranque en frío. Se trata de un reinicio completo del hardware del MCU.
El código del port de MicroPython inicializa todo el hardware esencial (incluidos los relojes integrados y los reguladores de potencia, la UART serie interna, etc.) y, a continuación, inicia el entorno de MicroPython. La configuración existente del RTC puede conservarse tras un reinicio en frío, pero todo el resto del estado del hardware se borra.
La misma secuencia de arranque por reinicio en frío puede desencadenarse por varios eventos, como:
Código Python que ejecuta
machine.reset().El usuario pulsa un botón físico de reinicio en la placa (cuando corresponda).
Despertar del modo de suspensión profunda (en la mayoría de los ports).
Reinicio por el watchdog hardware del MCU.
Detector hardware de caída de tensión (brown out) del MCU.
Los detalles de los desencadenantes de reinicio específicos del hardware dependen del port y del hardware asociado. La función machine.reset_cause() puede usarse para determinar con más precisión la causa de un reinicio.
Reinicio en caliente¶
Cuando MicroPython ya se está ejecutando, es posible desencadenar un reinicio en caliente escribiendo Ctrl-D en el REPL o ejecutando machine.soft_reset().
Un reinicio en caliente borra el intérprete de Python, libera toda la memoria de Python e inicia de nuevo el entorno de MicroPython.
El estado que se borra con un reinicio en caliente incluye:
Todas las variables, objetos, módulos importados, etc. de Python.
La mayoría de los periféricos configurados mediante el módulo machine. Hay excepciones muy limitadas; por ejemplo, los modos de machine.Pin (es decir, si un pin es de entrada o salida, alto o bajo) no se reinician en la mayoría de los ports. La configuración más avanzada, como
Pin.irq(), siempre se reinicia.Bluetooth.
Sockets de red. Los sockets TCP abiertos se cierran de forma limpia respecto a la otra parte.
Archivos abiertos. El sistema de archivos queda en un estado válido.
Parte del estado del sistema permanece igual tras un reinicio en caliente, incluido:
Cualquier conexión de red existente (Ethernet, Wi-Fi, etc.) permanece activa en la capa de red IP. Consultar la interfaz de red desde el código puede indicar que la interfaz de red sigue activa con una dirección IP configurada, etc.
Un REPL activo parece continuo antes y después del reinicio en caliente, salvo en algunos casos poco habituales:
Un REPL por UART serie restaurará su configuración hardware predeterminada (velocidad en baudios, etc.).
La velocidad del reloj de la CPU normalmente no cambia con un reinicio en caliente.
La configuración del RTC (es decir, el ajuste de la hora actual) no cambia con un reinicio en caliente.
Secuencia de arranque¶
Cuando MicroPython arranca tras un reinicio en frío o en caliente, sigue esta secuencia de arranque en orden:
_boot.py¶
Este es un script interno congelado en el firmware de MicroPython. MicroPython lo proporciona en muchos ports para realizar la inicialización esencial.
Por ejemplo, en la mayoría de los ports _boot.py detectará el primer arranque de un dispositivo nuevo y formateará el sistema de archivos de la memoria flash interna para dejarlo listo para usar.
A menos que estés creando una compilación personalizada de MicroPython o añadiendo un nuevo port, probablemente no necesites preocuparte por _boot.py. Es mejor no cambiar su contenido a menos que sepas realmente lo que estás haciendo.
boot.py¶
Un archivo llamado boot.py puede copiarse al sistema de archivos interno de la placa usando mpremote.
Si se encuentra boot.py, se ejecuta. Puedes añadir código en boot.py para realizar una inicialización personalizada de una sola vez (por ejemplo, para configurar el hardware de la placa).
Una práctica común es configurar la conexión de red de una placa en boot.py para que siempre esté disponible tras el reinicio y poder usarla con el REPL, mpremote, etc.
Advertencia
boot.py siempre debe finalizar y no ejecutarse indefinidamente.
Según la placa, parte de la inicialización del hardware se retrasa hasta después de que boot.py finalice. Esto incluye la inicialización de USB en las OpenMV Cam basadas en STM32. En estas placas, la salida impresa desde boot.py puede no ser visible en el puerto serie USB integrado hasta que boot.py termine de ejecutarse.
El propósito de esta inicialización tardía es que sea posible preconfigurar hardware concreto en boot.py y que después arranque con la configuración correcta.
Nota
A veces es más sencillo no tener un archivo boot.py y colocar cualquier código de inicialización al principio de main.py en su lugar.
main.py¶
De forma similar a boot.py, un archivo llamado main.py puede copiarse al sistema de archivos interno de la placa. Si se encuentra, se ejecuta a continuación en el proceso de arranque.
main.py es para cualquier código Python que quieras ejecutar cada vez que se inicie tu dispositivo.
Algunos consejos para el uso de main.py:
main.pyno tiene que finalizar; puedes poner ahí un bucle infinitowhile True.Para aplicaciones Python complejas no necesitas poner todo tu código en
main.py.main.pypuede ser un punto de entrada sencillo que importe tu aplicación e inicie su ejecución:import my_app my_app.main()
Esto puede ayudar a mantener clara la estructura de tu aplicación. También facilita instalar varias aplicaciones en una placa y alternar entre ellas.
Al escribir aplicaciones robustas, es buena práctica envolver el código de
main.pycon un manejador de excepciones para tomar las medidas adecuadas si el código falla. Por ejemplo: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()
De lo contrario, MicroPython pasará al REPL tras cualquier fallo o si main finaliza (véase más abajo).
Cualquier variable global que se haya establecido en
boot.pyseguirá establecida en el contexto global demain.py.Para optimizar al máximo el uso de la memoria flash y el consumo de memoria, puedes copiar archivos
main.mpyoboot.mpyprecompilados al sistema de archivos, o incluso congelarlos en la compilación del firmware.La ejecución de
main.pyse omite cuando se inicia un reinicio en caliente desde el modo raw REPL (por ejemplo, cuando mpremote u otro programa interactúa directamente con MicroPython).
Intérprete interactivo (REPL)¶
Si no se encuentra main.py, o si main.py finaliza, entonces El modo de intérprete interactivo de MicroPython (también conocido como REPL) se iniciará de inmediato.
Nota
Incluso si main.py contiene un bucle infinito, escribir Ctrl-C en el puerto serie del REPL inyectará un KeyboardInterrupt. Si ningún manejador de excepciones lo captura, main.py finalizará y se iniciará el REPL.
Cualquier variable global que se haya establecido en boot.py y main.py seguirá establecida en el contexto global del REPL.
El REPL continúa ejecutándose hasta que código Python desencadene un reinicio en frío o en caliente.
Bloqueo blando (fallo al arrancar)¶
Es poco frecuente, pero es posible que MicroPython deje de responder durante el inicio, un estado que a veces se denomina «soft bricked» (bloqueo blando). Por ejemplo:
Si la ejecución de
boot.pyse queda atascada y el puerto serie USB nativo nunca se inicializa.Si código Python reconfigura la interfaz del REPL, dejándola inaccesible.
Ten la seguridad de que la recuperación es posible.
Si usas OpenMV IDE, a menudo basta con conectarse: el IDE detiene el main.py en ejecución y toma el control. Si la cámara no se conecta en absoluto, usa la opción Factory Reset que se indica más abajo. El método Ctrl-C que se describe a continuación es para sesiones directas de terminal serie, ya que depende del REPL del dispositivo, que OpenMV IDE no utiliza.
KeyboardInterrupt¶
En muchos casos, abrir el puerto serie del REPL y escribir Ctrl-C inyectará KeyboardInterrupt y puede provocar que el script en ejecución finalice y se inicie un REPL. Desde el REPL, puedes usar os.remove() para eliminar el archivo Python problemático:
import os
os.remove('main.py')
Para confirmar qué archivos siguen presentes en el sistema de archivos interno:
import os
os.listdir()
Restablecimiento de fábrica¶
Si no puedes llegar a un REPL con el método anterior, la opción restante es un restablecimiento de fábrica: borrar todo el contenido del sistema de archivos de la memoria flash interna. Esta es también la solución si el sistema de archivos interno se ha corrompido.
OpenMV IDE tiene varias formas integradas de hacer esto. Primero pon la cámara en su modo de recuperación/gestor de arranque (bootloader): el método varía según la placa, así que consulta la sección Recovery and debug pins de la referencia rápida de tu placa para saber cómo entrar en él. A continuación, haz clic en el botón de conexión de OpenMV IDE y sigue las indicaciones para borrar el sistema de archivos y volver a flashear el firmware.
Advertencia
Volver a flashear el firmware sin borrar el sistema de archivos normalmente no recuperará el dispositivo de un bloqueo blando, ya que una actualización normal del firmware conserva el contenido del sistema de archivos. Asegúrate de elegir la opción de borrado cuando OpenMV IDE te lo solicite.
Si te quedas atascado, pregunta en los foros de OpenMV.