AGENTS.md
August 12, 2026 · View on GitHub
Native MicroPython display interface modules for PyDevices displaydev (USER_C_MODULES).
Portable code in src/ports/common/; SoC code under src/ports/<mp-port>/;
desktop SDL (usdl2) under src/ports/desktop/usdl2/. CircuitPython: MCU
interfaces stay on stock CP; only usdl2 uses ./apply_cp_patches.sh (unix).
Before editing lifecycle / soft-reset / a new board bring-up, read:
- docs/idempotent-lifecycle.md — required
deinit/ soft-reset contract (implemented for all real backends) - docs/soft-reset-and-bring-up.md — proven failure modes and methods from ESP32-P4
mipidsiand Qualia S3dotclockframebuffer.DotClockFramebuffer(+ LVGL); applies to other ports/interfaces - docs/port-matrix.md — module/port matrix and pydevices board-config map
Those two interfaces are the reference bring-ups: keep their scanout / blit / attr / soft-reset patterns when changing siblings.
Layout
| Path | Contents |
|---|---|
src/include/ | Public headers (displayif/ subdir) |
src/ports/ | Port C sources + per-port micropython.mk / .cmake (common/, esp32/, desktop/usdl2/, …) |
src/circuitpython_spike/ | CP unix spike for usdl2 (copied by apply_cp_patches.sh) |
docs/ | Markdown docs (root keeps README.md and AGENTS.md only) |
docs/ports/ | Per-port notes moved from former ports/*/README.md |
tests/ | Unit tests only (e.g. test_lifecycle_api.py) |
tools/ | Developer / hardware smoke tests (*_smoke.py), test_usdl2.py, sdl2_dev_env.sh |
Root micropython.mk / micropython.cmake stay at the repo root for USER_C_MODULES.
Desktop also: root circuitpython.mk + apply_cp_patches.sh (unix usdl2 only).
Hard rules
- Fix root causes in displayif (or the owning binding). Do not require hard reset, and do not special-case pydevices board configs to avoid second init.
- Do not patch
micropython/for soft-reset teardown when a usermod--wrapor registry hook will do (see soft-reset docs). Do not commit upstream MicroPython trees. - Every accelerated backend that owns DMA/IRQ/PIO/SDK handles must register with
displayif_register_soft_reset()and tear down from the same path used bydeinit/__del__/ idempotent ctors. - Desktop
usdl2registers the same way (SDL timers +SDL_Quit); wired on unix/windows MP and CP unix. - Host teardowns run from
--wrap=gc_sweep_all(before the heap is wiped). They must notm_freeGC memory — only release non-GC host resources.
Build / flash (agent workflow)
Public docs stay sibling-clone + stock make / idf.py. When working with a connected MCU via mpftp:
mpftp firmware build --port esp32 --board ESP32_GENERIC_P4 --variant C6_WIFI
mpftp firmware flash -d COM4
Prefer mpftp for board serial / firmware when that skill/session is available; do not assume build_mp.sh for MCU flash.
Soft-reset smoke (minimum)
After changing any host teardown or wrap:
- Construct the interface (or
import board_config/ example). - Soft-reset (
mpftp soft-resetormachine.soft_reset()). - Construct / import again — must succeed without hard reset or Guru Meditation.