Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a179cb6
tests: Use a unique domain name for tests/multi_wlan/getaddrinfo.
projectgus Mar 26, 2026
6d327a1
mimxrt: Provide abort so that C++ libunwind can link.
projectgus Mar 3, 2026
523ad2c
tools/ci.sh: Build the usercmodule example in CI for more ports.
projectgus Mar 3, 2026
c080565
ports: Refactor C++ compilation support.
projectgus Mar 3, 2026
5ce74c3
tests/misc: Skip cexample_subclass.py on minimal unix variant.
projectgus Mar 5, 2026
bc92f5a
nrf: Add support for building C++ user modules.
projectgus Mar 25, 2026
e379cb4
rp2: Allow setting MICROPY_C_HEAP_SIZE from make command line.
projectgus Mar 25, 2026
3eb617d
docs/develop/cmodules: Add some notes about C dynamic memory and C++.
projectgus Mar 25, 2026
4f04f08
docs/develop/memorymgt: Expand on MicroPython memory management from C.
projectgus Apr 1, 2026
50218dd
docs: Link memory management & gc docs more, reduce duplication.
projectgus Apr 1, 2026
c9bb925
docs/develop: Link to module docs, remove extraneous example code.
projectgus Apr 1, 2026
5e7d4bf
docs/library/gc: Add documentation for gc.isenabled().
projectgus Apr 8, 2026
35652ff
docs/library/gc: Add some simple examples for gc.threshold().
projectgus Apr 8, 2026
1a8c835
docs/library/machine.Pin: Update pull-up/down constants.
agatti Apr 8, 2026
b67c55c
py/emitinlinethumb: Shrink condition code lookups.
agatti Mar 25, 2026
5ddc551
py/compile: Reject *arg after keyword argument.
jepler Apr 3, 2026
5b127f0
py/modio: Error out on over-long read()/write() in user IO code.
jepler Apr 5, 2026
1834dcf
py/objtuple: Support __add__ and __iadd__ with tuple subclasses.
jepler Apr 5, 2026
a43a8ac
py/mpconfig: Automatically configure thumb2 and float emitter features.
dpgeorge Apr 7, 2026
02f2683
py/objint_longlong: Fix signed comparison error.
jepler Aug 2, 2025
eeed037
extmod/machine_usb_device: Document xfer_cb result value, add enums.
projectgus Apr 8, 2026
98e4264
tests/run-tests.py: Correct spelling errors.
jepler Apr 8, 2026
bd69a0d
lib/re1.5: Check stack during compilecode.
jepler Apr 8, 2026
cf0ef5a
rp2/rp2_dma: Reduce footprint of the DMA control fields table.
agatti Mar 30, 2026
083b0cc
qemu/Makefile: Refactor shared ROMFS definitions.
agatti Apr 8, 2026
acaba3f
qemu/boards/VIRT_RV32: Add ROMFS support.
agatti Apr 8, 2026
f3e79c8
qemu/boards/VIRT_RV64: Add ROMFS support.
agatti Apr 8, 2026
809cf6f
qemu/boards/MPS2_AN385: Add ROMFS support.
agatti Apr 8, 2026
75441f4
qemu/boards/SABRELITE: Add ROMFS support.
agatti Apr 8, 2026
67de20a
tests: Rename "tests/frozen" into "tests/assets".
agatti Apr 9, 2026
c895770
tests/ports/qemu: Add ROMFS tests to CI.
agatti Apr 8, 2026
2752d39
esp32/modules: Use "from machine import *" instead of __getattr__.
dpgeorge Apr 9, 2026
50348ce
stm32/mpconfigport: Enable machine.CAN if CAN2 is used.
iabdalkader Apr 13, 2026
036bd81
stm32: Fix mboot build with TinyUSB-enabled boards.
pi-anl Mar 23, 2026
941cc31
mimxrt: Convert port to use new event waiting functions.
dpgeorge Apr 8, 2026
1f601e8
samd: Convert port to use new event waiting functions.
dpgeorge Apr 13, 2026
a593d19
stm32/tinyusb: Add High Speed USB controller support.
pi-anl Oct 19, 2025
7f56da5
shared/tinyusb: Fix RHPORT mode selection for High-Speed USB.
pi-anl Oct 19, 2025
f957813
stm32: Fix USB VBUS sensing for newer STM32F4/F7 HAL versions.
pi-anl Nov 1, 2025
2971782
stm32/factoryreset: Add TinyUSB-specific boot.py examples.
pi-anl Oct 28, 2025
03472b5
shared/tinyusb: Fix CDC reconnect stall and TX FIFO.
pi-anl Mar 6, 2026
a60b5c5
stm32: Match ST DFU bootloader serial number in TinyUSB.
pi-anl Mar 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*.dxf binary
*.mpy binary
*.der binary
*.bin binary

# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text
Expand Down
74 changes: 72 additions & 2 deletions docs/develop/cmodules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ limitations with the Python environment, often due to an inability to access
certain hardware resources or Python speed limitations.

If your limitations can't be resolved with suggestions in :ref:`speed_python`,
writing some or all of your module in C (and/or C++ if implemented for your port)
is a viable option.
writing some or all of your module in C (and/or
:ref:`C++ if implemented for your port<cxx_support>`) is a viable option.

If your module is designed to access or work with commonly available
hardware or libraries please consider implementing it inside the MicroPython
Expand Down Expand Up @@ -285,3 +285,73 @@ can now be accessed in Python just like any other builtin module, e.g.
sleep_ms(1000)
print(watch.time())
# should display approximately 1000
.. _c_heap:

C Dynamic Memory Allocation
---------------------------

MicroPython uses its own "Python heap" for `memorymanagement`,
which is not the same as the "C heap" used by C library functions ``malloc()``,
``free()``, etc. Not every MicroPython port comes with a "C heap" at all.

Tier 1 & 2 ports have varying support for C dynamic memory allocation via a "C
heap":

- unix, windows, esp32 and webassembly ports support C dynamic memory
allocation.
- rp2 port will fail to allocate any memory at runtime unless the firmware is
built with ``MICROPY_C_HEAP_SIZE=n`` to reserve ``n`` bytes of memory for a C
heap. This memory will not be available for Python code to use.
- alif, mimxrt, nrf, renesas-ra, samd, and stm32 port builds that include
dynamic C allocation will fail at link-time with errors such as ``undefined
reference to `malloc'``. MicroPython has no built-in support for dynamic C
allocation on these ports. Any solution requires manually adding a C heap
implementation to the custom build.
- zephyr port currently does not support building with user modules.

Python heap as C heap
~~~~~~~~~~~~~~~~~~~~~

It may be practical for C code to call "Python heap" dynamic allocation
functions such ``m_malloc()``, ``m_malloc0()`` and ``m_free()`` instead.

See `python_memory_from_c` for more information about this approach.

.. _cxx_support:

C++ Modules
-----------

Most Tier 1 & 2 MicroPython ports (and some Tier 3) support building C++ user
modules, using the C++-specific environment variables described above.

Integrating C++ and MicroPython successfully involves some additional
considerations:

C++ Dynamic Memory Allocation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C++ programs (as well as C++ Standard Library features) typically use dynamic
memory allocation. The C++ default memory allocator (i.e. operators ``new`` and
``delete``) is typically implemented as a layer on top of `c_heap`.

For MicroPython ports which don't include C dynamic memory allocation support,
C++ dynamic memory allocation can be supported in one of two ways:

- Implement C dynamic memory allocation in your custom build.
- Implement a custom C++ allocator in your custom build.

Linkage Considerations
~~~~~~~~~~~~~~~~~~~~~~

Because MicroPython is a C-based project, any symbols which link to or from
MicroPython need to be qualified ``extern "C"`` in C++ code.

It's strongly recommended to follow the pattern demonstrated in
`examples/usercmodule/cppexample
<https://github.com/micropython/micropython/blob/master/examples/usercmodule/cppexample>`_,
where the Python module is implemented in a minimal C file wrapper around the
C++ code.

10 changes: 2 additions & 8 deletions docs/develop/library.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,9 @@ Implementing a core module
--------------------------

Like CPython, MicroPython has core builtin modules that can be accessed through import statements.
An example is the ``gc`` module discussed in :ref:`memorymanagement`.
An example is the :mod:`gc` module discussed in :ref:`memorymanagement`.

.. code-block:: bash

>>> import gc
>>> gc.enable()
>>>

MicroPython has several other builtin standard/core modules like ``io``, ``array`` etc.
MicroPython has several other builtin standard/core modules like :mod:`io`, :mod:`array`, etc.
Adding a new core module involves several modifications.

First, create the ``C`` file in the ``py/`` directory. In this example we are adding a
Expand Down
111 changes: 74 additions & 37 deletions docs/develop/memorymgt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,80 @@ Memory Management
=================

Unlike programming languages such as C/C++, MicroPython hides memory management
details from the developer by supporting automatic memory management.
Automatic memory management is a technique used by operating systems or applications to automatically manage
the allocation and deallocation of memory. This eliminates challenges such as forgetting to
free the memory allocated to an object. Automatic memory management also avoids the critical issue of using memory
that is already released. Automatic memory management takes many forms, one of them being
garbage collection (GC).

The garbage collector usually has two responsibilities;

#. Allocate new objects in available memory.
#. Free unused memory.

