Skip to content

Add Adafruit Metro ESP32-P4 and ESP32-P4 USB host support - #11496

Closed
ladyada-eagleclaw wants to merge 3 commits into
adafruit:mainfrom
ladyada-eagleclaw:add-metro-esp32p4-usb-host
Closed

ladyada-eagleclaw wants to merge 3 commits into
adafruit:mainfrom
ladyada-eagleclaw:add-metro-esp32p4-usb-host

Conversation

@ladyada-eagleclaw

Copy link
Copy Markdown

AI-assisted with Codex, asked to bring up CircuitPython on the Adafruit Metro ESP32-P4 and make USB host and DSI work. The validation below comes from builds, serial captures, and physical board/display checks; Ladyada typed into the attached keyboard and confirmed the display output.

What

Add the Adafruit Metro ESP32-P4 board definition and ESP32-P4 support for the existing usb_host.Port API. The board has 16 MB flash and 16 MB PSRAM. Its USB-C connector uses the full-speed PHY on the Serial/JTAG pins (GPIO24/25), while USB-A uses the dedicated high-speed PHY and a switched 5 V supply on GPIO14.

The Adafruit USB allocation is VID 0x239A, PID 0x817C, recorded as the Metro ESP32-P4 CircuitPython entry in Adafruit's boards repository. Pin aliases cover the labelled headers and onboard peripherals, including A0–A5, SDIO, NeoPixel, and C6 connections.

USB host implementation

Use the existing TinyUSB DWC2 host driver on controller 1, initialize the UTMI PHY in host mode, and expose its dedicated pads as USB_HS_DP/USB_HS_DM. These are not GPIOs; reject them in GPIO allocation and require this exact pair for the host port. Host and device must use different controllers.

Schedule host work on the VM task, including polling expired enumeration timers from the background tick. IRQ-only scheduling stalled enumeration during TinyUSB's delayed debounce/reset steps. Keep the host singleton across VM reloads.

Hardware tested

Metro ESP32-P4 Rev A, silicon v0.1, Windows USB host, keyboard 1c4f:0002, and 7-inch Raspberry Pi Touch Display 2. CircuitPython USB-C CDC/MSC remained available while the USB-A keyboard drove the DSI console. Ladyada typed hello metro; it appeared on the TFT. NeoPixel red/green/blue/off states were checked on the webcam while the demo ran.

The combined bring-up firmware also passed pin-alias checks, an 8 MiB allocation with page-spaced pattern readback, A0–A5 construction/read, and SDIO sector reads plus a read-only filesystem mount. The first prototype has a known card-detect hardware issue, so card detect is not claimed as a firmware pass.

Minimal host test:

import board, digitalio, time, usb.core, usb_host

power = digitalio.DigitalInOut(board.USB_HOST_POWER)
power.switch_to_output(value=True)
host = usb_host.Port(board.USB_HOST_DP, board.USB_HOST_DM)
time.sleep(2)
print(['%04x:%04x' % (d.idVendor, d.idProduct)
       for d in usb.core.find(find_all=True)])

Observed enumeration: ['1c4f:0002']. Invalid-pin rejection and repeated construction returning the same host instance were also tested. High-speed throughput, hubs, and other USB device classes have not been hardware-tested; the keyboard test does not establish a 480 Mbit/s transfer rate.

Build and related fixes

The exact PR branch builds on current main:

make -C ports/espressif BOARD=adafruit_metro_esp32p4 BUILD=build-metro-p4-host-dsi -j6

Firmware uses 1,002,544 bytes of its 2,097,152-byte partition. Changed-file pre-commit and git diff --check pass. The combined bring-up tree additionally built for adafruit_p4gpio, espressif_esp32p4_function_ev, espressif_esp32p4x_function_ev, m5stack_tab5, and solderparty_esp32p4_stamp_xl; those boards were compile-tested only.

Hardware validation used the combined bring-up tree with these separately submitted fixes: ADC mapping #11492, ROM USB reset #11493, stable UID #11494, and DSI output #11495. They are split out of this PR for independent review. In particular, the all-six-ADC, unattended reset, stable USB identity, and display results rely on those fixes.

C6 Wi-Fi/BLE integration and camera support are not implemented by this change. The panel initialization sequence stays in the Python demo, outside core.

ladyada-eagleclaw and others added 3 commits October 2, 2026 20:14
Co-authored-by: Limor Fried <ladyada@users.noreply.github.com>
Use the dedicated high-speed PHY for usb_host.Port while the other controller remains available for the USB device. Expose the dedicated pads as pins that cannot be claimed for GPIO, and process host events on the CircuitPython task under FreeRTOS.

Enabled for Metro ESP32-P4. Hardware checks passed host initialization, singleton reuse, invalid-pin rejection, USB-C operation and resets. Attached-device enumeration and keyboard reports remain pending connection of test hardware. All six P4 boards built and pre-commit checks passed.

Co-authored-by: Limor Fried <ladyada@users.noreply.github.com>
Co-authored-by: Limor Fried <ladyada@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant