docs/reference/reset_boot.rst
A device running MicroPython follows a particular boot sequence to start up and initialise itself after a reset.
.. _hard_reset:
Booting from hard reset is what happens when a board is first powered up, a cold boot. This is a complete reset of the MCU hardware.
The MicroPython port code initialises all essential hardware (including embedded
clocks and power regulators, internal serial UART, etc), and then starts the
MicroPython environment. Existing :doc:RTC </library/machine.RTC>
configuration may be retained after a hard reset, but all other hardware state
is cleared.
The same hard reset boot sequence can be triggered by a number of events such as:
machine.reset().The details of hardware-specific reset triggers depend on the port and
associated hardware. The :func:machine.reset_cause() function can be used to
further determine the cause of a reset.
.. _soft_reset:
When MicroPython is already running, it's possible to trigger a soft reset by
:ref:typing Ctrl-D in the REPL <repl_soft_reset> or executing
:func:machine.soft_reset().
A soft reset clears the Python interpreter, frees all Python memory, and starts the MicroPython environment again.
State which is cleared by a soft reset includes:
machine module </library/machine>. There are very limited exceptions, for example
:doc:machine.Pin </library/machine.Pin> modes (i.e. if a pin is input or
output, high or low) are not reset on most ports. More advanced configuration
such as :func:Pin.irq() is always reset.Some system state remains the same after a soft reset, including:
Any existing network connections (Ethernet, Wi-Fi, etc) remain active at the
IP Network layer. Querying the :doc:network interface from code </library/network> may indicate the network interface is still active with a
configured IP address, etc.
An active :doc:REPL <repl> appears continuous before and after soft reset,
except in some unusual cases:
machine.USBDevice <machine.USBDevice> class has been used to
create a custom USB interface then any built-in USB serial device will
appear to disconnect and reconnect as the custom USB interface must be
cleared during reset.CPU clock speed is usually not changed by a soft reset.
:doc:RTC </library/machine.RTC> configuration (i.e. setting of the current
time) is not changed by soft reset.
.. _boot_sequence:
When MicroPython boots following either a hard or soft reset, it follows this boot sequence in order:
_boot.py ^^^^^^^^
This is an internal script :doc:frozen into the MicroPython firmware <manifest>. It is provided by MicroPython on many ports to do essential
initialisation.
For example, on most ports _boot.py will detect the first boot of a new
device and format the :doc:internal flash filesystem <filesystem> ready for
use.
Unless you're creating a custom MicroPython build or adding a new port then you
probably don't need to worry about _boot.py. It's best not to change the
contents unless you really know what you're doing.
.. _boot.py:
boot.py ^^^^^^^
A file named boot.py can be copied to the board's internal :ref:filesystem <filesystem> using :doc:mpremote <mpremote>.
If boot.py is found then it is executed. You can add code in boot.py to
perform custom one-off initialisation (for example, to configure the board's
hardware).
A common practice is to configure a board's network connection in boot.py so
that it's always available after reset for use with the :doc:REPL <repl>,
:doc:mpremote <mpremote>, etc.
.. warning:: boot.py should always exit and not run indefinitely.
Depending on the port, some hardware initialisation is delayed until after
boot.py exits. This includes initialising USB on the stm32 port and all
ports which support :ref:machine.USBDevice <machine.USBDevice>. On these
ports, output printed from boot.py may not be visible on the built-in USB
serial port until after boot.py finishes running.
The purpose of this late initialisation is so that it's possible to
pre-configure particular hardware in boot.py, and then have it start with
the correct configuration.
.. note:: It is sometimes simpler to not have a boot.py file and place any
initialisation code at the top of main.py instead.
.. _main.py:
main.py ^^^^^^^
Similar to boot.py, a file named main.py can be copied to the board's
internal :ref:filesystem <filesystem>. If found then it is executed next in the
startup process.
main.py is for any Python code that you want to run each time your device
starts.
Some tips for main.py usage:
main.py doesn't have to exit, feel free to put an infinite while True loop in there.
For complex Python applications then you don't need to put all your
code in main.py. main.py can be a simple entry point that
imports your application and starts execution::
import my_app
my_app.main()
This can help keep the structure of your application clear. It also makes it easy to install multiple applications on a board and switch among them.
It's good practice when writing robust apps to wrap code in main.py with an
exception handler to take appropriate action if the code crashes. For example::
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()
Otherwise MicroPython will drop to the REPL following any crash or if main exits (see below).
Any global variables that were set in boot.py will still be set in the
global context of main.py.
To fully optimise flash usage and memory consumption, you can copy
:doc:pre-compiled <mpyfiles> main.mpy and/or boot.mpy files to the
filesystem, or even :doc:freeze <manifest> them into the firmware build
instead.
main.py execution is skipped when a soft reset is initiated from :ref:raw REPL mode <raw_repl> (for example, when :doc:mpremote <mpremote> or another
program is interacting directly with MicroPython).
Interactive Interpreter (REPL) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If main.py is not found, or if main.py exits, then :doc:repl
will start immediately.
.. note:: Even if main.py contains an infinite loop, typing Ctrl-C on the
REPL serial port will inject a KeyboardInterrupt. If no exception
handler catches it then main.py will exit and the REPL will start.
Any global variables that were set in boot.py and main.py will still be
set in the global context of the REPL.
The REPL continues executing until Python code triggers a hard or soft reset.
.. _soft_bricking:
It is rare but possible for MicroPython to become unresponsive during startup, a state sometimes called "soft bricked". For example:
boot.py execution gets stuck and the native USB serial port
never initialises.Rest assured, recovery is possible!
KeyboardInterrupt ^^^^^^^^^^^^^^^^^
In many cases, opening the REPL serial port and typing Ctrl-C will inject
KeyboardInterrupt and may cause the running script to exit and a REPL to
start. From the REPL, you can use :func:os.remove() to remove the misbehaving
Python file::
import os
os.remove('main.py')
To confirm which files are still present in the internal filesystem::
import os
os.listdir()
Safe Mode and Factory Reset ^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you're unable to easily access the REPL then you may need to perform one of two processes:
boot.py and main.py and immediately
starts a REPL, allowing you to clean up. This is only supported on some ports.The specific process(es) are different on each port:
pyboard and stm32 port instructions </pyboard/tutorial/reset>esp32 port instructions </esp32/tutorial/reset>renesas-ra port instructions </renesas-ra/tutorial/reset>rp2 port instructions </rp2/tutorial/reset>wipy port instructions </wipy/tutorial/reset>For ports without specific instructions linked above, the factory reset process
involves erasing the board's entire flash and then flashing MicroPython again
from scratch. Usually this will involve the same tool(s) that were originally
used to install MicroPython. Consult the installation docs for your board, or
ask on the GitHub Discussions_ if you're not sure.
.. warning:: Re-flashing the MicroPython firmware without erasing the entire flash first will usually not recover from soft bricking, as a firmware update usually preserves the contents of the filesystem.
.. _GitHub Discussions: https://github.com/orgs/micropython/discussions