Commit Graph

5354 Commits

Author SHA1 Message Date
Damien George
1f601e8987 samd: Convert port to use new event waiting functions.
Convert the samd port from the old `MICROPY_EVENT_POLL_HOOK` macro to use
the new `mp_event_wait_xxx()` functions in conjunction with
`MICROPY_INTERNAL_WFE`.

This change should be functionally equivalent to the existing behaivour
because `mp_event_wait_ms()` is equal to
`mp_handle_pending(MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS); __WFE()`,
which is what `MICROPY_EVENT_POLL_HOOK` was.

Signed-off-by: Damien George <damien@micropython.org>
2026-04-16 16:20:57 +10:00
Damien George
941cc31db2 mimxrt: Convert port to use new event waiting functions.
Convert the mimxrt port from the old `MICROPY_EVENT_POLL_HOOK` macro to use
the new `mp_event_wait_xxx()` functions in conjunction with
`MICROPY_INTERNAL_WFE`.

This change should be functionally equivalent to the existing behaivour
because `mp_event_wait_ms()` and `mp_event_wait_indefinite()` are equal to
`mp_handle_pending(MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS); __WFE()`,
which is what `MICROPY_EVENT_POLL_HOOK` was.

Signed-off-by: Damien George <damien@micropython.org>
2026-04-16 16:13:34 +10:00
Andrew Leech
036bd81636 stm32: Fix mboot build with TinyUSB-enabled boards.
usbd_conf.c unconditionally includes shared/tinyusb/mp_usbd.h which
pulls in tusb.h when MICROPY_HW_ENABLE_USBDEV is set. The
BUILDING_MBOOT guard that disables TinyUSB comes after the include,
so mboot builds fail with missing tusb.h. Guard the include with
!BUILDING_MBOOT.

Also add forward declaration of mp_usbd_ll_init() next to the
MICROPY_HW_TINYUSB_LL_INIT macro in mpconfigboard_common.h, since
the function is used in an inline function in mp_usbd.h but only
declared in the port-specific usbd_conf.h.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2026-04-16 15:20:58 +10:00
iabdalkader
50348ce0eb stm32/mpconfigport: Enable machine.CAN if CAN2 is used.
Enable machine.CAN if CAN1 or CAN2 or both are enabled.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2026-04-15 16:11:44 +10:00
Damien George
2752d398ad esp32/modules: Use "from machine import *" instead of __getattr__.
The esp32 port has the machine Counter and Encoder classes implemented in
Python, requiring a `machine.py` that extends the built-in machine module.

That previously used `__getattr__()` to delegate lookups to the built-in,
but that means any failed lookup raises an `AttributeError` instead of an
`ImportError`.  This means (among other things) that certain tests like
CAN and I2CTarget would fail because they couldn't skip the test correctly.

This commit improves the situation by using `from machine import *` instead
of `__getattr__()`, which puts all the built-in functions/classes/constants
directly in the `machine.py` global namespace.  That means an `ImportError`
is now correctly raised for attributes that don't exist.

Although this takes up a bit more RAM, it's now a lot faster to import from
the machine module: what used to take around 100us to lookup a name now
takes only 5us.

Signed-off-by: Damien George <damien@micropython.org>
2026-04-15 16:08:34 +10:00
Alessandro Gatti
c895770d4a tests/ports/qemu: Add ROMFS tests to CI.
This commit adds a new test to make sure ROMFS files are mounted and
read correctly, to be run as part of the CI process.

The changes also include the source binary files that have been used to
create the pre-baked ROMFS partition image used in the test, along with
a Makefile to allow recreating said file.

The CI test ROMFS image is mounted only if no other ROMFS partition is
mounted in slot 0.  The specific test is executed only if there actually
is a ROMFS partition mounted and if the partition is identified as the
one used to run tests on.  This allows for user images to be mounted and
for a successful test run if that is the case.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:04:26 +10:00
Alessandro Gatti
67de20ae0a tests: Rename "tests/frozen" into "tests/assets".
This commit renames the "tests/frozen" directory into "tests/assets" to
make it more explicit that it does contain files that are needed for
other tests to function.

