Skip to content

GPIO usage per MCU — hardware reference

Which GPIOs are safe to wire a mic, an LED strand, or an Ethernet PHY to on each MCU projectMM supports, so a bench build picks a pin from here instead of re-scraping the datasheet. This is chip-level (which GPIOs the silicon reserves or role-assigns); a specific product's board wiring is its catalog entry in web-installer/deviceModels.json, and the one fully-mapped board is the ESP32-S31 coreboard.

Each chip lists two kinds of pin to avoid:

  • Reserved — wired to flash / PSRAM / native USB on-silicon. Using one crashes or corrupts the device. Never route peripheral I/O here.
  • Role-conflict — a usable GPIO that also carries a default role (JTAG, the UART0 console, a boot strap). Usable for I/O, but you give up that role: no hardware JTAG debug, no serial console, or a boot-mode hazard if the pin is driven during reset. Fine for a peripheral you're willing to trade the role for.

Everything else is free for user I/O. Since the ESP32 I²S / RMT / LED peripherals route through the GPIO matrix, any free GPIO works for a mic or an LED lane; there is no fixed pinout to match.

Sources: the per-chip Espressif datasheet (linked in each section). When picking defaults for a new chip, read its strapping-pin and flash/PSRAM tables from the datasheet first, not from a tutorial.

Usable LED-output GPIOs per MCU (quick reference)

For LED output specifically — the pins a WS2812-class strand data line can attach to, which the parallel drivers (RMT / LCD_CAM / Parlio, moving to 1..16 lanes) draw their lanes from. This is stricter than "any free I/O" in one way: an LED output needs a real output driver, so input-only pins are excluded (a mic input line can use them, an LED cannot). It excludes flash/PSRAM (reserved), input-only, and — for a clean default — the strapping pins (usable, but a wrong reset level is a boot hazard). The per-chip tables below give the full reasoning; this is the distilled "safe to drive an LED here" set.

