summaryrefslogtreecommitdiffstatshomepage
path: root/docs/reference
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2024-10-02 19:16:39 +1000
committerDamien George <damien@micropython.org>2024-11-19 10:57:26 +1100
commit0e7c3901b897a1edd53b56b6119f2d4119e88842 (patch)
tree1264a33779159677fa6550cfc8bdecd91c2ee6ea /docs/reference
parentcbffe61f96d060ed4af2bde7e3043a3664dc147a (diff)
downloadmicropython-0e7c3901b897a1edd53b56b6119f2d4119e88842.tar.gz
micropython-0e7c3901b897a1edd53b56b6119f2d4119e88842.zip
docs: Add a "Reset and Boot Sequence" reference page.
Previously individual ports documented these aspects to varying degrees, but most of the information is common to all ports. In particular, this adds a canonical explanation of `boot.py` and `main.py`. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Diffstat (limited to 'docs/reference')
-rw-r--r--docs/reference/index.rst1
-rw-r--r--docs/reference/mpremote.rst6
-rw-r--r--docs/reference/repl.rst9
-rw-r--r--docs/reference/reset_boot.rst260
4 files changed, 272 insertions, 4 deletions
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
index 98f6b65737..1558c0fdfa 100644
--- a/docs/reference/index.rst
+++ b/docs/reference/index.rst
@@ -21,6 +21,7 @@ implementation and the best practices to use them.
glossary.rst
repl.rst
+ reset_boot.rst
mpremote.rst
mpyfiles.rst
isr_rules.rst
diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst
index b47ec76c98..d4c6983595 100644
--- a/docs/reference/mpremote.rst
+++ b/docs/reference/mpremote.rst
@@ -547,9 +547,9 @@ device at ``/dev/ttyACM1``, printing each result.
mpremote resume exec "print_state_info()" soft-reset
-Connect to the device without triggering a soft reset and execute the
-``print_state_info()`` function (e.g. to find out information about the current
-program state), then trigger a soft reset.
+Connect to the device without triggering a :ref:`soft reset <soft_reset>` and
+execute the ``print_state_info()`` function (e.g. to find out information about
+the current program state), then trigger a soft reset.
.. code-block:: bash
diff --git a/docs/reference/repl.rst b/docs/reference/repl.rst
index 55f76ee1a0..be02ddebde 100644
--- a/docs/reference/repl.rst
+++ b/docs/reference/repl.rst
@@ -143,10 +143,12 @@ the auto-indent feature, and changes the prompt from ``>>>`` to ``===``. For exa
Paste Mode allows blank lines to be pasted. The pasted text is compiled as if
it were a file. Pressing Ctrl-D exits paste mode and initiates the compilation.
+.. _repl_soft_reset:
+
Soft reset
----------
-A soft reset will reset the python interpreter, but tries not to reset the
+A :ref:`soft_reset` will reset the python interpreter, but tries not to reset the
method by which you're connected to the MicroPython board (USB-serial, or Wifi).
You can perform a soft reset from the REPL by pressing Ctrl-D, or from your python
@@ -182,6 +184,9 @@ variables no longer exist:
['__name__', 'pyb']
>>>
+For more information about reset types and the startup process, see
+:doc:`/reference/reset_boot`.
+
The special variable _ (underscore)
-----------------------------------
@@ -196,6 +201,8 @@ So you can use the underscore to save the result in a variable. For example:
15
>>>
+.. _raw_repl:
+
Raw mode and raw-paste mode
---------------------------
diff --git a/docs/reference/reset_boot.rst b/docs/reference/reset_boot.rst
new file mode 100644
index 0000000000..7c0d5f334a
--- /dev/null
+++ b/docs/reference/reset_boot.rst
@@ -0,0 +1,260 @@
+Reset and Boot Sequence
+=======================
+
+A device running MicroPython follows a particular boot sequence to start up and
+initialise itself after a reset.
+
+.. _hard_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:
+
+- Python code executing :func:`machine.reset()`.
+- User presses a physical Reset button on the board (where applicable).
+- Waking from deep sleep (on most ports).
+- MCU hardware watchdog reset.
+- MCU hardware brown out detector.
+
+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:
+
+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:
+
+- All Python variables, objects, imported modules, etc.
+- Most peripherals configured using the :doc:`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.
+- Bluetooth.
+- Network sockets. Open TCP sockets are closed cleanly with respect to the other party.
+- Open files. The filesystem is left in a valid state.
+
+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:
+
+ * If the :ref:`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.
+ * A serial UART REPL will restore its default hardware configuration (baud
+ rate, etc).
+
+- 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:
+
+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:
+
+Soft Bricking (failure to boot)
+---------------------------------
+
+It is rare but possible for MicroPython to become unresponsive during startup, a
+state sometimes called "soft bricked". For example:
+
+- If ``boot.py`` execution gets stuck and the native USB serial port
+ never initialises.
+- If Python code reconfigures the REPL interface, making it inaccessible.
+
+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:
+
+1. "Safe mode" boot, which skips ``boot.py`` and ``main.py`` and immediately
+ starts a REPL, allowing you to clean up. This is only supported on some ports.
+2. Factory Reset to erase the entire contents of the flash filesystem. This may
+ also be necessary if the internal flash filesystem has become corrupted
+ somehow.
+
+The specific process(es) are different on each port:
+
+- :doc:`pyboard and stm32 port instructions </pyboard/tutorial/reset>`
+- :doc:`renesas-ra port instructions </renesas-ra/tutorial/reset>`
+- :doc:`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