Right now there's only a single pre-compiled module being used for
miscellaneous tests, but it will soon hold ROMFS test data as well.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:04:26 +10:00
Alessandro Gatti
75441f49ad qemu/boards/SABRELITE: Add ROMFS support.
This commit lets the SABRELITE machine definition load a ROMFS
partition at the very end of the RAM space.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:04:26 +10:00
Alessandro Gatti
809cf6f561 qemu/boards/MPS2_AN385: Add ROMFS support.
This commit lets the MPS2_AN385 machine definition load a ROMFS
partition right at the beginning of the 16MiB PSRAM area.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:04:26 +10:00
Alessandro Gatti
f3e79c8b56 qemu/boards/VIRT_RV64: Add ROMFS support.
This commit reserves a memory area to mount ROMFS partitions into, and
lets the port Makefile know the memory area details.

A 4 MiB segment is allocated at 0x8062_0000, which is inside the
emulated machine's DRAM segment.  The virt board requires the image
loaded in its DRAM segment to be contiguous, so the ROMFS segment is
placed right after the stack area.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:04:26 +10:00
Alessandro Gatti
acaba3f469 qemu/boards/VIRT_RV32: Add ROMFS support.
This commit reserves a memory area to mount ROMFS partitions into, and
lets the port Makefile know the memory area details.

A 4 MiB segment is allocated at 0x8061_0000, which is inside the
emulated machine's DRAM segment.  The virt board requires the image
loaded in its DRAM segment to be contiguous, so the ROMFS segment is
placed right after the stack area.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:04:26 +10:00
Alessandro Gatti
083b0cc60f qemu/Makefile: Refactor shared ROMFS definitions.
This commit refactors shared ROMFS definitions appearing in some Arm
boards configuration, moving them into the QEMU port's Makefile.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:04:26 +10:00
Alessandro Gatti
cf0ef5a9d7 rp2/rp2_dma: Reduce footprint of the DMA control fields table.
This commit shortens the amount of space taken by the DMA control fields
table, and explicitly marks it as `const`.

The DMA fields info table used a full-size QSTR index value, and 9 bits
of numeric information.  Given that the QSTR index could be converted
into a `qstr_short_t`, there is no fields spill outside a machine word
boundary - albeit with having 7 unused bits but there isn't much that
can be done for that.  The effective structure size for each entry is
halved, from 8 bytes down to 4.

Also, the structure is only read from, yet it was not marked as `const`.
Marking the structure as constant did not help reduce the final size but
at least correctly signals the compiler that no write accesses are
possible.

This shrinks the RPI_PICO/RPI_PICO_W build by 56 bytes, with a similar
size reduction for RPI_PICO2/RPI_PICO2_W.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-15 16:03:38 +10:00
Damien George
a43a8ac89e py/mpconfig: Automatically configure thumb2 and float emitter features.
Prior to this commit a port would need to manually configure the
`MICROPY_EMIT_THUMB_ARMV7M` and `MICROPY_EMIT_INLINE_THUMB_FLOAT` options,
based on whether the CPU is Thumb2 and whether it has hardware floating
point support (eg Cortex-M0+ vs Cortex-M3 vs Cortex-M4).

This is error prone, for example on stm32:
- `NUCLEO_G0B1RE` (a Cortex-M0+ MCU) had both enabled even though neither
  options work on that target.
- `NUCLEO_L152RE` (a Cortex-M3 MCU) had both enabled but this target does
  not support hardware floating point.

The change here automatically enables the two options based on built-in
compiler macros.

This change is tested on the following boards:
- alif ALIF_ENSEMBLE: both enabled
- rp2 RPI_PICO: both disabled
- rp2 RPI_PICO2: both enabled
- samd SAMD21_XPLAINED_PRO: both disabled
- samd SAMD_GENERIC_D51X20: both enabled
- stm32 NUCLEO_G0B1RE: both disabled
- stm32 NUCLEO_L152RE: only MICROPY_EMIT_THUMB_ARMV7M enabled
- stm32 PYBD_SF6: both enabled
- stm32 PYBV10: both enabled

Signed-off-by: Damien George <damien@micropython.org>
2026-04-15 15:49:44 +10:00
Angus Gratton
e379cb4479 rp2: Allow setting MICROPY_C_HEAP_SIZE from make command line.
This isn't a necessary change, but allows make MICROPY_C_HEAP_SIZE=nnn as
an alternative to setting it in a board's .cmake file.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2026-04-15 15:25:50 +10:00
Angus Gratton
bc92f5a249 nrf: Add support for building C++ user modules.
The compiler flags -ansi -std=c11 were both being passed to g++, causing
weirdness. Removed the -ansi flag entirely, it's superseded by explicitly
setting the standard.

Also adds build coverage for user C modules (including C++) in CI.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2026-04-15 15:25:50 +10:00
Angus Gratton
c080565170 ports: Refactor C++ compilation support.
Move the common CXXFLAGS and LDFLAGS into py/mkrules.mk

Changes ports minimal, esp8266, mimxrt, renesas-ra, samd,
stm32, unix, windows (mingw32).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2026-04-15 15:24:52 +10:00
Angus Gratton
6d327a1a84 mimxrt: Provide abort so that C++ libunwind can link.
Also add missing SRC_CXX support to the mimxrt build, same as
on other ports.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2026-04-15 15:24:11 +10:00
Dryw Wade
f456a23b62 esp32/machine_pin: Make all pins on ESP32-P4 output capable.
All GPIO pins on the ESP32-P4 are output capable, so there is no need to
define GPIO_FIRST_NON_OUTPUT.

Fixes #18982.

Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
2026-04-08 22:44:03 +10:00
Alessandro Gatti
2f16bf430a esp32/network_wlan: Look up IP addresses for the stations list.
This commit extends the output of `WLAN.status('stations')` to also
include the IP address of WiFi stations connected to the device if in AP
mode.

IP address lookup is currently not available on targets that use hosted
WiFi (eg. ESP32P4), as the hosted API does not yet support performing
the MAC->IP lookup on the WiFi MCU end.

The ESP32 port is brought up to parity with most ports in this regard
(primarily with the ESP8266).  This functionality depends on the DHCP
server provided by ESP-IDF, which is automatically run on the WiFi
interface if the device is put in AP mode.  Currently the ESP32 port
cannot run with said DHCP server disabled, so if a device does not
request a static IP it may either have the wrong IP address returned
(since the DHCP server assigned an address which is then discarded by
the client), or it won't have any (ie. "0.0.0.0").  In the latter case
`None` will be returned as the station's address instead.

This implements #9203.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-08 22:04:55 +10:00
Dryw Wade
e57e522182 esp32/machine_sdcard: Make default SDMMC slot configurable.
Resolves part of #18984.  On ESP32-P4, SDMMC slot 0 supports SDIO 3.0, and
is liekly the default for most boards.  MICROPY_HW_SDMMC_DEFAULT_SLOT can
be set in `mpconfigboard.h` to change default slot.

Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
2026-04-08 21:55:56 +10:00
Pierre Gaufillet
71d2314164 esp32/boards/LILYGO_T3_S3: Add LILYGO T3-S3 board definition.
ESP32-S3FH4R2 with SX1262 LoRa (HPD17A), SSD1306 OLED, SD card.
Freezes lora-sx126x and ssd1306 from micropython-lib.

Signed-off-by: Pierre Gaufillet <pierre.gaufillet@bergamote.eu>
2026-04-08 21:47:09 +10:00
Alessandro Gatti
024178455d unix/modsocket: Add "sendall" method to socket class.
This commit adds an implementation for "socket.sendall" to the Unix
port.

Right now the implementation is a wrapper over a single "socket.send"
call, since it wasn't possible to let "socket.send" perform a partial
transfer.  With no partial transfers it is not possible to have a
testable implementation following the expected behaviour, so a single
send operation is done and OSErr(EINTR) is raised if a partial transfer
occurs.

The discussion for the issue linked to this PR contains more information
about the efforts made to let partial transfers happen.

This fixes #16803.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-04-08 19:20:51 +10:00
Andrew Leech
18735dde3b tests/ports/unix: Add tests for m_tracked_realloc.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2026-04-08 17:02:01 +10:00
Kwabena W. Agyeman
501b0e6bab alif/tinyusb_port: Fix _xfer_trb cache alignment.
TRB buffers, which are the target of cache clean/invalidate actions, were
not cache-aligned between buffers.  Reported the problem to Alif, and
adding padding to them is the proper fix.  Appears to work without any
other changes in device behavior.

Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
2026-04-08 16:24:55 +10:00
iabdalkader
ed463edb36 qemu/boards/MPS2_AN500: Configure and enable ROMFS.
Using the last 2MBs of PSRAM.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2026-04-07 17:28:02 +10:00
iabdalkader
a22d9da0a3 qemu/boards/MPS3_AN547: Configure and enable ROMFS.
Uses DDR address space.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2026-04-07 17:27:57 +10:00
iabdalkader
6b2488f1d6 qemu: Add basic ROMFS support.
This commit adds basic ROMFS support.  This helps with running tests since
mpremote mount is too slow with big files.

To be configured per-board, and then run with:

    $ make QEMU_ROMFS_IMG0=image.romfs ...

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2026-04-07 17:25:41 +10:00
Daniël van de Giessen
e8992ebc78 esp32/machine_uart: Allow passing -1 to specify pin will be unused.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2026-04-07 15:08:21 +10:00
Daniël van de Giessen
b6bc2d473c esp32/adc: Raise error if ADC read result is invalid.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2026-04-07 14:57:36 +10:00
Fin Maaß
c16a484796 zephyr/machine_uart: Ignore return value of uart_irq_update.
For uart_irq_update() the allowed return values
are a negative errno or 1. 0 is not allowd.
Therefore ignore the return value.
Also the return type might soon be changed to void.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-04-07 13:41:15 +10:00
Jeff Epler
4fe08ff16b all: Avoid qstr_str calls when printing a qstr.
The `%q` formatter of mp_printf can be used instead, and may save a small
amount of code.

Signed-off-by: Jeff Epler <jepler@unpythonic.net>
2026-04-07 13:36:34 +10:00
Damien George
e8a3ee0342 esp32/esp32_common.cmake: Add missing C flags to user C module sources.
On the esp32 port when adding a user C module, the source code for the user
C module was being compiled without certain C flags.  Notably the
optimisation flag was missing.

This commit fixes that by explicitly adding the missing C flags to the
compilation of user C modules.

The missing flags were the following, which are now included when building
user C modules (found by inspecting the generated CMake files when building
with ulab):

    -ffunction-sections
    -fdata-sections
    -Wall
    -Werror=all
    -Wno-error=unused-function
    -Wno-error=unused-variable
    -Wno-error=unused-but-set-variable
    -Wno-error=deprecated-declarations
    -Wextra
    -Wno-error=extra
    -Wno-unused-parameter
    -Wno-sign-compare
    -Wno-enum-conversion
    -gdwarf-4
    -ggdb
    -mdisable-hardware-atomics
    -O2
    -fmacro-prefix-map=micropython/ports/esp32=.
    -fmacro-prefix-map=espressif/esp-idf=/IDF
    -fstrict-volatile-bitfields
    -fno-jump-tables
    -fno-tree-switch-conversion

See related issue #18880.

Work done in collaboration with @andrewleech.

Signed-off-by: Damien George <damien@micropython.org>
2026-04-01 14:44:04 +11:00
Matt Trentini
2dc2e30d98 esp32/boards/SEEED_XIAO_ESP32C6: Add new XIAO board definition.
Signed-off-by: Matt Trentini <matthew.trentini@planetinnovation.com.au>
Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2026-03-25 23:57:07 +11:00
Dryw Wade
f4d2447174 esp32/boards/SPARKFUN_THINGPLUS_ESP32C5: Add SF Thing Plus ESP32-C5.
Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
2026-03-25 23:55:21 +11:00
Matt Trentini
ac48088749 rp2/boards/SEEED_XIAO_RP2040: Add XIAO RP2040 board definition.
Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2026-03-25 23:48:48 +11:00
Damien George
6f96d260e6 webassembly/variants/pyscript: Enable weakref module and add tests.
The webassembly port needs some additional weakref tests due to the fact
that garbage collection only happens when Python execution finishes and
JavaScript resumes.

The `tests/ports/webassembly/heap_expand.py` expected output also needs to
be updated because the amount of GC heap got smaller (weakref WTB takes
some of the available RAM).

Signed-off-by: Damien George <damien@micropython.org>
2026-03-22 23:13:26 +11:00
Damien George
f83f363bb8 webassembly/Makefile: Add test//% target.
Following a69425b533, this is a convenient
way to run a subset of tests.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-22 23:06:07 +11:00
Damien George
702f15ab98 stm32/boards/PYBD_SF2: Free up some space in internal flash.
With the recent addition of `machine.PWM` and `machine.CAN`, the internal
flash of PYBD_SF3 overflows by about 300 bytes.

This commit moves the inline assembler compiler functions from internal to
external QSPI flash.  That frees up about 3k internal flash, and shouldn't
affect performance.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-22 00:04:52 +11:00
Damien George
82e44e07e7 stm32/mpthreadport: Increase minimum thread stack size to 2.5k.
2.25k Seems necessary so it doesn't crash `thread/thread_stacksize1.py`.
But 2.5k gives a little extra headroom to make that test actually pass.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-22 00:03:20 +11:00
iabdalkader
134bf4d847 alif/irq: Add missing IRQ priorities.
Add DMA, NPU and PDM IRQ priorities to irq.h.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2026-03-21 23:58:16 +11:00
Alessandro Gatti
b3d88cf210 extmod/nimble/modbluetooth_nimble: Handle port init failures.
This commit fixes an issue related to the NimBLE initialisation
procedure in low memory environments on ESP32 boards.

