Tiny PHP runtime (≈1–2 MB) baked straight into firmware. Targets ESP32 (ESP-IDF) and Raspberry Pi Pico / RP2040 (Pico SDK) for IoT scripting without Linux.
- Familiar PHP syntax for quick device scripts.
- Static firmware: no shell, no dynamic loading, optional VFS only.
- Deterministic footprint: ≤2 MB VM, ≤256 KB bytecode heap.
- Zend-lite VM: compact opcode interpreter.
- AOT compiler (
microphpc): PHP → MBC bytecode → embedded as aconst uint8_t[]. - Built-ins for MCU I/O: GPIO, PWM, ADC, I2C, SPI, UART, RTC, and Wi-Fi/TCP on ESP32.
- Memory: arenas for zvals/arrays/strings, RC + COW, interned ids, optional exceptions.
- No
eval, dynamicinclude/require, PCRE, iconv/mbstring, PDO/curl/streams zoo.
your.php --microphpc--> your.mbc --objgen--> embedded_program.c → firmware.bin
- VM/core: ✅ arrays, strings, closures, errors
- HAL: ✅ GPIO/PWM/UART |
⚠️ I2C/SPI alpha | 🌐 Wi-Fi (ESP32 alpha) - Tooling: ✅
microphpc,mbc-inspect,objgen.py - Boards: ✅ ESP32-S3 | ✅ RP2040 | ☑️ ESP32-C3 (CI pending)
- ESP32: ESP-IDF v5.x (
idf.py,xtensa-esp32-elforriscv32-esp-elf) - RP2040: Pico SDK +
arm-none-eabi-gcc - Host: CMake ≥3.20, Python ≥3.9, PHP ≥8.1 (lint only)
git clone https://github.com/makalin/microphp.git
cd microphp/tools/microphpc
cmake -B build -S .
cmake --build build --config Releaseecho '<?php gpio_write(2,true); sleep_ms(500); gpio_write(2,false); ?>' > examples/blink.php
./build/microphpc examples/blink.php -o out/blink.mbccd ../../targets/esp32
python tools/objgen.py ../../out/blink.mbc > main/embedded_program.c
idf.py set-target esp32s3
idf.py build flash monitorcd ../rp2040
cmake -B build -S .
cmake --build build --config Release
picotool load -x build/microphp.uf2<?php
gpio_mode(2, OUTPUT);
while (true) {
gpio_write(2, true); sleep_ms(200);
gpio_write(2, false); sleep_ms(800);
}<?php
$p = pwm_open(0, pin: 15, freq_hz: 5000, duty: 0.0);
for ($d=0.0; $d<=1.0; $d+=0.02) { pwm_set($p,$d); sleep_ms(20); }
for ($d=1.0; $d>=0.0; $d-=0.02) { pwm_set($p,$d); sleep_ms(20); }<?php
$i2c = i2c_open(0, scl:22, sda:21, speed:400000);
i2c_write($i2c, 0x48, [0x00]);
$raw = i2c_read($i2c, 0x48, 2);
$temp = (($raw[0] << 4) | ($raw[1] >> 4)) * 0.0625;
printf("T=%.2f C\n", $temp);<?php
wifi_connect(ssid:"SSID", pass:"PASS");
$s = http_listen(80);
while ($c = http_accept($s, 5000)) {
$req = http_read($c);
http_write($c, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello micro-PHP");
http_close($c);
}- Time:
sleep_ms(int),millis(): int - GPIO:
gpio_mode(pin,int),gpio_write(pin,bool),gpio_read(pin): bool - PWM:
pwm_open(ch,pin,freq_hz,duty),pwm_set(h,duty),pwm_close(h) - UART:
uart_open(id,baud),uart_read(h,n),uart_write(h,bytes) - I2C/SPI:
i2c_open/read/write,spi_txrx - Net/ESP32:
wifi_connect,tcp_*,udp_*,http_*,net_time_sync - RTC/Flash:
rtc_now(),kv_get/kv_set(tiny flash KV)
| Option | Default | Notes |
|---|---|---|
MICROPHP_EXCEPTIONS |
ON | Disable to save ~8–20 KB |
MICROPHP_FLOAT64 |
ON | OFF → float32, faster/smaller |
MICROPHP_STDIO |
ON | UART logging |
MICROPHP_NET |
OFF | ESP32 networking |
MICROPHP_KVSTORE |
ON | Flash KV store |
Memory knobs: MICROPHP_STR_ARENA_KB (128), MICROPHP_ARRAY_ARENA_KB (128), MICROPHP_STACK_KB (24), MICROPHP_TASKS_MAX (4).
- Array push 1e5: ~45 ms
- String concat 1e5 (8 B): ~64 ms
- GPIO tight toggle: ~1.1 MHz effective
*Synthetic; varies by config/board.
Can I run WordPress? No—this is an embedded subset. Think small, single-purpose scripts. Filesystem? Optional RAM/flash VFS; typical flow embeds bytecode. “Hello, world” size? ~1.6 MB runtime (ESP32, no NET) + ~0.5–2 KB bytecode.
- Keep features behind toggles; every byte counts.
- Include size diff and
.mapexcerpts in PRs. - Add example +
mbc-inspectoutput for new built-ins.
- Sandboxed VFS (ramfs/kvfs)
- TLS via mbedTLS (ESP32)
.mpharbundler (single blob)- Super-op fusion in
microphpc -O3 - On-target trace profiler & flamegraph dump
MIT (runtime & tools). Vendor HALs retain their licenses.
/core # VM, zval, arrays, strings, opcodes
/hal # esp32, rp2040 ports
/tools # microphpc, mbc-inspect, objgen
/targets # firmware projects (ESP-IDF, Pico SDK)
/examples # blink, pwm, i2c, http, kv, uart
/docs # internals, opcodes, ABI
-
Core design & implementation: @makalin
-
PHP inspiration: PHP Group and the Zend Engine architecture
-
MCU SDKs:
- ESP-IDF (ESP32)
- Raspberry Pi Pico SDK (RP2040)
-
Toolchain support:
xtensa-esp32-elfandriscv32-esp-elfGCC portsarm-none-eabi-gccfor ARM Cortex-M0+
-
Community inspiration: lightweight interpreters like MicroPython and Lua RTOS
-
Contributors: see GitHub contributors
🐾 micro-PHP — Scripting the tiny world, one byte at a time.