MCU Usable LED-output GPIOs (avoid straps for defaults) Count Notes
ESP32 (classic) 4, 13, 14, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33 13 +16, 17 on non-PSRAM WROOM (they're PSRAM bus on WROVER). Input-only 34-39 are mic-input only, not LED.
ESP32-S3 (N16R8 / octal-PSRAM) 1-18, 21, 47, 48 → the clean 16 for LED lanes: 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,21 16 Excludes octal-PSRAM (33-37), USB (19,20), UART0 (43,44), onboard RGB LED (38 on rev v1.0 / 48 on rev v1.1 — avoid whichever your board uses), straps (0,3,45,46). Quad-PSRAM (N8R2) / no-PSRAM parts free 33-37 too.
ESP32-P4 (P4-NANO) 20, 21, 22, 23, 24, 25, 26, 27, 32, 33, 39-48 20 Board-specific: the NANO commits eth-RMII (28-31/49-52), C6-SDIO (14-19/54), I2C (7-8), UART0 (37-38). A carrier board changes the exposed set — the MHC-WLED shield routes through transceivers (no bare GPIO).
ESP32-S31 (coreboard) take from the coreboard reference free set Most of the header is committed to on-board RGMII eth + ES8311 codec + SD + USB-host; don't guess.

Mapping these to actual device-model defaults (which of a board's usable pins to pre-fill in deviceModels.json) is a separate, per-board step — the catalog defaults one strip for a bare dev board (the user wires the rest), or the exact wired set for a purpose-built board (QuinLED Dig-Octa: 0,1,2,3,4,5,12,13). That per-model work is tracked in backlog-core § LED output pins.

ESP32 (classic)

Datasheet. 34 GPIOs, but several are input-only or strapping.

Avoid GPIOs Why
Reserved 6-11 SPI flash (the on-package flash bus). Always off-limits.
Reserved 16, 17 Extra flash/PSRAM bus on WROVER (PSRAM) modules; free on plain WROOM.
Role-conflict 0, 2, 5, 12, 15 Boot straps. Usable, but a wrong level at reset changes boot mode (GPIO 12 = flash voltage is the dangerous one). Don't drive during boot.
Input-only 34, 35, 36, 39 No output driver and no internal pull-ups. Fine for a mic SD/SCK/WS input, useless for an LED output.

Clear for output I/O: 4, 13, 14, 18, 19, 21-23, 25-27, 32, 33 (plus 16/17 on non-PSRAM). Input-only 34-39 suit mic data lines.

i80 parallel LED lanes (classic ESP32 = I2S backend). The classic ESP32 runs the parallel LED driver over the I2S peripheral in i80 mode (the S3/P4 use LCD_CAM for the same i80 API; one driver, chip-picked backend). Like every i80 board it needs exactly 8 or 16 data pins plus two bus-control pins (clockPin = WR, dcPin = DC — the LEDs ignore both). Bench-verified default on the ESP32-WROVER (/dev/cu.usbserial-0001):

  • 8 lanes: data 2,4,13,14,18,19,21,22 · clockPin (WR) 32 · dcPin (DC) 33. (Pin 2 is a boot strap — it drives an LED fine and idles LOW, so it's benign here, but the Pins UI flags it; swap it for 23 to silence the warning.)
  • 16 lanes: not cleanly reachable on the WROVER. Only 13 non-strap output pins exist, and WR/DC consume 2 more, so a 16-lane set must borrow strap pins (0, 12, 15) — and GPIO 12 is the flash-voltage strap: driving it at reset can brick the boot, so don't. Use a board with more free GPIOs (an S3/P4) for 16 lanes; the classic ESP32 is an 8-lane i80 board in practice.
  • Memory ceiling: 2048 lights at 8 lanes (measured on the WROVER, 2026-07-13; 8×256 drives, 8×384 already fails). The I2S backend can't DMA from PSRAM, so its frame buffer is internal-RAM-only (~76 KB largest block) — an over-ceiling config degrades with i80 bus init failed — check pins / memory, it does not crash. Neither shrinking the grid (that memory is PSRAM) nor turning doubleBuffer off (one DMA buffer instead of two) raises it. See performance.md § Multi-pin LED driving.

ESP32-S3

Datasheet. 45 GPIOs. The reserved set depends on the module's PSRAM, which is the trap.

Avoid GPIOs Why
Reserved 26-32 SPI flash bus. Always off-limits.
Reserved (octal-PSRAM only, the N16R8 / R8 modules) 33-37 Octal PSRAM's SPIIO4-7 + DQS. On an R8 module these are not GPIOs; using one corrupts PSRAM. On quad-PSRAM (N8R2) or no-PSRAM parts they are free. Check the module suffix.
Role-conflict 39, 40, 41, 42 JTAG (MTCK/MTDO/MTDI/MTMS). Usable as GPIO, but you lose hardware JTAG debug. Keep free if you plan to add JTAG.
Role-conflict 19, 20 Native USB D-/D+ (the USB-C port on DevKitC boards). Usable, but breaks the native-USB console/DFU.
Role-conflict 43, 44 UART0 TX/RX — the default serial console. Take them and you lose printf-over-serial.
Role-conflict 0, 45, 46 Boot straps. Don't drive at reset.
Absent 22, 23, 24, 25 These GPIO numbers do not exist on the S3 (a numbering gap in the silicon). Setting a pin control to one is invalid — GPIO_IS_VALID_GPIO rejects it, and the pin map flags it as an error.

Clear for I/O on the N16R8: 1-18, 21, 47, 48 (mind GPIO 3 is a soft strap; the on-board WS2812 LED sits on 48 on DevKitC-1 rev v1.1 but on 38 on rev v1.0, so avoid whichever your board uses — the bench board is a rev v1.0, LED on 38, leaving 48 free). Example, the bench mic on the N16R8 is SCK=47 / WS=48 / SD=21 — clear of octal PSRAM, JTAG (39-42 stay free for a future JTAG probe), the boot straps, and (on this rev) the LED, with the mic wires kept away from the Wi-Fi antenna end.

ESP32-P4

Datasheet. 55 GPIOs, RISC-V. The P4 has no native radio; WiFi rides an on-board ESP32-C6 over SDIO, so several pins carry that link.

Avoid GPIOs Why
Reserved flash/PSRAM pins per module The HP SPI flash + PSRAM bus (module-specific; the Waveshare P4-NANO wires them internally). Off-limits.
Role-conflict 34-38 Strapping pins (boot mode). Don't drive at reset; the first LED-driver default wrongly landed here (see lessons.md).
Role-conflict 37, 38 UART0 console on the P4-NANO (CONFIG_ESP_CONSOLE_UART_DEFAULT) — the runtime ESP_LOGI lines come out here, not over USB.
Board-wired (P4-NANO) Ethernet RMII 28-31 / 49-52, C6 SDIO 14-19 / 54, I2C 7-8 Consumed by the NANO's on-board Ethernet PHY, the C6 WiFi co-processor, and the I2C bus.

Clear on the P4-NANO: 20-27, 32-33, 39-48 (the LED-driver default is pins="20,21,22,23,24,25,26,27"). Exact free set is board-specific; the NANO's is the reference. A carrier board changes what's exposed and how — the MHC-WLED ESP32-P4 shield routes every terminal through level shifters / RS-485 transceivers / protected inputs (no bare GPIO), which is why a direct loopback jumper fails on it; its full terminal map is on that page.

ESP32-S31

Datasheet. RISC-V, Wi-Fi 6 + on-chip 1 Gbps EMAC; shares the MoonLive RISC-V backend with the P4. The bench board's full schematic pin map (Ethernet RGMII, ES8311 audio codec, SD, USB-host) is on its own page: ESP32-S31 coreboard.

Avoid GPIOs Why
Reserved flash/PSRAM per module On-package flash + PSRAM bus. Off-limits.
Board-wired (coreboard) RGMII Ethernet + ES8311 I2S/I2C + SD + USB-host The Function-CoreBoard-1 uses a large set for its on-board peripherals — see the coreboard reference for the exact map, since the audio codec (not a bare I²S mic) drives its own pins.

For the S31 coreboard, take pins from the coreboard reference's "free" set rather than guessing, because so much of the header is committed to on-board peripherals.

The rule behind the defaults

projectMM leaves peripheral pins unset by default and lets the deviceModel catalog fix them only where the product wires them (the Defaults rule): a board-soldered PHY or codec defaults its pins; a user-soldered mic or LED strand stays unset so a guess can't drive a pin the user committed elsewhere. This table is what to consult when choosing that user pin, or when writing a new board's catalog entry.