MicroPython uses at least two different NimBLE stacks across the
supported ports, mynewt (imported as an external library), and the one
provided by Espressif in their own SDKs.  The problem is that these two
ports differ in the signature for `nimble_port_init(void)`, with mynewt
returning `void`, and Espressif's returning a status code on failure.

On ESP32 boards, allocating almost all the available heap and then
turning on the Bluetooth stack would trigger a failure in the NimBLE
initialisation function that is not handled by the NimBLE integration
code, as there's no expectation of a recoverable condition.  Since the
stack initialisation would progress, then uninitialised memory accesses
crash the board.

Since we cannot really modify neither mynewt nor Espressif SDKs, the
next best thing is to provide two conditional initialisation paths
depending on a configuration setting.  This would make Espressif ports
recover from a failed initialisation whilst retaining the existing
behaviour on other ports.

This fixes #14293.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2026-03-21 16:27:37 +11:00
Angus Gratton
2ccf78ae19 ci,esp32: Build oldest & newest ESP-IDF versions in CI.
Intended to catch problems where new features don't build
in old ESP-IDF.

Includes major refactor to the GitHub Actions Workflow for
esp32 port, including making a reusable workflow for both
Code Size and ESP32 build jobs.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2026-03-20 12:42:52 +11:00
Damien George
98ab12a491 stm32/boards/stm32n657_af.csv: Add TIM alt funcs to PA0-PA3.
Signed-off-by: Damien George <damien@micropython.org>
2026-03-20 11:37:15 +11:00
Damien George
2b64d6d023 stm32/boards/stm32f091_af.csv: Split TIM2_CH1 from TIM2_ETR.
So that TIM2_CH1 can be used.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-20 11:37:15 +11:00
Damien George
af31472e3d stm32/boards: Disable some features on boards with small flash.
This allows the newly-added `machine.PWM` class to fit on these boards,
which is arguably more useful than the features disabled in this commit.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-20 11:37:15 +11:00
Damien George
094c268ff1 stm32/machine_pwm: Use heuristic to assign TIMx_CHy to a pin.
When assigning a TIMx_CHy to a pin, the second available alternate function
is chosen (or the first if there is only one).  This gives better overall
static allocation of TIM's to pins.

On most MCUs (eg F4, F7, H5, H7) picking the second gives TIM5_CH[1-4] for
PA0-PA3, and TIM5 is a 32-bit timer.  That leaves TIM2 (also usually on
PA0-PA3) for other pins that only have TIM2.

For STM32G0, STM32L432 and STM32L452 the heuristic is to simply use the
first available alternate function because that gives TIM2 (a 32-bit timer)
on PA0-PA3.

The above heuristic guarantees that PA0-PA3 always get a 32-bit timer on
all supported MCUs.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-20 11:26:57 +11:00
Damien George
dbe6a11670 stm32/machine_pwm: Implement machine.PWM class.
This commit implements the standard `machine.PWM` class on stm32, using the
common bindings in `extmod/machine_pwm.c`.  Features implemented are:
- construct a PWM object from a pin, with automatic selection of TIM
  instance and channel;
- get and set freq, duty_u16 and duty_ns;
- optionally invert the output.

The PWM objects are static objects (partly in ROM, partly in RAM) so
creating a PWM instance on the same pin will return exactly the same
object.  That's consistent with other peripherals in the stm32 port, and
consistent with other PWM implementations (eg rp2).

When creating a PWM object on a pin, if that pin has multiple TIM instances
then only the first will be selected.  A future extension could allow
selecting the TIM/channel (eg similar to how ADCBlock allows selecting an
ADC).

Signed-off-by: Damien George <damien@micropython.org>
2026-03-20 11:24:19 +11:00
Damien George
2d3241f34c stm32/timer: Expose functions to convert id to reg and enable TIM clock.
This functionality already exists in the TIM code, and can be reused by the
upcoming PWM implementation.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-20 10:42:25 +11:00
Damien George
e74f3d5eaa stm32/timer: Use HAL macro to determine if TIM is 32-bit.
Some MCUs (eg N6) have more timers which are 32-bit, and it's best to use
this macro to work that out.

Signed-off-by: Damien George <damien@micropython.org>
2026-03-20 10:42:25 +11:00