MicroPython Releases v1.24 - v1.28 Digest
Source material: annotated tag messages in /tmp/mpy-tags/v1.24.0.txt, v1.24.1.txt, v1.25.0.txt, v1.26.0.txt, v1.26.1.txt, v1.27.0.txt, v1.28.0.txt. The v1.28 tag was read briefly to calibrate against the existing /micropython-v1.28/index.html page, which uses bespoke canvas/SVG demos for hardware features (PWM waveform, CAN bus animation, GC weakref visual) and live PyScript playgrounds for pure-Python features (t-strings).
Tier definitions used below:
- Tier A - bespoke canvas/SVG/animation. Best for visualising hardware behaviour, time-series, register state, packet flow, etc.
- Tier B - PyScript live playground. Feature must run on the
webassemblyport: language features, stdlib additions,asyncio, networking-as-data, etc. - Tier C - annotated code diff or static example. Port matrix, before/after snippets, architecture diagram.
v1.24.0 - “RP2350 and ESP32-C6 support, RISC-V native emitter, common TinyUSB code”
Released: 2024 (date not in tag; matches GitHub release log). Headline tagline: “RISC-V grows up, RP2350 lands, and TinyUSB gets unified.”
Top headline features
- RP2350 support (rp2 port) - pico-sdk v2.0.0 brings the new MCU in both ARM and RISC-V modes, in 30- and 48-pin variants. New
RPI_PICO2board, IPv6 enabled by default, USB stays active duringlightsleep(). - ESP32-C6 support + RISC-V native emitter (esp32 port) - Updated to ESP-IDF v5.2.2, RV32IMC native code generation enabled on C3 and C6. New
ESP32_GENERIC_C6,M5STACK_NANOC6,UM_TINYC6boards. micropython.RingIO- new thread-safe byte-oriented ring buffer with a stream interface. Cross-port (core).- Unified TinyUSB CDC + portable UART IRQ API - shared CDC code across esp32 (S2/S3), mimxrt, renesas-ra, rp2 and samd. Startup CDC data is now buffered and flushed on host connection (REPL banner appears on first connect). Consistent UART IRQ callbacks (
IRQ_RX,IRQ_RXIDLE,IRQ_TXIDLE,IRQ_BREAK) on most ports. network.ipconfig()+network.PPP- new IPv4/IPv6 config API replacingifconfig(); portable lwIP-based PPP available on rp2 and stm32.- f-string concatenation + raw f-strings (core language). Plus
sys.exit()now triggers a soft reset (breaking change).
By the numbers
- ~58 contributors named.
- ~10 new boards: 8 esp32 (
ESP32_GENERIC_C6,M5STACK_ATOMS3_LITE,M5STACK_NANOC6,OLIMEX_ESP32_EVB,UM_FEATHERS3NEO,UM_OMGS3,UM_RGBTOUCH_MINI,UM_TINYC6), 1 rp2 (RPI_PICO2), 1 stm32 (ARDUINO_OPTA). - esp32 code size shrank ~3.1% (-53kB) - notable thanks to ESP-IDF cleanup.
- Contributor timezones: 15 distinct (-0700 through +1100).
Demo proposals
| Feature | Tier | Notes |
|---|---|---|
| f-string concat + raw f-strings | B | Pure language, runs on webassembly. Side-by-side: pre-1.24 paste vs 1.24+ paste, hit Run, watch identical output. Trivial PyScript win. |
sys.exit() -> soft reset |
B | Demonstrable in PyScript with caveat (no real “device” to reset, but show the SystemExit flow). Could just be Tier C if too confusing. |
micropython.RingIO |
B | Pure-Python visible API, available on webassembly. Live producer/consumer playground; could pair with a Tier-A oscilloscope-style canvas of the buffer fill level. |
| RP2350 / ESP32-C6 | A | Bespoke MCU comparison card: side-by-side spec strip (cores, RAM, RISC-V/ARM toggle for RP2350). Animated “ARM <-> RISC-V” toggle is a great visual hook. |
| RISC-V native emitter | C | Show @micropython.native snippet, port-availability matrix (rp2 RISC-V, esp32 C3/C6, qemu). Probably no useful interactivity. |
| TinyUSB CDC unification | C | Annotated diagram of which ports now share code; before/after of the “missing REPL banner on first connect” gotcha. Hard to demo live. |
network.ipconfig() |
C | Static side-by-side: old nic.ifconfig((ip, mask, gw, dns)) vs new nic.ipconfig(addr4=...). IPv6 support is a key talking point. |
| UART IRQ API + PPP | C | Port matrix; static. |
Watch-outs / open questions
sys.exit()behaviour change is genuinely breaking - need to lead with the warning, not bury it.- “RISC-V native emitter” overlaps with v1.25’s inline RV32 assembler; need to decide which release “owns” the RISC-V hero narrative.
qemu-arm->qemurename is interesting trivia but probably not section-worthy.
v1.24.1 (point release, 2024)
One-liner: small grab-bag patch - mpremote fs_writefile UnboundLocalError fix, esp32 PWM resolution + ESP-IDF v5.0/5.1 PWM regression, objdeque buffer overflow, lwIP IGMP IPv6, FrameBuffer.ellipse zero-radius bug, ESP32-S2 native code crash workaround. Skip on the page unless we want a “patches” footnote.
v1.25.0 - “ROMFS, alif port, RISCV inline assembler, DTLS, mpremote recursive remove”
Released: early 2025. Headline tagline: “After three years cooking, ROMFS ships - plus a brand new ML-capable port.”
Top headline features
- ROMFS / VfsRom - long-awaited (cited “more than three years in development”). Read-only, memory-mappable filesystem, executes bytecode in-place without copying to RAM. Imports become significantly faster, fonts/data usable in-place. Enabled on PYBD-SFx, all alif boards, an
ESP8266_GENERIC FLASH_2M_ROMFSvariant, and all stm32 Arduino boards. Driven via newmpremote romfs query/build/deploy. - alif port (new) - support for Alif Ensemble MCUs with multi-core ARM + Ethos-U55 ML accelerators. TinyUSB, dual-core via OpenAMP, octal-SPI XIP, machine.{Pin,UART,SPI,I2C}, cyw43 WiFi+BLE. Boards:
ALIF_ENSEMBLE,OPENMV_AE3. @micropython.asm_rv32inline assembler - write 32-bit RISC-V machine code inline in Python. Enabled on rp2 when RP2350 is in RISC-V mode.- DTLS support -
tls.PROTOCOL_DTLS_CLIENT/..._SERVERmodes wrap UDP sockets. Enabled on alif, mimxrt, renesas-ra, rp2, stm32 and unix. marshalmodule -dumps()/loads()for code objects; combined withfunction.__code__lets you serialise functions to bytes. Not enabled by default but pure-Python visible.- mpremote
rm -r+ recursive remove, plus support for relative URLs inpackage.json, local-fs mip install, fastermountreadline.
By the numbers
- ~50 contributors.
- ~21 new boards: 2 alif, 1 mimxrt, 12 rp2 (lots of SparkFun + RP2350-class), 5 samd, 1 stm32.
- Contributor timezones: 15.
- mimxrt code size +2.06% (exFAT, function constructor); unix +2.05% (VfsRom + DTLS).
New boards
- alif:
ALIF_ENSEMBLE,OPENMV_AE3. - mimxrt:
MAKERDIARY_RT1011_NANO_KIT. - rp2:
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,WEACTSTUDIO_RP2350B_CORE. - samd:
ADAFRUIT_NEOKEY_TRINKEY,ADAFRUIT_QTPY_SAMD21,SAMD_GENERIC_D21X18,SAMD_GENERIC_D51X19,SAMD_GENERIC_D51X2. - stm32:
WEACT_F411_BLACKPILL.
Demo proposals
| Feature | Tier | Notes |
|---|---|---|
| ROMFS | A | Bespoke memory-map diagram: heap vs flash, animated arrow showing “import normally” copying bytecode -> RAM, then toggle to “import from ROMFS” with no copy. Could include a fake mpremote terminal showing mpremote romfs build / deploy. Strong visual story. |
| alif port | C | Port spec card: cores, Ethos-U55 mention, supported peripherals, boards. Could cross-link to OpenMV AE3 marketing image. |
@micropython.asm_rv32 |
C | Annotated side-by-side: pure Python loop vs inline RV32 asm, with a “speedup” badge. Cannot run in PyScript (no RV32 native emitter on webassembly). |
| DTLS | C/A | Tier C: code diff PROTOCOL_TLS_CLIENT -> PROTOCOL_DTLS_CLIENT. Could upgrade to Tier A with an animated UDP-with-handshake packet diagram. |
marshal module |
B | Pure Python, runnable in PyScript pyscript variant. Live: define a function, marshal.dumps(f.__code__), view bytes, loads() and run again. Caveat: needs to confirm marshal is enabled on the pyscript build - tag explicitly says “not enabled by default”. OPEN QUESTION. |
str.startswith/endswith tuples + start/end |
B | Trivial PyScript demo. Bundle into a “Python language tweaks” sub-section. |
2-arg next() |
B | Trivial PyScript. Same sub-section. |
vfs.mount() no-args returns mount table |
B | Runnable on webassembly if VFS is mounted there - OPEN QUESTION whether the pyscript variant exposes a mount table. |
mpremote rm -r / romfs deploy |
C | Static animated terminal screencast (CSS keyframes typing). |
Watch-outs / open questions
- ROMFS section is the obvious headline - but the underlying concept (memory-mapped bytecode v6) needs careful explanation. Worth a callout box on bytecode versions.
- Confirm whether
marshalis compiled into the PyScript pyscript variant before promising a Tier-B demo. webassembly port: no changes specific to this component/portin v1.25 - so most v1.25 wins are inherited via core changes only. Demos must lean on language/stdlib features rather than port-specific ones.
v1.26.0 - “I2CTarget, improved floats and native emitter, STM32N6 & ESP32C2 support”
Released: mid 2025. Headline tagline: “MicroPython gets serious about floating-point - and starts answering I2C, not just asking.”
Top headline features
machine.I2CTarget- Python implements an I2C target/slave device. Simplest case binds an I2C register/memory device to abytearray. More complex cases use IRQs from the class to handle arbitrary protocols. Available on alif, esp32, mimxrt, rp2, samd, stm32, zephyr.- Float accuracy overhaul - repr-reversibility went from ~28%/38% (single/double) to 98.5%/99.8%. Three layers: better float printing, compile-time float folding/
const, and a heuristic for the lost low bits in OBJ_REPR_C. - STM32N6xx + ESP32-C2 - 800 MHz STM32N6 with ML accelerators, USB, XSPI memory-mapped flash; ESP32-C2 (aka ESP8684) low-cost RISC-V WiFi+BLE.
- Native + viper emitter improvements - more compact loads/stores across ARM, Thumb, Xtensa, RV32, x86, x64. Thumb v1 (RP2040) gets long jumps >12 bits, allowing larger Python functions to compile native. Xtensa inline asm gets most LX3 opcodes.
esp32.PCNT+machine.Counter/machine.Encoder(esp32) - hardware pulse counting incl. quadrature encoders.- Slice-on-stack VM optimisation -
bytearray_obj[a:b] = cno longer allocates a slice on the heap; works inside hard ISRs and reduces churn. - Misc language:
__all__in star imports, PEP-487__set_name__,:_b/o/xseparators instr.format, arrays extendable from any iterable.
By the numbers
- ~46 contributors.
- ~10 new boards (lower than usual, attention was on infra).
- esp32 code size +1.12% (+19 kB), driven by IDF v5.4.2 + I2CTarget.
- Contributor timezones: 13.
New boards
- esp32:
GARATRONIC_PYBSTICK26_ESP32C3,SPARKFUN_IOT_REDBOARD_ESP32. - samd:
SPARKFUN_REDBOARD_TURBO,SPARKFUN_SAMD21_DEV_BREAKOUT. - stm32:
NUCLEO_N657X0,OPENMV_N6. - zephyr:
beagleplay_cc1352p7,nrf5340dk,nrf9151dk,rpi_pico.
Demo proposals
| Feature | Tier | Notes |
|---|---|---|
machine.I2CTarget |
A | Bespoke SVG: two MCUs on an I2C bus, controller writes to “register 0x10”, target’s bytearray updates live; click to flip controller/target roles. Best storytelling feature of the release. |
| Float accuracy improvement | B | Strong PyScript candidate. Pure-Python: input a float, show old-style truncated repr vs new accurate repr (we’d need to fake the “before” with hand-rolled formatting, since the live build is “after”). Could pair with a live histogram of the 28%->98.5% reversibility stat. |
| Float constant folding | B | PyScript: show const(2 * math.pi) folding behaviour; demonstrate via dis-like output if available. OPEN QUESTION: dis module on webassembly. |
| Slice-on-stack | C | Annotated diff: arr[1:5] = b'abcd' - explain the hard-ISR implication, GC-free property. Tier B is possible but the visible behaviour is identical to the user, so Tier C is more honest. |
| Native/viper emitter perf | C | Bar chart of code-size savings from tag (Thumb v1 +long jumps stat); architecture port matrix. |
| STM32N6 / ESP32-C2 | C | Spec cards mirroring v1.24’s RP2350 cards. STM32N6 ML accelerator angle is interesting. |
esp32.PCNT / Counter / Encoder |
A | Bespoke quadrature-encoder canvas: drag a virtual knob, watch the count tick. Hardware-only feature so no Tier B option. esp32-only callout. |
__set_name__ / __all__ star import |
B | Pure language. Bundle into a “Python language additions” sub-section with a single PyScript playground that swaps between examples. |
str.format :_b/o/x separators |
B | One-line PyScript demo: f"{0xdeadbeef:_x}". Trivial. |
| DTLS HelloVerify + lwIP UDP queue | C | Static; not user-visible without networking. |
mpremote fs tree + df |
C | Animated terminal recording. |
Watch-outs / open questions
- I2CTarget’s “Python responds to I2C” pitch needs careful framing - audiences will assume it’s an I2C controller. Lead with “your microcontroller is now the slave/target”.
- The float accuracy story is technically dense (OBJ_REPR_C is internal). Need to focus on the user-visible “repr round-trips correctly now” outcome, not the heuristic.
Counter/Encoderare added inmodules/machine.py(Python wrapper) on esp32; the API is currently esp32-only although it lives undermachine. Worth noting it’s not yet cross-port.
v1.26.1 (point release)
One-liner: ESP32 native USB stability - esp_tinyusb -> v1.7.6, USB CDC TX rewrite, mpremote DTR/RTS quirk fix for TinyUSB CDC. Also adds MICROPY_MAINTAINER_BUILD env var. Worth a one-line footnote for ESP32 users since the USB hang is a real-world bug.
v1.27.0 - “ESP32C5, ESP32P4 & STM32U5 support, enhanced test suite, port Tier levels”
Released: late 2025. Headline tagline: “Three new MCU families, formal port tiers, and a unified REPL on every port.”
Top headline features
- ESP32-C5 + ESP32-P4 support - new RISC-V SoCs. P4 can run standalone or paired with a C5/C6 wireless co-processor; tag provides board profiles for all three configurations.
- STM32U5xx series support - low-power high-performance STM32; USB, ADC, DAC, UART, I2C, SPI, RTC. Board:
NUCLEO_U5A5ZJ_Q. - Formal port Tier levels - 20 ports categorised into 4 tiers; documented in README and at https://docs.micropython.org/en/latest/develop/support_tiers.html. Sets expectations for support and lowers the bar for new ports to land.
- Test suite + CI overhaul - auto-detection of unicode/float/native support,
target_wiring.pyfor hardware-in-the-loop wiring config, allmachine.UARTtests converted, ASan/UBSan builds, full test suite on unix-minimal and zephyr CI, serial throughput test. - Unified REPL on unix/windows - main REPL replaced with the bare-metal pyexec REPL. Adds raw-REPL support to unix/windows. Now
mpremoteworks against unix builds the same as bare-metal. - Hard IRQ timer callbacks across ports - most ports (except esp32) now support
hard=formachine.Timer. - Drop Python 2.7 support in build scripts.
- Misc language: relative imports in custom
__import__,bool/lenon dict views, start/end positions forre.match/search, IPv6 inasyncio.start_server(),sysmodule enabled at all feature levels by default.
By the numbers
- ~50 contributors.
- ~10 new boards: 5 esp32, 4 stm32, plus zephyr boards (PocketBeagle 2, XIAO BLE NRF52840 SENSE, NXP MIMXRT1020 EVK).
- esp32 code size +2.12% (+36 kB) - dominated by ESP-IDF 5.5.1 bump.
- Contributor timezones: 16 (-0800 to +1100).
New boards
- esp32:
ESP32_GENERIC_C2 FLASH_2M,ESP32_GENERIC_C5,ESP32_GENERIC_P4(+C5_WIFI,C6_WIFIvariants),SIL_MANT1S,SOLDERED_NULA_MINI. - stm32:
NUCLEO_H7A3ZI_Q,NUCLEO_U5A5ZJ_Q,STM32F469DISC,WEACTSTUDIO_MINI_STM32H743. - zephyr: PocketBeagle 2 variants, XIAO BLE nRF52840 Sense, NXP MIMXRT1020 EVK.
Demo proposals
| Feature | Tier | Notes |
|---|---|---|
| ESP32-P4 + co-processor | A | Bespoke SVG diagram: P4 standalone vs P4-with-C6-radio - clickable toggle revealing how the two chips talk. Strongest hardware visual of the release. |
| STM32U5 | C | Spec card. Less inherently visual than P4. |
| Port Tier levels | A | Custom interactive port tier chart - all 20 ports as nodes coloured by tier, hover for board count, tier description. Could double as the navigation widget for a /releases/ index. |
target_wiring.py + test suite |
C | Aimed at contributors. Annotated example file. Skip-able on a public-facing page unless we lean into “MicroPython quality” narrative. |
| Hard IRQ timer callbacks | C/A | Tier C: port matrix of hard=True support. Tier A possible: side-by-side timeline showing soft vs hard IRQ jitter, but that’s more a v1.26-era story. |
| Unified unix REPL / raw REPL | C | Animated terminal: mpremote run against unix build. Mostly developer-experience. |
re.match(start, end) |
B | Pure-Python PyScript demo. Trivial. |
bool/len on dict views |
B | One-liner PyScript. Bundle. |
asyncio.start_server() IPv6 |
B | PyScript probably can’t bind a real socket; demote to Tier C code diff. |
Relative imports in custom __import__ |
B | PyScript demo - install a custom __import__ hook, show relative resolution. Niche but cute. |
| Drop Python 2.7 | C | Footnote. |
Watch-outs / open questions
- Port Tier levels is a great organising idea for the
/releases/index page itself - consider building the tier chart once and reusing. - ESP32-C5 vs ESP32-C6 vs ESP32-P4 will confuse non-ESP audiences. Clear naming/colour key needed.
asyncio.start_server()IPv6 - check whether the pyscript variant exposes any networking. If not, definitely Tier C.- Several “pure language” wins are small enough that a single combined “Language additions in v1.27” PyScript playground (with a dropdown to pick the example) is probably better than five tiny demos.
v1.28.0 (already implemented - calibration only)
Tagline: “PWM on alif and stm32, new machine.CAN API, t-strings and weakref module.”
The existing /micropython-v1.28/index.html page uses:
- PWM -> Tier A (interactive frequency/duty canvas waveform)
- CAN -> Tier A (animated SVG bus topology)
- t-strings -> Tier B (live PyScript playground; explicitly enabled on the pyscript variant per tag)
- weakref -> Tier A + B hybrid (interactive GC visualiser;
weakrefis only enabled on the pyscript variant per tag)
Calibration takeaway: the existing page leans hard into Tier A for hardware features and Tier B for language features, with each section getting roughly equal real-estate. The PyScript playgrounds are textareas + Run buttons, not embedded REPLs - so the bar for a “Tier B” demo is “can be expressed as a self-contained ~10-line script”. This matches what’s proposed above.
Cross-cutting analysis
Recurring themes across v1.24 -> v1.27
- RISC-V march: every release adds RV32 capability (v1.24 native emitter, v1.25 inline asm, v1.26 emitter optimisations, v1.27 Zba opcodes + RV64 qemu, v1.28 Zcmp). A “RISC-V journey” timeline could span the whole
/releases/index. - ESP-IDF treadmill: v5.2.2 (1.24) -> 5.3/5.4 (1.25) -> 5.4.2 (1.26) -> 5.5.1 (1.27). Each bump changes ESP32 code size visibly.
- New STM32 families per release: H7 octospi (1.24), N6 (1.26), U5 + F469 (1.27).
- Native emitter / viper improvements in every release - good candidate for a single cross-release “performance” article.
- mpremote ergonomics: hash-based recursive copy (1.24),
rm -r+romfs(1.25),fs tree+ betterdf+ ESP CDC detection (1.26), DTR/RTS fixes (1.27). machine.*API standardisation:ipconfig(1.24), default I2C/SPI/UART buses (1.25),I2CTarget+Counter/Encoder(1.26), hard timers everywhere (1.27),PWMeverywhere +CANstandardised (1.28). This is arguably the meta-narrative of the four releases.- Zephyr port maturation: threading (1.24),
Timer/WDT(1.25), PWM/UART/SPI/I2C (1.26), ADC + native FS VFS (1.27). - asyncio improvements in every release (1.24 webassembly top-level await, 1.25 implicit, 1.26 scheduler fixes, 1.27 IPv6 server).
- Floating point + native emitter accuracy is a story specifically for 1.26 but builds on 1.25’s compiler infrastructure.
- TinyUSB consolidation: started in 1.24 (CDC), continues in every release; in 1.27 even stm32 starts adopting TinyUSB optionally.
PyScript opportunity ranking (most -> least in-browser-runnable content)
- v1.26.0 - HIGHEST. Strong language additions (
__set_name__,__all__in star import,:_b/o/xseparators, slice-on-stack, array-from-iterable) plus the float accuracy story is genuinely interactive. The hardware features (I2CTarget,Counter) make excellent Tier-A counterpoints, but there’s plenty for PyScript to chew on. - v1.25.0 - HIGH. ROMFS itself is hardware-flavoured but
marshal, multiple core language tweaks (startswithtuples, 2-argnext,vfs.mount()no-args,sys.implementation._build), and DTLS-as-API-shape all surface in PyScript. Caveat: needs to confirmmarshalis in the pyscript variant build. - v1.27.0 - MEDIUM. Several language additions (
restart/end, dict-viewbool/len, IPv6 inasyncio.start_server, relative imports in__import__,sysalways available) but each one is small. The release’s headline is hardware (ESP32-C5/P4, STM32U5) and meta (port tiers, test suite) - hard to PyScript. Best approach is one combined “language tweaks” playground. - v1.24.0 - LOWEST. The headline features are all hardware/port-level (RP2350, ESP32-C6, RISC-V emitter, TinyUSB unification, UART IRQ, PPP,
ipconfig). Pure-Python wins are limited to f-string concat, raw f-strings,RingIO, and thesys.exitsemantics shift. Plenty of Tier-A material - and the explicit “webassembly: better asyncio support, top-level await of Task and Event” line makes top-level-await the standout PyScript demo for this release.
Recommendations for the /releases/ index page
- Use the v1.27 port Tier chart as the navigation widget itself - one click jumps to the release page where that port grew/changed.
- A single “RISC-V across the releases” timeline at the top of the index ties all four releases together.
- Each release page should keep the v1.28 layout: hero -> 3-5 sections (mix of A/B) -> “by the numbers” footer -> board grid.
- Reuse a single PyScript bootstrap shared across pages - the pyscript variant build is the same for v1.25-v1.28 (v1.24 webassembly port had only “better asyncio” in the tag), so demos can target a recent build for older releases by acknowledging “this is what running it today looks like”.
