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:

  1. docs/idempotent-lifecycle.md — required deinit / soft-reset contract (implemented for all real backends)
  2. docs/soft-reset-and-bring-up.md — proven failure modes and methods from ESP32-P4 mipidsi and Qualia S3 dotclockframebuffer.DotClockFramebuffer (+ LVGL); applies to other ports/interfaces
  3. 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

PathContents
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 --wrap or 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 by deinit / __del__ / idempotent ctors.
  • Desktop usdl2 registers 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 not m_free GC 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:

  1. Construct the interface (or import board_config / example).
  2. Soft-reset (mpftp soft-reset or machine.soft_reset()).
  3. Construct / import again — must succeed without hard reset or Guru Meditation.