Changelog#
v0.1.0a2 — Second Alpha#
Python-on-bare-metal becomes substantially more faithful to Python. ~40 features and 90+ fixes across the compiler and the AVR backend.
Language fidelity#
Integer arithmetic promotion (promote-and-truncate) —
+/-/*/<<promote to the next wider type so same-width math never silently overflows (uint8 255 + 45 == 300). The declared type is a storage width; narrowing happens only at an explicit store or cast.uint8(a + b)is the fixed-width escape hatch. See Type System.True division —
/now always yields afloat(Python 3 semantics);//is integer division. Integer operands to/produce a warning that the float runtime is linked.Real
None—Noneis a genuine null literal, no longer the integer-1;is None/== Nonechecks work on reference / optional-typed values.Out-of-range integer literals and folded arithmetic constants are now rejected at compile time (e.g. a constant
uint8add that overflows is aCompileError).x ** constwith a runtime base lowers to repeated multiplication.
f-strings#
print(f"..."),uart.write_str(f"...")/uart.println(f"...")andlcd.print_str(f"...")now accept runtime interpolations, lowered to direct stream writes — no heap, no format buffer.Format specs:
{x:02x},{x:X},{x:08b},{x:o},{x:5d},{x:04d}.
Exceptions (overhauled)#
Full
try/except/else/finally, withfinallyrunning on every exit path: success, caught, propagation,return,break,continue, and from within handlers (including abreak/returninfinallythat discards the in-flight exception).Propagation through any depth — to the enclosing
try, the caller, or a halt atmain. The previous “single nesting level per function” limit is gone.Bare
raisere-raises the active exception;ZeroDivisionError(builtin, code 6) is raised on a runtime///%by zero.Builtin exceptions are real Python builtins — no redeclaration in the stdlib; the exception model rides the AVR T-flag (
SET/CLT/BRTS), notsetjmp/longjmp(superseding the a1 description below).
Compiler / backend#
Functions may now take more than five arguments — overflow arguments pass through a fixed SRAM spill region.
Runtime-indexed local arrays inside
@inlinefunctions; closures captured by@inline(including nested andnonlocal); slice-to-inferred-arrayb = a[lo:hi].32-bit signed widening, 32-bit multiply (
__mul32), and signed floor-div / mod runtime routines corrected; arithmetic right shift sign-extends on whole-byte shifts.ISR-shared globals promoted to GPIOR registers; flash-string-by-reference; ISR context save now covers R20–R23 and the Z pointer; out-of-range
@interruptvectors are rejected.An unhandled propagated exception now produces a loud halt (
E:<TypeName>to UART0, thencli; rjmp .-2) instead of silently continuing.
Compatibility layers#
pymcu-micropythonandpymcu-circuitpythonshims compile unmodified under the new promotion / true-division model; their float-returning helpers (millis() / 1000.0, ADC-to-voltage divisions) are now correctly typed asfloat.
v0.1 — First Public Alpha#
Language#
try / except / raise / finally— AVR targets via avr-libcsetjmp/longjmp; single nesting level per function; exception codes imported frompymcu.exceptionsValueError,TypeError,IndexError,KeyError,NotImplementedErrorare now builtins — no import required, identical to CPython;pymcu.exceptionsstill exports the codes for IDE support and explicit imports from library codeCompileErrorintrinsic —raise CompileError("msg")aborts compilation with aCompileError:diagnostic; never generates runtime code; used in HAL modules for unsupported arch/chip guards; cannot be caught bytry/exceptNotImplementedErroradded topymcu.exceptions(code 5)
Compiler#
HAL ZCA configuration parameters typed as
const—Pin(name, mode)now requiresmode: const[uint8];if mode == 2:branches fold at compile time; open-drain mode on unsupported targets aborts withCompileError: Open-drain mode not supported on AVRArchitectureErrorC# class — mapsraise CompileError(...)in Python source to a compiler diagnostic withTypeName = "CompileError"; emitted by all HAL modules for unsupported arch/chip combinations
AVR backend#
Unhandled exception UART output — when a
raisereaches__pymcu_unhandled_exnwith no activeexcepthandler, the runtime prints"E:<TypeName>\r\n"to UART0 (if initialized) then halts withcli; rjmp .-2; only exception types actually raised in the program have their name strings emitted in flash; no overhead when noraiseis present in the program; chips without standard UART0 (attiny85 etc.) emit only the halt loop
RP2040 / ARM backend (new, alpha)#
New
pymcu-armpackage adds therp2040target (Raspberry Pi Pico) — lowers PyMCU’s target-agnostic IR to LLVM IR (thumbv6m-none-eabi, Cortex-M0+) and drives an LLVM toolchain (opt→llc→ld.lld→llvm-objcopy) to a flat flash image (dist/firmware.bin, generic crc32 boot2 at offset 0)Supported HAL on RP2040:
pymcu.hal.gpio.Pin(single-cycle IO) andpymcu.hal.uart.UART(PL011) on core 0;delay_ms/delay_usvia the hardware microsecond TIMERMicroPython (
machine.Pin/machine.UART) and CircuitPython (board,digitalio,busio) shims compile unmodified to RP2040 firmwareLLVM tools resolved from the
pymcu-arm-toolchainwheel or a system LLVMNot yet on this backend: GC
list[T], exceptions, soft-float, dual-core,@extern, and every peripheral beyond GPIO/UART0 (SPI, I2C, PWM, ADC, PIO, USB, timers, EEPROM, watchdog)Firmware images are validated headlessly by the RP2040Sharp emulator (
PicoSimulation.LoadFlash) in CI
HAL#
pymcu.hal.spi,pymcu.hal.eeprom,pymcu.hal.watchdog,pymcu.hal.power— all unsupported arch/chip fallbacks now raiseCompileError(replaces silentreturn 0/ missing defaults); allmatch __CHIP__blocks havecase _:guards
Language (core)#
if / elif / else,while,for,match / case,def,class,return,pass,global,with,assert,raisefor i in range(n),for x in array,for i, x in enumerate(iterable),for x, y in zip(a, b)Fixed-size arrays
arr: uint8[N], constant and variable indexing, slice indexingTuple literals, tuple unpacking, multi-return functions
match / caseOR patterns, guardif cond, sequence patterns, capture patterns@property/@name.setter, single-level ZCA class inheritance,super(),class Foo(Enum)with obj:/with a as x, b as y:,lambda x: expr(no capture),nonlocalin@inlinein/not in,is/is not,divmod,bitcast,hex,bin,sum,any,allbytesliteralb"\x00",bytearray,int.from_bytesRaw strings
r"\n",str(n)compile-time,pow/**Extended unpacking
first, *rest = tup, nested list comprehensions,iffilter in comprehensions__name__guard (if __name__ == "__main__":)Dunder operator overloading (
__add__,__sub__, comparisons, bitwise,__len__, etc.)@extern("symbol")— external C symbol interop with AVR ABI
MCU extensions#
uint8 / int8 / uint16 / int16 / uint32 / int32typed annotations (required)intbuilt-in maps toint16ptr[T]/const[T],asm("instr"),@inline,@interrupt(vector)delay_ms(n)/delay_us(n),millis()/micros()__CHIP__/__FREQ__compile-time constants
HAL (ATmega328P)#
pymcu.hal.gpio—Pin: high/low/toggle/value/irq/pulse_inpymcu.hal.uart—UART: write/read/read_line/write_str/println/print_byte/available + RX interruptpymcu.hal.adc—AnalogPin: poll + interrupt; channels"PC0"–"PC5","TEMP"(internal sensor),"VBG","ADC8"pymcu.hal.timer—Timer(n, prescaler), Timer0/1/2, CTC modepymcu.hal.pwm—PWM: start/stop/set_duty/set_freqpymcu.hal.spi—SPI+SoftSPIpymcu.hal.i2c—I2C+SoftI2C,write_to/read_from/write_bytes/writeto_mem/readfrom_mempymcu.hal.eeprom—EEPROM: write/readpymcu.hal.watchdog—Watchdog: enable/disable/feedpymcu.hal.power—sleep_idle/sleep_adc_noise/sleep_power_down/sleep_power_save/sleep_standby/sleep_extended_standby
Drivers#
pymcu.drivers.dht11— DHT11 temperature + humiditypymcu.drivers.ds18b20— DS18B20 1-Wire precision temperature (12-bit)pymcu.drivers.lcd— HD44780 LCD (4-bit parallel), classLCDpymcu.drivers.ssd1306— SSD1306 OLED (I2C, 128×64)pymcu.drivers.max7219— MAX7219 8×8 LED matrix (SPI)pymcu.drivers.bmp280— BMP280 barometer (I2C)pymcu.drivers.neopixel— WS2812 NeoPixel
Compatibility layers#
pymcu.compat.micropython—machine,utime,micropythonmodulespymcu.compat.circuitpython—board,digitalio,analogio,pwmio,timemodules
Boards#
pymcu.boards.arduino_uno— D0–D13, A0–A5, LED_BUILTINpymcu.boards.arduino_mega— D0–D53, A0–A15, LED_BUILTINpymcu.boards.arduino_leonardo— D0–D13, A0–A5, LED_BUILTIN (CLI board key for the 32U4 isarduino_micro)
Toolchain#
Programmer plugin system — custom backends via
pymcu.pluginsentry-point group[tool.pymcu.ffi]— C/C++ interop: sources, include_dirs, cflags