Overzicht van turbo
turbo is een toolset die CircuitPython-code aanzienlijk versnelt door gebruik te maken van de native en viper machine-code emitters. Omdat veel boards oorspronkelijk alleen bytecode ondersteunen, biedt turbo een oplossing via een combinatie van aangepaste firmware en een host CLI.
Werking
- Firmware: Gebruikt een loader (via
CIRCUITPYLOADNATIVE=1) die native code kan laden zonder dat er een compiler op het board zelf nodig is.
- Host CLI: Automatiseert het proces van compileren met
mpy-cross en het installeren van de modules op het board.
- Bestandsstructuur: Broncode wordt in een
src/ map geplaatst, terwijl de gecompileerde .mpy bestanden in lib/turbo/<arch>/ landen. Een shim-bestand (turbo.py) past de sys.path aan zodat de gecompileerde versie voorrang krijgt op de broncode.
Prestaties en Compatibiliteit
De prestatiewinst is enorm: bij een Mandelbrot-test draait een viper inner loop tussen de 19x en 72x sneller dan standaard bytecode. De tool is getest en geverifieerd op diverse architecturen, waaronder:
- ARM Cortex-M (RP2040, RP2350, nRF52840, STM32F405)
- Xtensa (ESP32-S2, ESP32-S3)
- RISC-V (ESP32-C5)
Toekomst
Er wordt gewerkt aan een webinterface via WebSerial, waarmee gebruikers hun board kunnen detecteren, code kunnen analyseren en optimalisaties direct vanuit de browser kunnen uitvoeren.
turbo: Gecompileerde versnelling voor CircuitPython
CircuitPython bevat al @micropython.native and @micropython.viper. Er hoeft niets aan de taal te veranderen. Wat ontbrak, was een board dat machinecode kan laden en een tool die deze code genereert. turbo biedt beide:
- Firmware gebouwd met
CIRCUITPYLOADNATIVE=1, wat een loader van 2 tot 3 KB toevoegt zonder een on-board compiler.
- Een host CLI die je module compileert met de officiële
mpy-cross en deze installeert op een plek waar de importer deze kan vinden.
Op de twaalf boards die tot nu toe zijn gemeten, draait een viper inner loop 19x tot 72x sneller dan dezelfde code als bytecode.
Bestandsstructuur
De CLI verplaatst je bestanden nooit zelfstandig.
turbo init maakt een src/ map aan en plaatst daar de shim. Je verplaatst vervolgens de module die je wilt versnellen naar src/.
turbo build leest alleen uit src/ en schrijft naar lib/turbo/.
code.py wordt door geen enkele opdracht aangeraast.
Vergelijking van de mappenstructuur
Vóór turbo init + turbo build
CIRCUITPY/
├── code.py
└── pixels.py
Na turbo init + turbo build
CIRCUITPY/
├── code.py (ongewijzigd, blijft broncode)
├── lib/
│ ├── turbo.py (DE SHIM: nieuw, 49 regels)
│ └── turbo/
│ ├── turbo.json (manifest: src sha256, formaten)
│ └── armv7emsp/
│ ├── pixels.mpy (geïnstalleerde winnaar: viper)
│ ├── pixels.viper.mpy (bewaarde kandidaten)
│ └── pixels.native.mpy
└── src/
└── pixels.py (door JOU hierheen verplaatst)
Niets anders op de schijf verandert. Omdat circup de map lib/turbo/<arch>/ letterlijk kopieert, kan dit als een normale bibliotheek worden verzonden.
Werking op de host
Het proces verloopt als volgt voor een bestand zoals src/pixels.py:
- Markering: De
@turbo.viper marker wordt herkend (dit doet niets op het board, alleen op de host).
- Herschrijven: Er wordt een tijdelijke kopie gemaakt waarin
@turbo.viper wordt omgezet naar @micropython.viper (en apart voor @micropython.native). Je originele bestand wordt niet bewerkt.
- Compileren: De tool voert
mpy-cross -march=armv7emsp twee keer uit:
- Resultaat 1:
lib/turbo/armv7emsp/pixels.viper.mpy (639 B)
- Resultaat 2:
lib/turbo/armv7emsp/pixels.native.mpy (1,204 B)
- Installatie: De snelste versie wordt geïnstalleerd onder de eenvoudige naam
lib/turbo/armv7emsp/pixels.mpy.
Werking op het board tijdens boot
Wanneer het board opstart, gebeurt het volgende:
code.py wordt uitgevoerd (altijd als broncode, nooit gecompileerd).
import turbo wordt aangeroepen:
- De shim (
lib/turbo.py) leest sys.implementation._mpy >> 10 (bijv. resultaat 7).
- Waarde
7 wordt gekoppeld aan de architectuur "armv7emsp".
- De shim controleert of
/lib/turbo/armv7emsp bestaat.
- Zo ja, dan wordt deze map, samen met
/src, vooraan in sys.path geplaatst.
sys.path BEFORE: ["", "/", ".frozen", "/lib"] sys.path AFTER: ["/lib/turbo/armv7emsp", "/src", "", "/", ".frozen", "/lib"]
import pixels wordt aangeroepen:
- De eerste hit is
/lib/turbo/armv7emsp/pixels.mpy → machinecode.
Belangrijk: De map src/ staat standaard niet in sys.path. Dit is bewust gedaan omdat CircuitPython in dezelfde directory altijd voorkeur geeft aan name.py boven name.mpy. Door de broncode te verbergen in een map die de importer niet direct ziet, werkt de versnelling zonder dat de importer zelf aangepast hoeft te worden.
Scenario's van importen
| Situatie | turbo.arch | Importeert vanuit |
| turbo firmware, arch directory gebouwd | armv7emsp | /lib/turbo/armv7emsp/pixels.mpy |
| turbo firmware, geen dir voor die arch | xtensawin | /src/pixels.py |
| stock firmware, geen native support | None | /src/pixels.py |
Consequenties:
- Als je
pixels.mpy verwijdert, landt de import op /src/pixels.py: het resultaat is identiek, maar trager.
code.py kan niet worden versneld, omdat dit via pyexec_file wordt uitgevoerd en niet via import.
Voorbeeld van een sessie
Verbatim van de farm Metro RP2040, 2026-09-08.
$ turbo doctor
board Adafruit Metro RP2040 adafruit_metro_rp2040
port /dev/ttyACM18
drive /media/sklarm/CIRCUITPY5
firmware CircuitPython 10.3.0-42-g3cdb20693f
_mpy 0x1306 arch armv6m · mpy 6.3 · native loader present
dev build of 10.3.0; using the 10.3.0 mpy-cross, abi checked below
toolchain ~/.cache/turbo/mpy-cross/10.3.0/linux-amd64/mpy-cross 1411 KB mpy v6.3
ready turbo build compiles -march=armv6m
$ turbo init --example
wrote lib/turbo.py shim, 49 lines, identity decorators on stock firmware
made src/ your source, kept off sys.path so it never shadows .mpy
made lib/turbo/armv6m/ where compiled modules land
wrote src/pixels.py mandelbrot, 12-bit fixed point, @turbo.viper
wrote code.py imports turbo, then pixels; prints the checksum
$ turbo build
pixels viper armv6m 603 B native 635 B
1 built, 1081 ms, copied 1 module, shim to /media/sklarm/CIRCUITPY5
$ turbo bench pixels
board: mpy v6.3 arch armv6m on /dev/ttyACM18
bytecode median 8335.3 ms value 407644
native median 4778.0 ms value 407644
viper median 422.9 ms value 407644
installed viper for armv6m (19.71x over bytecode)
De doctor functie haalt bij eerste gebruik de officiële mpy-cross op en cached deze, zodat er geen CircuitPython checkout of toolchain build nodig is. De waarde 407644 is een checksum; als een variant een andere checksum heeft, is het een ander programma en wordt deze niet geïnstalleerd.
De CLI bevindt zich nu in een eigen repository: mikeysklar/turbo-cli en zal beschikbaar komen op PyPI als adafruit-turbo.
Prestatiebenchmarks
De volgende resultaten zijn behaald met een Mandelbrot-test (160x120, 64 iteraties, mediane waarde van 8 metingen, in milliseconden).
| Board | Core | float bytecode | @native | @viper | viper / float |
| Metro M0 Express | Cortex-M0+ 48 MHz | 72,741 | 23,408 | 1,014 | 71.7x |
| Metro RP2040 | Cortex-M0+ 125 MHz | 13,942 | 4,739 | 384 | 36.3x |
| Metro M4 AirLift | Cortex-M4F 120 MHz | 11,221 | 3,536 | 431 | 26.0x |
| Feather nRF52840 | Cortex-M4F 64 MHz | 20,788 | 7,445 | 781 | 26.6x |
| Metro ESP32-S2 | Xtensa LX7 240 MHz | 7,438 | 2,110 | 206 | 36.1x |
| Metro RP2350 | Cortex-M33 150 MHz | 6,371 | 2,380 | 261 | 24.4x |
| Metro ESP32-S3 | Xtensa LX7 240 MHz | 4,873 | 1,708 | 186 | 26.2x |
| Feather STM32F405 | Cortex-M4F 168 MHz | 8,121 | 2,779 | 416 | 19.5x |
| ESP32-C5 DevKitC | RISC-V rv32imc 240 MHz | 7,591 | 1,809 | 172 | 44.0x |
| nRF54L15 DK | Cortex-M33 128 MHz | 10,233 | 2,836 | 349 | 29.3x |
| nRF54LM20 DK | Cortex-M33 128 MHz | 10,288 | 2,840 | 351 | 29.3x |
| EK-RA8D1 | Cortex-M85 480 MHz | 1,802 | 488 | 47 | 38.3x |
De snelheid van float bytecode is nagenoeg ongewijzigd (onder 0,1%) door de toevoeging van de loader. De volledige tabel is te vinden in docs/turbo-on-the-farm.md.
Handmatige Workflow
Voor de CLI bestond het proces uit de volgende handmatige stappen:
# Eenmalig per CircuitPython tag: mpy-cross en loader firmware bouwen
$ make -C mpy-cross -j4
$ make -C ports/raspberrypi BOARD=adafruit_metro_rp2350 CIRCUITPY_LOAD_NATIVE=1 -j4
# Per wijziging: compileren voor de core van het board, broncode buiten sys.path houden
$ ~/cp-1030/mpy-cross/build/mpy-cross -march=armv7emsp src/pixels.py -o lib/turbo/armv7emsp/pixels.mpy
$ cp lib/turbo.py lib/turbo/armv7emsp/pixels.mpy src/pixels.py -> CIRCUITPY
# Het image: firmware plus project als één UF2
$ folder2uf2 --board adafruit_metro_rp2350 --combine firmware.uf2 -o turbo-demo.uf2 turbo-demo/
# Bewijzen: benchmarks draaien
$ python3 tools/pyboard.py /dev/cu.usbmodem14201 bench.py
De CLI automatiseert bijna al deze complexe stappen.
Firmware verkrijgen
Download de .uf2 voor jouw board uit de nieuwste cp-<versie> release, of via de command line: gh release download cp-10.3.0 -R mikeysklar/turbo -p 'metro_esp32s3.uf2'
Elke release bevat ook een bijbehorende mpy-cross voor Linux en een BUILD.txt per board met de exacte commit, toolchain en flags. Instructies voor het bouwen van een nieuwe tag staan in docs/build.md.
Huidige Status
- ESP32-S2 en ESP32-S3 (Xtensa): Werkend, geverifieerd op hardware.
- ESP32-C5 (RISC-V): Werkend, geverifieerd op hardware (172 ms op de Mandelbrot loop, 44x sneller dan float bytecode).
- ESP32-C3 / C6 / P4: Gecompileerd, maar nog niet getest op hardware.
Loader-only model
Sinds 2026-09-06 wordt het "loader-only" model gehanteerd. Omdat turbo op de host compileert met mpy-cross, heeft het board alleen de native .mpy loader nodig en niet de on-board emitter. CIRCUITPYLOADNATIVE=1 bouwt dit:
- Gebruik van 2 tot 3 KB meer dan stock (in plaats van 20 tot 50 KB).
- Dezelfde viper-snelheid.
@micropython.viper vanuit broncode veroorzaakt een SyntaxError.
Ondersteunde Boards
| Board | Arch | Native / viper | Bron | In release |
| Metro RP2040 | Thumb (armv6m) | loader-only, no emitter | fork branch | emitter build |
| Metro RP2350 | Thumb (armv7em) | loader-only, no emitter | fork branch | emitter build |
| Feather nRF52840 | Thumb (armv7em) | loader-only, no emitter | fork branch | emitter build |
| Feather STM32F405 | Thumb (armv7em) | loader-only, no emitter | fork branch | emitter build |
| Metro M0 Express | Thumb (armv6m) | loader-only, no emitter | fork branch | niet nog niet |
| Metro M4 AirLift | Thumb (armv7em) | loader-only, no emitter | fork branch | niet nog niet |
| EK-RA8D1 | Thumb (armv7emdp) | werkt, D-cache aan | fork branch | niet nog niet |
| Metro ESP32-S2 | Xtensa LX7 | loader-only, no emitter | fork branch | emitter build |
| Metro ESP32-S3 | Xtensa LX7 | loader-only, no emitter | fork branch | emitter build |
| ESP32-C5 DevKitC | RISC-V (rv32imc) | werkt | fork branch | niet nog niet |
| ESP32-C3/C6/P4 | RISC-V | niet getest | fork branch | niet nog niet |
ESP32 Firmware Wijzigingen
Er zijn vijf commits gedaan op de esp32-native branch van de CircuitPython fork: 1 Selectie van de native emitter op basis van architectuur, niet alleen Thumb. 2 Commit van native machinecode in executeerbare RAM (de GC heap is niet executeerbaar). 3 Geheugenbescherming uitschakelen wanneer native code is ingeschakeld. 4 De Xtensa assembler laten compileren onder CircuitPython's warning flags. 5 De ARM Thumb interworking bit niet instellen op non-ARM pointers.
De laatste wijziging loste een bug op waarbij MICROPYMAKEPOINTER_CALLABLE de ARM Thumb bit in elke codepointer plaatste, wat op Xtensa leidde tot een sprong naar een oneven adres en een hard-fault bij de eerste native call.
Architectuur ID's
De waarde van sys.implementation._mpy >> 10 correspondeert met de volgende architecturen:
| ID | Arch | ID | Arch |
| 4 | armv6m | 8 | armv7emdp |
| 5 | armv7m | 9 | xtensa |
| 6 | armv7em | 10 | xtensawin |
| 7 | armv7emsp | 11 | rv32imc |
Inhoud van deze repository
shim/turbo.py: De on-board @turbo decorator.
cli/turbo_cli.py: De originele host tool (actieve ontwikkeling is verplaatst naar mikeysklar/turbo-cli).
examples/mandelbrot/: De benchmark gebruikt voor de bovenstaande cijfers.
docs/: Documentatie over conversieprocedures, farm notes, applicaties, werklogboek, analyses en build-instructies.
.github/workflows/firmware.yml: Bouwt alle boards en publiceert de release.
Toekomstige ontwikkelingen: Webinterface
Er wordt gewerkt aan een webpagina-versie van de CLI. Deze zal gebruikmaken van WebSerial om:
- Het board te detecteren.
- Een
.py bestand te lezen.
- Te adviseren welke functies gecompileerd moeten worden.
- De installatie uit te voeren en de snelheid voor en na de optimalisatie te meten op het eigen board van de gebruiker.
Een skelet hiervan is beschikbaar in mikeysklar/turbo-web.
turbo: Gecompileerde versnelling voor CircuitPython
CircuitPython bevat al @micropython.native and @micropython.viper. Er hoeft niets aan de taal te veranderen. Wat ontbrak, was een board dat machinecode kan laden en een tool die deze code genereert. turbo biedt beide:
- Firmware gebouwd met
CIRCUITPYLOADNATIVE=1, wat een loader van 2 tot 3 KB toevoegt zonder een on-board compiler.
- Een host CLI die je module compileert met de officiële
mpy-cross en deze installeert op een plek waar de importer deze kan vinden.
Op de twaalf boards die tot nu toe zijn gemeten, draait een viper inner loop 19x tot 72x sneller dan dezelfde code als bytecode.
Bestandsstructuur
De CLI verplaatst je bestanden nooit zelfstandig.
turbo init maakt een src/ map aan en plaatst daar de shim. Je verplaatst vervolgens de module die je wilt versnellen naar src/.
turbo build leest alleen uit src/ en schrijft naar lib/turbo/.
code.py wordt door geen enkele opdracht aangeraast.
Vergelijking van de mappenstructuur
Vóór turbo init + turbo build
CIRCUITPY/
├── code.py
└── pixels.py
Na turbo init + turbo build
CIRCUITPY/
├── code.py (ongewijzigd, blijft broncode)
├── lib/
│ ├── turbo.py (DE SHIM: nieuw, 49 regels)
│ └── turbo/
│ ├── turbo.json (manifest: src sha256, formaten)
│ └── armv7emsp/
│ ├── pixels.mpy (geïnstalleerde winnaar: viper)
│ ├── pixels.viper.mpy (bewaarde kandidaten)
│ └── pixels.native.mpy
└── src/
└── pixels.py (door JOU hierheen verplaatst)
Niets anders op de schijf verandert. Omdat circup de map lib/turbo/<arch>/ letterlijk kopieert, kan dit als een normale bibliotheek worden verzonden.
Werking op de host
Het proces verloopt als volgt voor een bestand zoals src/pixels.py:
- Markering: De
@turbo.viper marker wordt herkend (dit doet niets op het board, alleen op de host).
- Herschrijven: Er wordt een tijdelijke kopie gemaakt waarin
@turbo.viper wordt omgezet naar @micropython.viper (en apart voor @micropython.native). Je originele bestand wordt niet bewerkt.
- Compileren: De tool voert
mpy-cross -march=armv7emsp twee keer uit:
- Resultaat 1:
lib/turbo/armv7emsp/pixels.viper.mpy (639 B)
- Resultaat 2:
lib/turbo/armv7emsp/pixels.native.mpy (1,204 B)
- Installatie: De snelste versie wordt geïnstalleerd onder de eenvoudige naam
lib/turbo/armv7emsp/pixels.mpy.
Werking op het board tijdens boot
Wanneer het board opstart, gebeurt het volgende:
code.py wordt uitgevoerd (altijd als broncode, nooit gecompileerd).
import turbo wordt aangeroepen:
- De shim (
lib/turbo.py) leest sys.implementation._mpy >> 10 (bijv. resultaat 7).
- Waarde
7 wordt gekoppeld aan de architectuur "armv7emsp".
- De shim controleert of
/lib/turbo/armv7emsp bestaat.
- Zo ja, dan wordt deze map, samen met
/src, vooraan in sys.path geplaatst.
sys.path BEFORE: ["", "/", ".frozen", "/lib"] sys.path AFTER: ["/lib/turbo/armv7emsp", "/src", "", "/", ".frozen", "/lib"]
import pixels wordt aangeroepen:
- De eerste hit is
/lib/turbo/armv7emsp/pixels.mpy → machinecode.
Belangrijk: De map src/ staat standaard niet in sys.path. Dit is bewust gedaan omdat CircuitPython in dezelfde directory altijd voorkeur geeft aan name.py boven name.mpy. Door de broncode te verbergen in een map die de importer niet direct ziet, werkt de versnelling zonder dat de importer zelf aangepast hoeft te worden.
Scenario's van importen
| Situatie | turbo.arch | Importeert vanuit |
| turbo firmware, arch directory gebouwd | armv7emsp | /lib/turbo/armv7emsp/pixels.mpy |
| turbo firmware, geen dir voor die arch | xtensawin | /src/pixels.py |
| stock firmware, geen native support | None | /src/pixels.py |
Consequenties:
- Als je
pixels.mpy verwijdert, landt de import op /src/pixels.py: het resultaat is identiek, maar trager.
code.py kan niet worden versneld, omdat dit via pyexec_file wordt uitgevoerd en niet via import.
Voorbeeld van een sessie
Verbatim van de farm Metro RP2040, 2026-09-08.
$ turbo doctor
board Adafruit Metro RP2040 adafruit_metro_rp2040
port /dev/ttyACM18
drive /media/sklarm/CIRCUITPY5
firmware CircuitPython 10.3.0-42-g3cdb20693f
_mpy 0x1306 arch armv6m · mpy 6.3 · native loader present
dev build of 10.3.0; using the 10.3.0 mpy-cross, abi checked below
toolchain ~/.cache/turbo/mpy-cross/10.3.0/linux-amd64/mpy-cross 1411 KB mpy v6.3
ready turbo build compiles -march=armv6m
$ turbo init --example
wrote lib/turbo.py shim, 49 lines, identity decorators on stock firmware
made src/ your source, kept off sys.path so it never shadows .mpy
made lib/turbo/armv6m/ where compiled modules land
wrote src/pixels.py mandelbrot, 12-bit fixed point, @turbo.viper
wrote code.py imports turbo, then pixels; prints the checksum
$ turbo build
pixels viper armv6m 603 B native 635 B
1 built, 1081 ms, copied 1 module, shim to /media/sklarm/CIRCUITPY5
$ turbo bench pixels
board: mpy v6.3 arch armv6m on /dev/ttyACM18
bytecode median 8335.3 ms value 407644
native median 4778.0 ms value 407644
viper median 422.9 ms value 407644
installed viper for armv6m (19.71x over bytecode)
De doctor functie haalt bij eerste gebruik de officiële mpy-cross op en cached deze, zodat er geen CircuitPython checkout of toolchain build nodig is. De waarde 407644 is een checksum; als een variant een andere checksum heeft, is het een ander programma en wordt deze niet geïnstalleerd.
De CLI bevindt zich nu in een eigen repository: mikeysklar/turbo-cli en zal beschikbaar komen op PyPI als adafruit-turbo.
Prestatiebenchmarks
De volgende resultaten zijn behaald met een Mandelbrot-test (160x120, 64 iteraties, mediane waarde van 8 metingen, in milliseconden).
| Board | Core | float bytecode | @native | @viper | viper / float |
| Metro M0 Express | Cortex-M0+ 48 MHz | 72,741 | 23,408 | 1,014 | 71.7x |
| Metro RP2040 | Cortex-M0+ 125 MHz | 13,942 | 4,739 | 384 | 36.3x |
| Metro M4 AirLift | Cortex-M4F 120 MHz | 11,221 | 3,536 | 431 | 26.0x |
| Feather nRF52840 | Cortex-M4F 64 MHz | 20,788 | 7,445 | 781 | 26.6x |
| Metro ESP32-S2 | Xtensa LX7 240 MHz | 7,438 | 2,110 | 206 | 36.1x |
| Metro RP2350 | Cortex-M33 150 MHz | 6,371 | 2,380 | 261 | 24.4x |
| Metro ESP32-S3 | Xtensa LX7 240 MHz | 4,873 | 1,708 | 186 | 26.2x |
| Feather STM32F405 | Cortex-M4F 168 MHz | 8,121 | 2,779 | 416 | 19.5x |
| ESP32-C5 DevKitC | RISC-V rv32imc 240 MHz | 7,591 | 1,809 | 172 | 44.0x |
| nRF54L15 DK | Cortex-M33 128 MHz | 10,233 | 2,836 | 349 | 29.3x |
| nRF54LM20 DK | Cortex-M33 128 MHz | 10,288 | 2,840 | 351 | 29.3x |
| EK-RA8D1 | Cortex-M85 480 MHz | 1,802 | 488 | 47 | 38.3x |
De snelheid van float bytecode is nagenoeg ongewijzigd (onder 0,1%) door de toevoeging van de loader. De volledige tabel is te vinden in docs/turbo-on-the-farm.md.
Handmatige Workflow
Voor de CLI bestond het proces uit de volgende handmatige stappen:
# Eenmalig per CircuitPython tag: mpy-cross en loader firmware bouwen
$ make -C mpy-cross -j4
$ make -C ports/raspberrypi BOARD=adafruit_metro_rp2350 CIRCUITPY_LOAD_NATIVE=1 -j4
# Per wijziging: compileren voor de core van het board, broncode buiten sys.path houden
$ ~/cp-1030/mpy-cross/build/mpy-cross -march=armv7emsp src/pixels.py -o lib/turbo/armv7emsp/pixels.mpy
$ cp lib/turbo.py lib/turbo/armv7emsp/pixels.mpy src/pixels.py -> CIRCUITPY
# Het image: firmware plus project als één UF2
$ folder2uf2 --board adafruit_metro_rp2350 --combine firmware.uf2 -o turbo-demo.uf2 turbo-demo/
# Bewijzen: benchmarks draaien
$ python3 tools/pyboard.py /dev/cu.usbmodem14201 bench.py
De CLI automatiseert bijna al deze complexe stappen.
Firmware verkrijgen
Download de .uf2 voor jouw board uit de nieuwste cp-<versie> release, of via de command line: gh release download cp-10.3.0 -R mikeysklar/turbo -p 'metro_esp32s3.uf2'
Elke release bevat ook een bijbehorende mpy-cross voor Linux en een BUILD.txt per board met de exacte commit, toolchain en flags. Instructies voor het bouwen van een nieuwe tag staan in docs/build.md.
Huidige Status
- ESP32-S2 en ESP32-S3 (Xtensa): Werkend, geverifieerd op hardware.
- ESP32-C5 (RISC-V): Werkend, geverifieerd op hardware (172 ms op de Mandelbrot loop, 44x sneller dan float bytecode).
- ESP32-C3 / C6 / P4: Gecompileerd, maar nog niet getest op hardware.
Loader-only model
Sinds 2026-09-06 wordt het "loader-only" model gehanteerd. Omdat turbo op de host compileert met mpy-cross, heeft het board alleen de native .mpy loader nodig en niet de on-board emitter. CIRCUITPYLOADNATIVE=1 bouwt dit:
- Gebruik van 2 tot 3 KB meer dan stock (in plaats van 20 tot 50 KB).
- Dezelfde viper-snelheid.
@micropython.viper vanuit broncode veroorzaakt een SyntaxError.
Ondersteunde Boards
| Board | Arch | Native / viper | Bron | In release |
| Metro RP2040 | Thumb (armv6m) | loader-only, no emitter | fork branch | emitter build |
| Metro RP2350 | Thumb (armv7em) | loader-only, no emitter | fork branch | emitter build |
| Feather nRF52840 | Thumb (armv7em) | loader-only, no emitter | fork branch | emitter build |
| Feather STM32F405 | Thumb (armv7em) | loader-only, no emitter | fork branch | emitter build |
| Metro M0 Express | Thumb (armv6m) | loader-only, no emitter | fork branch | niet nog niet |
| Metro M4 AirLift | Thumb (armv7em) | loader-only, no emitter | fork branch | niet nog niet |
| EK-RA8D1 | Thumb (armv7emdp) | werkt, D-cache aan | fork branch | niet nog niet |
| Metro ESP32-S2 | Xtensa LX7 | loader-only, no emitter | fork branch | emitter build |
| Metro ESP32-S3 | Xtensa LX7 | loader-only, no emitter | fork branch | emitter build |
| ESP32-C5 DevKitC | RISC-V (rv32imc) | werkt | fork branch | niet nog niet |
| ESP32-C3/C6/P4 | RISC-V | niet getest | fork branch | niet nog niet |
ESP32 Firmware Wijzigingen
Er zijn vijf commits gedaan op de esp32-native branch van de CircuitPython fork: 1 Selectie van de native emitter op basis van architectuur, niet alleen Thumb. 2 Commit van native machinecode in executeerbare RAM (de GC heap is niet executeerbaar). 3 Geheugenbescherming uitschakelen wanneer native code is ingeschakeld. 4 De Xtensa assembler laten compileren onder CircuitPython's warning flags. 5 De ARM Thumb interworking bit niet instellen op non-ARM pointers.
De laatste wijziging loste een bug op waarbij MICROPYMAKEPOINTER_CALLABLE de ARM Thumb bit in elke codepointer plaatste, wat op Xtensa leidde tot een sprong naar een oneven adres en een hard-fault bij de eerste native call.
Architectuur ID's
De waarde van sys.implementation._mpy >> 10 correspondeert met de volgende architecturen:
| ID | Arch | ID | Arch |
| 4 | armv6m | 8 | armv7emdp |
| 5 | armv7m | 9 | xtensa |
| 6 | armv7em | 10 | xtensawin |
| 7 | armv7emsp | 11 | rv32imc |
Inhoud van deze repository
shim/turbo.py: De on-board @turbo decorator.
cli/turbo_cli.py: De originele host tool (actieve ontwikkeling is verplaatst naar mikeysklar/turbo-cli).
examples/mandelbrot/: De benchmark gebruikt voor de bovenstaande cijfers.
docs/: Documentatie over conversieprocedures, farm notes, applicaties, werklogboek, analyses en build-instructies.
.github/workflows/firmware.yml: Bouwt alle boards en publiceert de release.
Toekomstige ontwikkelingen: Webinterface
Er wordt gewerkt aan een webpagina-versie van de CLI. Deze zal gebruikmaken van WebSerial om:
- Het board te detecteren.
- Een
.py bestand te lezen.
- Te adviseren welke functies gecompileerd moeten worden.
- De installatie uit te voeren en de snelheid voor en na de optimalisatie te meten op het eigen board van de gebruiker.
Een skelet hiervan is beschikbaar in mikeysklar/turbo-web.