After more than three years in development, the "ROMFS" feature has been finalised, its filesystem format specified, and the VFS driver and supporting code are included in this release of MicroPython. This feature builds on bytecode version 6 (available for many years now), which supports executing bytecode in-place, that is, without the need to copy it to RAM. ROMFS defines a read-only, memory-mappable, extensible filesystem that can contain arbitrary resources, including precompiled mpy files, and allows executing bytecode directly from the filesystem. This makes importing significantly faster and use a lot less memory. Also, data resources such as fonts can be used in-place on a ROMFS without loading into RAM.
ROMFS is currently enabled only on selected boards: PYBD-SFx, all alif-port boards, a new ESP8266_GENERIC variant called FLASH_2M_ROMFS, and all stm32 Arduino boards. Other boards will have ROMFS enabled in the future, or it can be manually enabled on user-defined boards.
To build and deploy a ROMFS, mpremote has a new mpremote romfs command, with "query", "build", and "deploy" sub-commands, which can build and deploy a directory structure to a ROMFS partition on a target device. These initial ROMFS features will be extended in the future, but for now they provide a way to try out this long-anticipated feature.
This release also introduces a brand new "alif" port supporting Alif Ensemble MCUs. These MCUs offer multiple ARM cores, including Ethos-U55 machine-learning processors, and a comprehensive set of peripherals. Current features of the MicroPython alif port include USB support via TinyUSB, dual-core support using OpenAMP, octal SPI flash with XIP, the machine classes Pin, UART, SPI and I2C, and cyw43 WiFi and BLE support. Two alif board definitions are currently available: ALIF_ENSEMBLE for the official Alif Ensemble E7 DevKit, and OPENMV_AE3 for OpenMV's upcoming AE3-based camera board.
MicroPython's inline assembler now supports 32-bit RISC-V assembly code via the newly implemented @micropython.asm_rv32 decorator. This allows writing small snippets of RISC-V machine code that can be called directly from Python code. It is enabled on the rp2 port when the RP2350 is running in RISC-V mode.
Datagram TLS (DTLS) is now supported by the tls module and enabled on the alif, mimxrt, renesas-ra, rp2, stm32 and unix ports. An SSLContext can be created in DTLS mode using tls.PROTOCOL_DTLS_CLIENT or tls.PROTOCOL_DTLS_SERVER as the mode option, and this context can then be used to wrap a normal UDP socket to get a secure UDP connection.
The mpremote command-line tool now supports recursive remove via the new rm -r option; for example, mpremote rm -rv : can be used to remove all files and directories in the current working directory of the target device. mpremote also now supports relative URLs in the package.json file, installing from the local filesystem, and has optimised readline support in mpremote mount.
Improvements to the core interpreter include: full support for tuples and start/end arguments in the str.startswith() and str.endswith() methods; enabling of the two-argument version of the built-in next() function on most of the ports; a new sys.implementation._build entry which holds the build name of the target; and vfs.mount() with no arguments now returns a list of mounted filesystems.
The marshal module has been added with dumps() and loads() functions, which currently support code objects and, in combination with function.__code__, allow converting functions to/from a bytes object. This module is not enabled by default but can be used in custom build configurations.
The MicroPython native linker mpy_ld.py now includes support for linking in static libraries automatically. This allows the native-module build scripts to look for required symbols from libraries such as libgcc and libm that are provided by the compiler. This now makes it possible to use standard C functions like exp() in native modules. Also, native modules now support 32-bit RISC-V code.
The esp32 port now supports IDF v5.3 and v5.4, and support for versions below v5.2.0 has been dropped. Dynamic USB device support is now enabled on ESP32-S2 and ESP32-S3 MCUs, allowing configuration of the USB device at runtime. I2S has been enabled on all ESP32-C3 boards, the Pin.toggle() method has been added, and the I2C bus identifier is now an optional argument (by default, bus 0 is used). Additionally, memory management has been improved for the allocation of TLS sockets to attempt to automatically free any existing unused TLS memory when needed.
The mimxrt port now enables exFAT filesystem support and the PPP driver for boards with lwIP networking, and has support for a UF2 bootloader, making it easier to deploy firmware. The machine.RTC.now() method has been dropped (use datetime() instead), ADC.read_uv() has been added, and machine.I2C has support for the timeout keyword argument. The I2C, SPI and UART classes now support default buses, so the first argument to these constructors is no longer needed if the default bus is used. Some inconsistencies with PWM output have been fixed, along with an allocation bug for the UART RX and TX buffers.
The rp2 port sees the introduction of many new RP2350 boards, including the Pico 2 W, as well as support for PSRAM with size autodetection. The PIO interface now supports side_pindir selection, and SPI allows the MISO pin to be unspecified. Both the I2C and SPI classes now have the bus identifier as an optional argument with a default based on the board configuration. WPA3 is now supported on the Pico W and Pico 2 W in both AP and STA modes. Lost WiFi events due to code executing on the second core have now been fixed, mDNS has been fixed, and rp2.bootsel_button() and USB sleep now work on RP2350. ROMFS support has been added but is not enabled on any board by default; see commit 50a7362b3eff211a5051eeaecc88bdde045c90d1 for information on how to enable it manually.
The samd port has added full support for 9-bit data in the UART peripheral and supports default buses and pins for I2C, SPI and UART. DAC for two channels has been fixed on SAMD51, and UART buffering has had a few bug fixes.
The stm32 port now deinitialises I2C and SPI buses on soft-reset, which may be a breaking change for certain applications; be sure to always initialise I2C and SPI instances when creating them. The CAN code has been refactored, and a few minor bugs have been fixed there. Corrupt littlefs filesystems are now handled properly at startup: instead of a failed mount leading to a hard fault, the code attempts to mount again with default block device parameters, and if that also fails, it prints a message and continues the boot process. ROMFS is enabled on PYBD-SFx boards and all Arduino boards and can be enabled on other boards by manual configuration; see commit bea7645b2e55881c4f42e6cfbe2a6433c5986794 for details. The PYBD-SF6 firmware now supports both original boards and new boards with larger SPI flash. WPA3 is now supported on boards using the cyw43-driver. mboot now includes a version string which is placed at the very end of the flash section allocated for this bootloader (usually 32k); this version can be retrieved using the fwupdate.get_mboot_version() function.
The zephyr port has had machine.Timer and machine.WDT implemented.
New boards added in this release are: ALIF_ENSEMBLE and OPENMV_AE3 (alif port), MAKERDIARY_RT1011_NANO_KIT (mimxrt port), MACHDYNE_WERKZEUG, RPI_PICO2_W, SEEED_XIAO_RP2350, SPARKFUN_IOTNODE_LORAWAN_RP2350, SPARKFUN_IOTREDBOARD_RP2350, SPARKFUN_PROMICRO_RP2350, SPARKFUN_THINGPLUS_RP2350, SPARKFUN_XRP_CONTROLLER, SPARKFUN_XRP_CONTROLLER_BETA and WEACTSTUDIO_RP2350B_CORE (rp2 port), ADAFRUIT_NEOKEY_TRINKEY, ADAFRUIT_QTPY_SAMD21, SAMD_GENERIC_D21X18, SAMD_GENERIC_D51X19 and SAMD_GENERIC_D51X2 (samd port), WEACT_F411_BLACKPILL (stm32 port).
The change in code size since the previous release for select builds of various ports is (absolute and percentage change in the text section):
The leading causes of these changes in code size are:
minimal, stm32, renesas-ra: various small code-size optimisations
unix: enable VfsRom, update mbedTLS to v3.6.2, enable DTLS
cc3200: implement Pin.toggle() method
esp8266: enable function attributes, implement Pin.toggle(), allow enumerating connected stations in AP mode, update requests package
esp32: lots of small fixes and improvements
mimxrt: enable exFAT, add function.__code__ and function constructor
nrf: various small features such as sys.implementation._build, two-argument built-in next(), no-argument vfs.mount()
rp2: update mbedTLS to v3.6.2, enable DTLS, update cyw43-driver to 1.1.0
samd: support UART 9-bit data, add function.__code__ and function constructor, provide default IDs for UART, I2C and SPI
Performance of the VM and runtime is effectively unchanged since the previous release.
Thanks to everyone who contributed to this release: Alessandro Gatti, Alex Brudner, Amirreza Hamzavi, Andrew Leech, Angus Gratton, Anson Mansfield, Carl Pottle, Christian Clauss, chuangjinglu, Corran Webster, Damien George, danicampora, Daniël van de Giessen, Dryw Wade, eggfly, Garry W, garywill, Glenn Moloney, Glenn Strauss, Graeme Winter, Hans Maerki, Herwin Grobben, I. Tomita, iabdalkader, IhorNehrutsa, Jan Klusáček, Jan Sturm, Jared Hancock, Jeff Epler, Jon Nordby, Jos Verlinde, Karl Palsson, Keenan Johnson, Kwabena W. Agyeman, Lesords, machdyne, Malcolm McKellips, Mark Seminatore, Markus Gyger, Matt Trentini, Mike Bell, Neil Ludban, Peter Harper, peterhinch, Phil Howard, robert-hh, Ronald Weber, rufusclark, Sebastian Romero, Steve Holden, stijn, StrayCat, Thomas Watson, Victor Rajewski, Volodymyr Shymanskyy, Yoctopuce.
MicroPython is a global Open Source project, and contributions were made from the following timezones: -0800, -0700, -0600, -0500, -0400, +0000, +0100, +0200, +0300, +0330, +0700, +0800, +1000, +1100, +1300.
The work done in this release was funded in part through GitHub Sponsors, and in part by George Robotics, Espressif, Arduino, LEGO Education, OpenMV and Planet Innovation.
What follows is a detailed list of changes, generated from the git commit history, and organised into sections.
Main components
py core:
objdeque: fix buffer overflow in deque_subscr
py.mk: add check that any specified USER_C_MODULES folder exists
usermod.cmake: add check that any specified USER_C_MODULES exists
usermod.cmake: if USER_C_MODULES is a folder add micropython.cmake
objfloat: workaround non-constant NAN definition on Windows MSVC
misc: fix msvc and C++ compatibility
emitglue: fix clear cache builtin warning on Clang for AArch32
mkrules.mk: use partial clone for submodules if available
dynruntime.mk: delete compiled module file on clean
qstr: add qstr_from_strn_static() helper function
reader: provide mp_reader_try_read_rom() function
persistentcode: add support for loading .mpy files from a ROM reader
misc: add a popcount(uint32_t) implementation
emitinlinerv32: add inline assembler support for RV32
obj: cast float literals to 64-bit to prevent overflow warning
obj: make literals unsigned in float get/new functions
asmarm: fix asm_arm_ldrh_reg_reg_offset to emit correct machine code
asmarm: allow function state to be larger than 255
asmarm: fix locals address loading code generation with large imm
asmarm: fix halfword loads with larger offsets
mkrules.mk: move comment about partial clones outside make rule
persistentcode: initialize prelude_ptr to prevent compiler warning
parsenum: throw an exception for invalid int literals like "01"
emitnative: optimise Viper register offset load/stores on Xtensa
emitnative: emit shorter exception handler entry code on RV32
emitnative: optimise Viper immediate offset load/stores on Xtensa
mkrules: add GIT_SUBMODULES_FAIL_IF_EMPTY flag for CMake ports
parsenumbase: favor clarity of code over manual optimisation
gc: split out running finalizers to a separate pass
gc: allow gc_free from inside a gc_sweep finalizer
add optional support for recursive mutexes, use for gc mutex
gc: reorder static functions for clarity
mkrules.mk: reset USER_C_MODULES when building mpy-cross dependency
emitnative: mark condition code tables as const
emitnative: load and store words just once for Viper code
objcode: factor code object out into its own file
objfun: implement function.code and function constructor
persistentcode: add mp_raw_code_save_fun_to_bytes
mkrules.cmake: support passing CFLAGS_EXTRA in environment variable
emitinlinerv32: fix compilation with ESP-IDF v5.2 and later
emitinlinerv32: reduce the footprint of compiled code
emitinlinextensa: simplify register name lookup
parsenum: reduce code footprint of mp_parse_num_float
objstr: support tuples and start/end args in startswith and endswith