There are many GC algorithms but MicroPython uses the
`Mark and Sweep <https://en.wikipedia.org/wiki/Tracing_garbage_collection#Basic_algorithm>`_
policy for managing memory. This algorithm has a mark phase that traverses the heap marking all
live objects while the sweep phase goes through the heap reclaiming all unmarked objects.

Garbage collection functionality in MicroPython is available through the ``gc`` built-in
module:

.. code-block:: bash

>>> x = 5
>>> x
5
>>> import gc
>>> gc.enable()
>>> gc.mem_alloc()
1312
>>> gc.mem_free()
2071392
>>> gc.collect()
19
>>> gc.disable()
>>>

Even when ``gc.disable()`` is invoked, collection can be triggered with ``gc.collect()``.
details from the developer by supporting automatic memory management of a
":ref:`Python heap<heap>`" that holds all Python objects. MicroPython uses
garbage collection (GC) for automatic memory management. The garbage collector
is responsible for freeing memory which is no longer in use.

Specifically, MicroPython uses a `Mark and Sweep
<https://en.wikipedia.org/wiki/Tracing_garbage_collection#Basic_algorithm>`_
garbage collection algorithm. This algorithm has a mark phase that scans the
heap marking all live objects, and then a sweep phase goes through the heap
reclaiming all unmarked objects.

The MicroPython garbage collector is by default automatic, but manual control is
available through the :mod:`gc` built-in module.

.. _python_memory_from_c:

MicroPython Memory from C code
------------------------------

Awareness of the garbage collector is needed when writing C code that allocates
memory from the "Python heap" (i.e. functions ``m_malloc()``, ``m_malloc0()``,
``m_free()``, etc).

The mark phase of the garbage collector scans for live pointers to heap memory
starting from the following roots:

- The stack of the main Python runtime (or REPL).
- The stacks of each "Python thread", for ports which implement Python threads
on top of native operating system threads or tasks.
- The "root pointers" defined in C code using the macro
``MP_REGISTER_ROOT_POINTER``. These are the recommended way to have statically
scoped pointers to the Python heap.
- Tracked allocations made with the ``m_tracked_calloc()``, ``m_tracked_realloc``
and ``m_tracked_free()`` functions. These special functions allow allocating a
block of memory which is always considered live by the garbage collector.
Similar to memory allocation in C, this memory is only freed by calling
``m_tracked_free()`` or by soft reset. There is a small memory usage and
runtime overhead to each tracked allocation. This feature is not enabled by
default on all ports.

The garbage collector then recursively scans and marks all the memory pointed to
by the root pointers, until all addresses are exhausted. This is sufficient to
find all Python objects that are still in use by the MicroPython runtime.

However, the following memory will **not** be scanned by the garbage collector
and could be freed prematurely:

- Static or global C variables which contain pointers to heap memory.
- Pointers which don't point to the "head" of an allocated buffer (i.e. to the
exact address returned by ``m_malloc()``), but instead to an address inside
the allocated buffer (for example, a pointer to a nested struct). For
performance reasons, the garbage collector doesn't mark the enclosing buffer
in these cases.
- The stack of any thread or RTOS task which isn't running Python code or
manually registered as a "Python thread" (for ports which support native
threads or tasks).

Ways to avoid use-after-free in these scenarios:

- Use the tracked allocation API ``m_tracked_calloc()``, ``m_tracked_realloc()``
and ``m_tracked_free()``.
- Register a root pointer (see above), instead of storing a pointer in a static
variable.
- Restructure the code, for example by having an API where Python code
initialises a singleton Python object (implemented in C) which holds all of the
relevant pointers instead of having them in static variables.

.. note:: :ref:`soft_reset` always clears the Python heap and frees all memory.
It's important not to hold any pointers to the heap after a soft
reset, as they will become dangling pointers to freed memory.

Some ports support a "C heap" as well (see `c_heap`), in which case
you can allocate memory that will stay valid over soft reset by
calling standard C functions ``malloc``, etc.

The object model
----------------
Expand Down
44 changes: 43 additions & 1 deletion docs/library/gc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
==========================================

.. module:: gc
:synopsis: control the garbage collector
:synopsis: control the garbage collector which automatically frees
:ref:`heap memory <heap>`

|see_cpython_module| :mod:`python:gc`.

Expand All @@ -18,6 +19,10 @@ Functions
Disable automatic garbage collection. Heap memory can still be allocated,
and garbage collection can still be initiated manually using :meth:`gc.collect`.

.. function:: isenabled()

Returns True if automatic garbage collection is enabled, and False otherwise.

.. function:: collect()

Run a garbage collection.
Expand Down Expand Up @@ -64,3 +69,40 @@ Functions
This function is a MicroPython extension. CPython has a similar
function - ``set_threshold()``, but due to different GC
implementations, its signature and semantics are different.

Examples
^^^^^^^^

To trigger a garbage collection each time 32768 bytes of RAM have been allocated in total::

gc.threshold(32768)

To restore the default behaviour, only triggering garbage collection when out of memory::

gc.threshold(-1)

Example
-------

.. code-block:: bash

>>> import gc
>>> gc.mem_free() # Gets number of bytes free in memory
8192
>>> gc.mem_alloc() # Gets number of bytes allocated in memory
1024
>>> foo = bytearray(1000) # Create a big array of data
>>> gc.mem_free() # Show that there's less memory available
7168
>>> gc.mem_alloc() # Show that there's more memory used
2048
>>> del foo # Delete the object
>>> gc.mem_free() # Show that collection hasn't run yet
7168
>>> gc.mem_alloc() # That memory is still allocated
2048
>>> gc.collect() # Manually run the collection
>>> gc.mem_free() # Now we have reclaimed that memory
8192
>>> gc.mem_alloc() # That memory is no longer allocated
1024
13 changes: 12 additions & 1 deletion docs/library/machine.Pin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,22 @@ not all constants are available on all ports.

.. data:: Pin.PULL_UP
Pin.PULL_DOWN
Pin.PULL_HOLD

Selects whether there is a pull up/down resistor. Use the value
``None`` for no pull.

Some ports have a different constants set that can be used to select
hardware-specific behaviour:

- The esp8266 port does not have pull-down resistors on GPIO pins, hence
``Pin.PULL_DOWN`` is not supported.
- The mimxrt port has several extra constants to enable different pull
modes: ``Pin.PULL_UP_22K`` enables a 22KΩ pull-up on the pin,
``Pin.PULL_UP_47K`` enables a 47KΩ pull-up on the pin, and
``Pin.PULL_HOLD`` that puts the pin into high-impedance mode. The
``Pin.PULL_UP`` and ``Pin.PULL_DOWN`` constants will use a 100KΩ internal
resistor.

.. data:: Pin.DRIVE_0
Pin.DRIVE_1
Pin.DRIVE_2
Expand Down
25 changes: 21 additions & 4 deletions docs/library/machine.USBDevice.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,11 @@ Methods
The callback has three arguments:

1. The Endpoint number for the completed transfer.
2. Result value: ``True`` if the transfer succeeded, ``False``
otherwise.
3. Number of bytes successfully transferred. In the case of a
"short" transfer, The result is ``True`` and ``xferred_bytes``
2. Result value. This is an integer which is ``0`` (`XFER_SUCCESS`) on
success, or one of the non-zero values `XFER_FAILED` or `XFER_STALLED`
if the transfer failed.
3. Number of bytes successfully transferred. In the case of a "short"
transfer, the result is ``0`` (`XFER_SUCCESS`) and ``xferred_bytes``
will be smaller than the length of the buffer submitted for the
transfer.

Expand Down Expand Up @@ -301,4 +302,20 @@ Constants
- ``desc_cfg`` - ``bytes`` object containing the complete built-in USB
configuration descriptor.

.. data:: USBDevice.XFER_SUCCESS
.. data:: USBDevice.XFER_FAILED
.. data:: USBDevice.XFER_STALLED

These are integer constants that represent the possible transfer
result values passed to the ``xfer_cb`` callback (see
`USBDevice.config`).

- ``XFER_SUCCESS`` has value ``0`` and indicates the transfer was
successful.
- ``XFER_FAILED`` indicates the transfer failed due to low-level
integrity errors.
- ``XFER_STALLED`` indicates that the host has stalled this endpoint.

All failure values are non-zero integers.

.. _usb driver modules in micropython-lib: https://github.com/micropython/micropython-lib/tree/master/micropython/usb#readme
29 changes: 27 additions & 2 deletions docs/library/micropython.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,33 @@ Functions
is given then extra information is printed.

The information that is printed is implementation dependent, but currently
includes the amount of stack and heap used. In verbose mode it prints out
the entire heap indicating which blocks are used and which are free.
includes the amount of stack and heap used. In verbose mode it prints out a
summary of the entire heap indicating which blocks are used and which are
free.

The exact output of verbose mode varies between ports, but in general each
letter represents a single 16 byte block of memory. Each line of
output represents 0x400 bytes or 1KiB of RAM.

The meaning of each letter:

====== =================
Symbol Meaning
====== =================
. free block
h head block
= tail block
m marked head block
T tuple
L list
D dict
F float
B byte code
M module
S string or bytes
A bytearray
====== =================


.. function:: qstr_info([verbose])

Expand Down
Loading
Loading