Guition JC-ESP32P4-M3-DEV
An ESP32-P4 carrier with a MIPI display connector, a MIPI camera connector, Ethernet,
audio, a card slot, RS485, a battery charger and three USB-C sockets — and a radio
that is a second chip you talk to over SDIO.
Three things shape almost every task on this board. First, the P4 has no radio:
esp_wifi is not the API, esp_wifi_remote over esp_hosted is, and the ESP32-C6 inside
the module needs its own firmware. Second, the silicon comes in two mutually incompatible
revisions and ESP-IDF defaults to the wrong one for the boards being sold — the symptom
is a bootloader that dies with Illegal instruction, which reads like corrupt flash.
Third, there is no user LED: the only thing that lights is the power indicator, so a
board that "does nothing" is usually a board that is running fine with its console on the
wrong socket.
reference/board-hardware.md — the board: the module pin list transcribed from the
schematic, every P4 GPIO and what this board did with it, the JP1 header with its four
trap positions, power tree, Ethernet, I2C, audio, storage, the silicon-revision table,
the toolchain including the PlatformIO/SCons breakage, flashing, and a
symptom → cause → fix table.
reference/esp32p4-soc.md — the silicon: why no GPIO is stolen by flash, PSRAM, MIPI or
the HS USB PHY; strapping pins; ADC1/ADC2 and touch maps; the three USB controllers;
what the P4 has that no other ESP32 does.
reference/esp32-family.md — the rest of the family, for "should this be a different
ESP32?" questions.
reference/recipes.md — code: platformio.ini, sdkconfig.defaults, silicon-revision
and PSRAM detection, SDMMC with the on-chip LDO, I2C, ES8311, MIPI-DSI, GT911, Ethernet,
RS485, a 16 MB partition table, the die temperature sensor, Wi-Fi through the C6. Each
recipe says whether it was compiled.
template/ — a project that builds clean, in two variants, plus a scaffold script.
See template/README.md.
Confirm the board first
|
This board |
Not this board |
| Module lid |
JC-ESP32P4-M3 · GUITION · SOC: ESP32P4NRW32 · 32M PSRAM · Flash: 16M · WiFi: ESP32-C6 |
anything reading ESP32-P4-WROOM, ESP32-P4-MINI, or a Waveshare / M5Stack part number |
| Size and ports |
92 × 62 mm · three USB-C · RJ45 · TF slot · two 15-way FPC · 2×13 header on the left edge |
ESP32-P4 Function EV Board (two USB-C, different header), Waveshare ESP32-P4-NANO, M5Stack Tab5 |
| Display |
none on board — a DSI panel plugs into J2 |
boards with a bonded panel |
Then find the silicon revision, because it changes the build:
esptool --chip esp32p4 -p <port> flash-id # prints "revision v1.3" or "revision v3.x"
(esptool 5.3.0 ships with the pinned platform: commands are hyphenated and the binary is
esptool. esptool.py and flash_id still work, with a deprecation warning.)
Guition's own download archive splits every demo into P4_V1.3 and P4_V3X for this
reason. Everything below assumes rev v1.3 (rev < 3.0) and says where rev ≥ 3.0 differs.
Orientation
|
|
| Module |
JC-ESP32P4-M3 (Guition). ESP32-P4NRW32, 2 × RISC-V HP + 1 LP |
| Clock |
360 MHz on rev < 3.0 · 400 MHz on rev ≥ 3.0 · 40 MHz crystal |
| Memory |
16 MB NOR flash · 32 MB in-package PSRAM (HEX, 200 MHz) · 768 KB L2MEM · 32 KB LP SRAM · 8 KB TCM |
| Radio |
none on the P4. An ESP32-C6 inside the module, over SDIO slot 1, 4-bit, 40 MHz: CLK 18 · CMD 19 · D0-D3 14 15 16 17 · reset 54, active high. Driven by esp_hosted + esp_wifi_remote |
| GPIOs |
GPIO0-GPIO54, all of them exist. Flash, PSRAM, MIPI DSI/CSI and the HS USB PHY are all on dedicated pins and cost nothing |
| Free GPIO |
exactly eleven, all on JP1: 1, 2, 3, 4, 5, 20, 32, 33, 45, 46, 47 (+ 21, 22, 23 if you never fit a panel) |
| LED |
none on a GPIO. D1 is a power indicator on the 3V3 rail |
| Buttons |
SW1 → BOOTMODE = GPIO35, active low, 10 K pull-up · SW2 → CHIP_PU (reset) |
| Display |
MIPI-DSI, 2 lanes, J2 15-way FPC. No reset pin, no backlight pin. PHY power = on-chip LDO channel 3 @ 2500 mV |
| Camera |
MIPI-CSI, 2 lanes, J3 15-way FPC. SCCB on the shared I2C. No reset, no power-down |
| I2C |
one bus, everything on it: SDA 7 · SCL 8, 5.1 K pull-ups on board. ES8311 0x18 · panel brightness 0x45 · GT911 0x5D/0x14 · camera SCCB |
| Audio |
MCLK 13 · BCLK 12 · LRCK 10 · DOUT 9 (→ speaker) · DIN 48 (← microphone) · PA enable GPIO11, active high, 10 K pull-down |
| Storage |
microSD on SDMMC slot 0, 4-bit: CLK 43 · CMD 44 · D0-D3 39 40 41 42. No CS, no card-detect. VDD from on-chip LDO channel 4 |
| Ethernet |
IP101 PHY (per Guition's sdkconfig; the schematic says only U4), RMII, PHY address 1. CRS_DV 28 · RXD0 29 · RXD1 30 · TXD0 34 · TXD1 35 · TXEN 49 · CLK 50 · MDC 31 · MDIO 52 · reset 51 — exactly ESP-IDF 5.5.5's P4 defaults, so no pin config is needed |
| RS485 |
MAX485 on UART1: TX 26 · RX 27. DE//RE is generated in hardware — there is no direction GPIO |
| USB |
three USB-C: native USB-Serial/JTAG (GPIO24/25, 303A:1001) · CH340C onto UART0 (GPIO37/38) · USB 2.0 OTG HS on dedicated pins |
| Battery |
Li-ion on CN4, IP5306 charger. Sensed on GPIO53 (ADC2_CH4) through a 68 K/100 K divider |
| Toolchain |
PlatformIO Core 6.2.0 + pioarduino platform-espressif32 55.03.311 (ESP-IDF 5.5.5) + board = esp32-p4-evboard + framework = espidf. The official espressif32 platform cannot build for the P4 at all |
Rules that prevent the expensive mistakes
Each of these produces a failure that looks like something else.
CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y and CONFIG_ESP32P4_REV_MIN_100=y in
sdkconfig.defaults, or a V1.3 board does not boot at all. ESP-IDF 5.5 defaults to
building for rev ≥ 3.1, and Kconfig.hw_support says outright: "Support of ESP32-P4
rev. <3.0 and >=3.0 is mutually exclusive". Without the two lines the second-stage
bootloader dies immediately after the entry 0x... line with Guru Meditation Error: Illegal instruction — which points at corrupt flash, a bad build, anything but a
Kconfig setting. On a rev ≥ 3.0 board it is the reverse: CONFIG_ESP32P4_REV_MIN_301=y.
In Arduino the same choice is the board name: esp32-p4-evboard (ES, < 3.0) versus
esp32-p4_r3-evboard (≥ 3.0).
platform = espressif32 does not work. Pin the pioarduino URL. The official
PlatformIO platform, including 7.1.x, is on Arduino core 2.0.17 and carries no
ESP32-P4 board definition whatsoever. The error is Unknown board ID 'esp32-p4-evboard', which reads like a typo. Use
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.311/platform-espressif32.zip.
ModuleNotFoundError: No module named 'SCons.Tool.FortranCommon' at link time is a
packaging conflict, not your code. PlatformIO Core 6.2.0 wants tool-scons ~4.41101.0; pioarduino pins 4.40801.0, so the platform deletes
~/.platformio/packages/tool-scons mid-build, removing SCons from under the running
process. Either uv pip install pioarduino (their Core 6.1.19) or patch one word in
~/.platformio/platforms/espressif32/platform.json — board-hardware.md §12.1 has the
sed line. The patch is undone by any platform update.
PlatformIO builds the partition image from board_build.partitions in
platformio.ini, not from CONFIG_PARTITION_TABLE_*. Setting the Kconfig option and
expecting the image to follow gives you a 1 MB factory while the config says
SINGLE_APP_LARGE. Keep both lines in agreement. And check what you actually got:
partitions_singleapp_large.csv yields a 1,536 KB app slot, stranding 14 MB of a
16 MB part. recipes.md §12 has a 16 MB CSV that builds.
There is no user LED on this board. Only D1, a red power indicator on the 3V3 rail,
not on a GPIO. So blink is not a valid first test unless you wire an LED to JP1 — and
worse, in GPIO_MODE_INPUT_OUTPUT the input buffer reads the pad, and an unloaded
pad follows its own driver, so a passing read-back proves the pin drives, never that
it reaches anything. A self-test can report a pin working perfectly while it is
wired to the Ethernet PHY and fighting it. Pick from the eleven free JP1 pins in the
orientation table, and treat "the console prints" as the real first test.
Four of the twenty-six JP1 positions belong to the ESP32-C6, not the P4. Pins 20,
22, 24 and 26 are the radio's own U0RXD, U0TXD, IO9 boot strap and CHIP_PU,
brought out so the C6 can be reflashed. Driving any of them takes Wi-Fi down mid-run;
pin 26 holds the radio in reset permanently. Pin 8 is not connected at all.
esp_wifi_init() alone is not enough, and a failure there is usually not a Wi-Fi
problem. The P4 has no radio. Add espressif/esp_wifi_remote: ^0.14.2 to
idf_component.yml (it pulls esp_hosted 2.0.13), configure the SDIO link — slot 1,
4-bit, 40 MHz, CLK 18 / CMD 19 / D0-D3 14-17, reset GPIO 54 with
CONFIG_ESP_HOSTED_SDIO_RESET_ACTIVE_HIGH=y — and make sure the C6 is actually
running slave firmware. A blank or held-in-reset C6 surfaces as a transport timeout
inside esp_hosted init, not as an esp_wifi error.
The microSD card is powered by the P4's own on-chip LDO channel 4. Without
sd_pwr_ctrl_new_on_chip_ldo(.ldo_chan_id = 4) on the sdmmc_host_t the card is simply
unpowered and the mount times out, which reads as a bad card or bad wiring. It is
SDMMC slot 0, the IO MUX slot, so the pins are not passed in the slot config —
that absence is correct, not an omission. There is no chip select (it is not SPI), no
card-detect and no write-protect: pass SDMMC_SLOT_NO_CD and SDMMC_SLOT_NO_WP.
Acquire on-chip LDO channel 3 at 2500 mV before any MIPI-DSI call. It powers
VDD_MIPI_DPHY. Skip it and esp_lcd_new_dsi_bus fails or the panel stays dark with no
useful error. esp_ldo_acquire_channel({.chan_id = 3, .voltage_mv = 2500}).
GPIO11 low means silence whatever else is correct. The NS4150 amplifier's enable is
active high and held low by a 10 K pull-down (R19), so audio is muted until firmware
raises it. Raise it before initialising the ES8311, or the first frames pop.
I2S DOUT is GPIO9 and DIN is GPIO48, from the host's point of view. The schematic
names both from the codec's side, where the host's output is called DSDIN — which
reads backwards. Worse, the net on GPIO48 is named ES7210_SDOUT and there is no
ES7210 on this board: it is the ES8311's own ADC output feeding the on-board analog
microphone. Getting the direction wrong gives a silent speaker and a microphone that
records nothing, with the codec answering normally on I2C.
There is exactly one I2C bus and it is already busy. SDA = 7, SCL = 8, with
5.1 K pull-ups on board. The ES8311 (0x18), the DSI panel's brightness register
(0x45), a GT911 touch controller (0x5D or 0x14) and the camera's SCCB all live on
it, and it also reaches CN3 and JP1 pins 23/25. Nothing on this board defaults to
GPIO7/8 in any framework, so a scan that finds nothing is almost always the pins. Do
not open a second bus on the same pins for the touch controller — pass the same handle.
Ethernet needs no pin configuration on this board, and the RMII pins are not
free-for-all either. ETH_ESP32_EMAC_DEFAULT_CONFIG() for the P4 in ESP-IDF 5.5.5
already defaults to this board's exact wiring — mdc 31, mdio 52, clock
EMAC_CLK_EXT_IN on GPIO50, tx_en 49, txd0 34, txd1 35, crs_dv 28, rxd0 29,
rxd1 30 — which is why Guition's demo sets only MDC and MDIO, to the values they
already had. If you do move one: the RMII signals are IO MUX pads with a short
per-signal list (CRS_DV 28/45/51, RXD0 29/46/52, RXD1 30/47/53, TXD0 34/41,
TXD1 35/42, TX_EN 33/40/49, clock-in 32/44/50), set through
emac_dataif_gpio.rmii; only MDC, MDIO and the PHY reset go through the GPIO matrix
and can be anywhere. PHY address is 1 and the part is an IP101 — both from
Guition's demo sdkconfig, not from the schematic, which labels the PHY only U4.
Finally, RMII_TXD1 is GPIO35, the boot strap and SW1: holding SW1 at reset is
download mode, which is fine, but anything else pulling GPIO35 low through reset looks
like "the firmware stopped running".
RS485 has no direction GPIO and you should stop looking for one. DE and /RE are
generated in hardware from the TX line by a 74LVC1G132 + an 8550 PNP one-shot. Pass
RTS = UART_PIN_NO_CHANGE; Guition's own demo then still calls
uart_set_mode(UART_MODE_RS485_HALF_DUPLEX), which is harmless.
Match CONFIG_ESP_CONSOLE_* to the socket you plugged into. Three USB-C ports, two
of which flash the board: the native USB-Serial/JTAG (CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG,
enumerates 303A:1001) and the CH340C bridge onto UART0 (CONFIG_ESP_CONSOLE_UART_DEFAULT,
needs the CH340 driver on the host). Pick the wrong one and the board flashes, runs,
and prints nothing — with no LED to check instead.
Deleting or forgetting sdkconfig.defaults breaks two things silently. Without
CONFIG_SPIRAM the PSRAM component is compiled out entirely, so the failure is a
linker error — undefined reference to esp_psram_get_size — rather than a runtime
zero. And without the revision lines of rule 1 the board stops booting. Both were
observed in this session.
The die temperature sensor's range must be contained in one row of the P4 range
table ({50..125} {20..100} {-10..80} {-30..50} {-40..20}).
TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80) works; a plausible (-10, 100) is inside
none of them, and temperature_sensor_install() returns ESP_ERR_INVALID_ARG with the
log line "Out of testing range" — which reads like a missing peripheral rather than a
bad argument.
Feed it more than 500 mA. Guition's own burning instructions say so. The speaker
amplifier and the backlight boost run from the IP5306's VOUT-BAT rail, so a thin
cable shows up as distorted audio and random resets before it shows up as a power
problem.
When the task is choosing a pin
Count first, because the answer is smaller than the chip suggests. The P4 has 55 GPIOs and
none of them are eaten by flash, PSRAM, MIPI or the HS USB PHY — all of those are on
dedicated silicon pins, so the S3 reflex of "six pins belong to the flash, never touch
them" does not apply. This board, however, spends almost everything:
| GPIO |
Note |
| 1, 2, 3, 4, 5 |
JP1 pins 7, 9, 11, 13, 15. LP/RTC-capable, touch channels. 2-5 are the pad-JTAG pins at reset |
| 20 |
JP1 pin 17, ADC1_CH4. The cleanest pin on the header — no strap, no alternate use |
| 32, 33 |
JP1 pins 19, 21 |
| 45, 46, 47 |
JP1 pins 14, 12, 10. They are SD1 D4-D6, used only by 8-bit SD, which this board cannot do |
Then the ones you buy by giving something up: 39-44 cost the card · 9, 10, 11, 12,
13, 48 cost audio · 7, 8 are the shared bus · 26, 27 cost RS485 · 28, 29, 30,
31, 34, 35, 49, 50, 51, 52 cost Ethernet · 21, 22, 23 cost a panel's touch and
backlight · 37, 38 cost the UART console · 24, 25 cost the native USB port.
Never available: 14-19 and 6 (the C6 link, and 14-19 do not even reach a module
pin), 53 (battery divider), 54 (the C6's enable).
36 is free and has a 10 K pull-up, but reaches no connector — module pad only.
If eleven pins is not enough, the answer is an I2C expander on JP1 pins 23/25 or CN3,
at an address outside 0x18, 0x45, 0x5D, 0x14.
When the task is "the board does not work"
Diagnose in this order; each step only depends on the ones before it.
- Does the ROM banner (
ESP-ROM:esp32p4...) appear? It comes out before any of your
configuration applies. No banner ⇒ cable, wrong socket, or something holding GPIO35 low.
- Does anything of yours print? If the banner appears and your output does not, this
is rule 15 — the console is built for the other socket. Check which port enumerated:
303A:1001 is the native one, a 1A86:* is the CH340C.
- Does it die right after
entry 0x... with Illegal instruction? Rule 1. Stop here;
nothing downstream matters.
- What does
esp_chip_info().revision say? < 300 is the pre-rev-3 part. Confirm it
matches the sdkconfig you built with.
- Does
esp_psram_get_size() return 32 MB? If the symbol does not link,
CONFIG_SPIRAM is missing (rule 16). If it returns 0, the same.
- Wi-Fi failing? Rule 7, in that order: component versions, SDIO slot and pins, reset
polarity on GPIO54, then whether the C6 has firmware at all.
- Card not mounting? Rule 8, in that order: LDO channel 4, then SDMMC not SPI, then
slot 0, then
width = 4, then FAT32, then another card.
- Panel dark? Rule 9 first (LDO channel 3), then the panel's own timings — and note
that Guition's archive ships two different sets of porches for the same 800 × 1280
panel; see
recipes.md §8.
- Audio silent? GPIO11 first (rule 10), then the DOUT/DIN direction (rule 11).
- I2C scan empty? Rule 12 — the pins. If some addresses answer and one does not, it
is that device, not the bus.
- Ethernet link down? Rule 13: MDC 31, MDIO 52, reset 51, PHY address 1.
- Still lost? Flash
--minimal. It touches only the toolchain, the silicon revision,
the console route and the PSRAM mapping, so it separates "wrong build configuration"
from "wrong peripheral code" without guessing.
template/src/board_report.c prints the revision, PSRAM state, flash size, reset reason,
measured clock and die temperature, which answers steps 4-5 in one paste.
Starting a new project
Do not hand-assemble one: the platformio.ini has a platform URL that cannot be guessed
and the sdkconfig.defaults has two lines without which the board does not boot. Scaffold
from template/:
~/.claude/skills/esp32p4-jc-m3-dev/template/variants/new-project.sh <target-dir> [--full|--minimal]
cd <target-dir> && pio run
--minimal — silicon revision, flash size, PSRAM check, USB console, blink on a free JP1
pin. 207,224 B flash, 17,220 B RAM. Flash this first on a board you have not used
before: with no user LED it is the only way to separate a wrong build configuration from
wrong peripheral code.
--full (default) — board self-test: chip and revision, MAC, reset reason, the core
clock as measured, flash and JEDEC id, partition layout, internal and PSRAM heaps,
PSRAM/SRAM/CPU benchmarks, die temperature, an I2C scan, a GPIO read-back, then live
telemetry once a second. 244,198 B flash, 17,520 B RAM.
Both build with zero warnings at the toolchain versions in the orientation table. Nothing
is generated and no paths are embedded, so copying template/ by hand works identically.
template/README.md maps files to subsystems.
The display, camera, audio, Ethernet, RS485 and Wi-Fi are deliberately not in the
template — they need hardware this board does not include, and each is in
reference/recipes.md marked with whether it was compiled.
When the user already has a project, prefer bringing their platformio.ini and
sdkconfig.defaults in line with the template over rewriting their code — on this board
that is where the failures live.
Arduino is a supported alternative (framework = arduino, arduino-esp32 3.2.x for rev
v1.3 and 3.3.11 for rev v3.x, board ESP32P4 Dev Module in the Arduino IDE), and every pin
rule above applies unchanged. Under Arduino the board name is the revision selector
(rule 1), so it matters more, not less.
Flashing
pio run -t upload -t monitor
Three USB-C sockets; two of them can flash the board.
|
native USB-Serial/JTAG |
CH340C |
HS USB OTG |
| Enumerates |
303A:1001 · /dev/cu.usbmodem* · /dev/ttyACM* |
1A86:* · /dev/cu.usbserial* · /dev/ttyUSB* |
nothing, until firmware configures it |
| Console option |
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG |
CONFIG_ESP_CONSOLE_UART_DEFAULT |
— |
| Auto-reset |
yes |
yes, RTS/DTR onto BOOTMODE/CHIP_PU |
— |
| Host driver |
none |
CH340 driver required |
— |
When upload fails, the manual sequence is:
hold SW1 (BOOTMODE) → tap SW2 (reset) → release SW1 → upload
Bad firmware cannot brick this board. The ROM bootloader is mask ROM and always answers
that sequence:
esptool --chip esp32p4 -p <port> flash-id # chip banner with revision, and 16 MB
esptool --chip esp32p4 -p <port> chip-id
esptool --chip esp32p4 -p <port> erase-flash
esptool 5.3.0 comes with the pinned platform; it renamed esptool.py to esptool and
the underscore commands to hyphens, keeping the old spellings working with a warning.
The one genuinely unrecoverable mistake is burning EFUSE_0PXA_TIEH_SEL_0, which switches
VDDO_FLASH to 1.8 V permanently on a 3.3 V flash. eFuses are one-time. Do not run
espefuse on this board.
Reporting
Say what is verified and what is derived.
Verified on hardware (a rev v1.3 board, by the project this skill was extracted from):
the silicon-revision trap of rule 1 and its exact Illegal instruction symptom; the SCons
packaging conflict of rule 3 and the manifest patch that fixes it; the partition-table
source of rule 4; the temperature-sensor range trap of rule 17; that the board reports
ESP32-P4 rev v1.3, 32 MB PSRAM, 16 MB flash (JEDEC 0x684018), 360 MHz measured; and the
memory bandwidth figures in board-hardware.md §10.
Verified against ESP-IDF 5.5.5 itself (the copy the pinned platform installs), not
just against the vendor's demos: the revision Kconfig and its "mutually exclusive" wording;
that ESP32P4_REV_MIN_301 is the default; the SDMMC slot-0 IO MUX pins (sdmmc_pins.h
gives CLK 43, CMD 44, D0-D3 39-42, D4-D7 45-48 — the board's wiring exactly) and that slot 1
does not use IO MUX, which is why the C6 sits there; sd_pwr_ctrl_by_on_chip_ldo.h, whose
own comment names LDO channel 4 for SDMMC IO; esp_ldo_regulator.h and its four channels;
the P4 temperature range table; ADC2_CHANNEL_4_GPIO_NUM 53; SOC_GPIO_PIN_COUNT 55,
SOC_I2S_NUM 3, SOC_TWAI_CONTROLLER_NUM 3, SOC_TOUCH_SENSOR_NUM 14; the RMII pad lists
in emac_periph.c; and that ETH_ESP32_EMAC_DEFAULT_CONFIG() for the P4 is this board's
pin set. The esptool command spellings were checked by running the 5.3.0 binary.
Verified in this session: both template variants build clean with zero warnings at
PlatformIO Core 6.2.0 / pioarduino 55.03.311 / ESP-IDF 5.5.5, at the flash and RAM figures
quoted above; the generated sdkconfig carries the revision, PSRAM and console settings; the
16 MB partition CSV in recipes.md §12 builds and produces the partition sizes it claims;
and a missing CONFIG_SPIRAM fails at link, not at runtime (rule 16).
Schematic-derived, high confidence. Every pin in board-hardware.md §2 is traced on
Guition's own schematic sheets. That includes the facts most likely to be got wrong
elsewhere: the JP1 pinout and its four ESP32-C6 positions; that GPIO14-19 never reach a
module pin; that the TF card's VDD comes from on-chip LDO channel 4 through an
always-on switch (R10 unpopulated, so GPIO45 is free); that PA_CTRL has a 10 K
pull-down; that RS485 direction is a hardware one-shot with no GPIO; and the ten Ethernet
RMII pins.
Vendor code, high confidence. The SDIO link parameters, the SD slot and LDO channel,
the DSI LDO channel and voltage, the I2C addresses, the ADC unit/channel for the battery
and the Ethernet MDC/MDIO/PHY-address all come from Guition's own demos in the product
archive, most of which vendor Espressif's esp32_p4_function_ev_board BSP unmodified.
Primary-source. The GPIO inventory, strapping tables, boot modes, ADC channel maps and
the three USB controllers in reference/esp32p4-soc.md are from the ESP32-P4 Series
Datasheet v0.5 — which is marked PRELIMINARY on every page.
Corrected during a second verification pass — do not reintroduce these:
- The RMII data pins are not "fixed in copper". They are IO MUX pads with a short list
of alternatives each, selectable through
emac_dataif_gpio.rmii; the board simply uses
the same set ESP-IDF already defaults to.
temperature_sensor_install() fails with ESP_ERR_INVALID_ARG ("Out of testing
range"), not ESP_ERR_NOT_FOUND.
- A pin in
GPIO_MODE_INPUT_OUTPUT reads the pad, not an output latch. The distinction
matters: on an unloaded pad the read-back still passes, which is why the GPIO28 mistake
went unnoticed.
- IP101 and PHY address 1 come from Guition's demo sdkconfig. The schematic labels
the PHY only
U4, and which strap resistors set the address is not shown.
- esptool 5.3.0 uses
esptool and hyphenated commands (flash-id, chip-id,
erase-flash).
- The ESP32-P4 datasheet describes no CAN FD — three TWAI controllers, CAN 2.0, up to
1 Mbit/s — and ESP-IDF defines no FD capability for it, contradicting the CAN FD row in
reference/esp32-family.md, which is second-hand from Espressif's product selector.
- The C6 variant inside the module is not named anywhere in Guition's material; say
"an ESP32-C6", not a specific part number.
Known contradictions — quote them as contradictions, not as facts:
- Guition's xiaozhi board file defines
BOOT_BUTTON_GPIO as 21. GPIO21 is the touch
panel's interrupt line. The boot button is SW1 on GPIO35. Do not copy that define.
- The schematic net
ES7210_SDOUT names a chip this board does not have (rule 11).
- Two different DSI porch sets for the same 800 × 1280 panel ship in the same archive —
Guition's xiaozhi board file and Espressif's BSP disagree.
recipes.md §8.
- The specification PDF claims "up to 400 MHz"; a rev v1.3 board runs 360, and reports
- The Getting Started PDF is for a different Guition board (
JC1060P470) and says so
in its own text. Its Arduino IDE steps still apply.
Not verified anywhere. No DSI panel, camera, SD card, Ethernet cable, RS485 device,
speaker, microphone or battery was attached in this session, and nothing was flashed here.
The display, audio, storage, Ethernet, RS485, battery and Wi-Fi recipes are marked
"not compiled in this session" individually — say so rather than presenting them as
certain.
1---2name: esp32p4-jc-m3-dev3description: Guition JC-ESP32P4-M3-DEV4---56# Guition JC-ESP32P4-M3-DEV78An ESP32-P4 carrier with a MIPI display connector, a MIPI camera connector, Ethernet,9audio, a card slot, RS485, a battery charger and **three USB-C sockets** — and a radio10that is a second chip you talk to over SDIO.1112Three things shape almost every task on this board. First, **the P4 has no radio**:13`esp_wifi` is not the API, `esp_wifi_remote` over `esp_hosted` is, and the ESP32-C6 inside14the module needs its own firmware. Second, **the silicon comes in two mutually incompatible15revisions** and ESP-IDF defaults to the wrong one for the boards being sold — the symptom16is a bootloader that dies with `Illegal instruction`, which reads like corrupt flash.17Third, **there is no user LED**: the only thing that lights is the power indicator, so a18board that "does nothing" is usually a board that is running fine with its console on the19wrong socket.2021- `reference/board-hardware.md` — the board: the module pin list transcribed from the22 schematic, every P4 GPIO and what this board did with it, the JP1 header with its four23 trap positions, power tree, Ethernet, I2C, audio, storage, the silicon-revision table,24 the toolchain including the PlatformIO/SCons breakage, flashing, and a25 symptom → cause → fix table.26- `reference/esp32p4-soc.md` — the silicon: why no GPIO is stolen by flash, PSRAM, MIPI or27 the HS USB PHY; strapping pins; ADC1/ADC2 and touch maps; the three USB controllers;28 what the P4 has that no other ESP32 does.29- `reference/esp32-family.md` — the rest of the family, for "should this be a different30 ESP32?" questions.31- `reference/recipes.md` — code: `platformio.ini`, `sdkconfig.defaults`, silicon-revision32 and PSRAM detection, SDMMC with the on-chip LDO, I2C, ES8311, MIPI-DSI, GT911, Ethernet,33 RS485, a 16 MB partition table, the die temperature sensor, Wi-Fi through the C6. Each34 recipe says whether it was compiled.35- `template/` — a **project that builds clean**, in two variants, plus a scaffold script.36 See `template/README.md`.3738## Confirm the board first3940| | This board | Not this board |41|---|---|---|42| Module lid | `JC-ESP32P4-M3 · GUITION` · `SOC: ESP32P4NRW32` · `32M PSRAM` · `Flash: 16M` · `WiFi: ESP32-C6` | anything reading `ESP32-P4-WROOM`, `ESP32-P4-MINI`, or a Waveshare / M5Stack part number |43| Size and ports | 92 × 62 mm · **three USB-C** · RJ45 · TF slot · two 15-way FPC · 2×13 header on the left edge | ESP32-P4 Function EV Board (two USB-C, different header), Waveshare ESP32-P4-NANO, M5Stack Tab5 |44| Display | **none on board** — a DSI panel plugs into J2 | boards with a bonded panel |4546Then find the **silicon revision**, because it changes the build:4748```sh49esptool --chip esp32p4 -p <port> flash-id # prints "revision v1.3" or "revision v3.x"50```5152(esptool 5.3.0 ships with the pinned platform: commands are hyphenated and the binary is53`esptool`. `esptool.py` and `flash_id` still work, with a deprecation warning.)5455Guition's own download archive splits every demo into `P4_V1.3` and `P4_V3X` for this56reason. Everything below assumes **rev v1.3** (rev < 3.0) and says where rev ≥ 3.0 differs.5758## Orientation5960| | |61|---|---|62| Module | **JC-ESP32P4-M3** (Guition). ESP32-P4NRW32, 2 × RISC-V HP + 1 LP |63| Clock | **360 MHz** on rev < 3.0 · 400 MHz on rev ≥ 3.0 · 40 MHz crystal |64| Memory | **16 MB** NOR flash · **32 MB in-package PSRAM** (HEX, 200 MHz) · 768 KB L2MEM · 32 KB LP SRAM · 8 KB TCM |65| Radio | **none on the P4.** An **ESP32-C6** inside the module, over **SDIO slot 1, 4-bit, 40 MHz**: CLK **18** · CMD **19** · D0-D3 **14 15 16 17** · reset **54, active high**. Driven by `esp_hosted` + `esp_wifi_remote` |66| GPIOs | **GPIO0-GPIO54, all of them exist.** Flash, PSRAM, MIPI DSI/CSI and the HS USB PHY are all on **dedicated pins** and cost nothing |67| Free GPIO | exactly eleven, all on JP1: **1, 2, 3, 4, 5, 20, 32, 33, 45, 46, 47** (+ 21, 22, 23 if you never fit a panel) |68| LED | **none on a GPIO.** D1 is a power indicator on the 3V3 rail |69| Buttons | **SW1** → `BOOTMODE` = **GPIO35**, active low, 10 K pull-up · **SW2** → `CHIP_PU` (reset) |70| Display | **MIPI-DSI**, 2 lanes, J2 15-way FPC. **No reset pin, no backlight pin.** PHY power = **on-chip LDO channel 3 @ 2500 mV** |71| Camera | **MIPI-CSI**, 2 lanes, J3 15-way FPC. SCCB on the shared I2C. No reset, no power-down |72| I2C | **one bus, everything on it**: SDA **7** · SCL **8**, 5.1 K pull-ups on board. ES8311 `0x18` · panel brightness `0x45` · GT911 `0x5D`/`0x14` · camera SCCB |73| Audio | MCLK **13** · BCLK **12** · LRCK **10** · **DOUT 9** (→ speaker) · **DIN 48** (← microphone) · **PA enable GPIO11, active high, 10 K pull-down** |74| Storage | microSD on **SDMMC slot 0, 4-bit**: CLK **43** · CMD **44** · D0-D3 **39 40 41 42**. **No CS, no card-detect.** VDD from **on-chip LDO channel 4** |75| Ethernet | IP101 PHY (per Guition's sdkconfig; the schematic says only `U4`), RMII, PHY address **1**. CRS_DV **28** · RXD0 **29** · RXD1 **30** · TXD0 **34** · TXD1 **35** · TXEN **49** · CLK **50** · MDC **31** · MDIO **52** · reset **51** — **exactly ESP-IDF 5.5.5's P4 defaults**, so no pin config is needed |76| RS485 | MAX485 on **UART1**: TX **26** · RX **27**. **DE//RE is generated in hardware — there is no direction GPIO** |77| USB | **three USB-C**: native USB-Serial/JTAG (GPIO24/25, `303A:1001`) · **CH340C** onto UART0 (GPIO37/38) · **USB 2.0 OTG HS** on dedicated pins |78| Battery | Li-ion on CN4, IP5306 charger. Sensed on **GPIO53** (`ADC2_CH4`) through a 68 K/100 K divider |79| Toolchain | PlatformIO Core 6.2.0 + **pioarduino** `platform-espressif32` **55.03.311** (ESP-IDF **5.5.5**) + `board = esp32-p4-evboard` + `framework = espidf`. **The official `espressif32` platform cannot build for the P4 at all** |8081## Rules that prevent the expensive mistakes8283Each of these produces a failure that looks like something else.84851. **`CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y` and `CONFIG_ESP32P4_REV_MIN_100=y` in86 `sdkconfig.defaults`, or a `V1.3` board does not boot at all.** ESP-IDF 5.5 defaults to87 building for rev ≥ 3.1, and `Kconfig.hw_support` says outright: *"Support of ESP32-P488 rev. <3.0 and >=3.0 is mutually exclusive"*. Without the two lines the second-stage89 bootloader dies immediately after the `entry 0x...` line with **`Guru Meditation Error:90 Illegal instruction`** — which points at corrupt flash, a bad build, anything but a91 Kconfig setting. On a rev ≥ 3.0 board it is the reverse: `CONFIG_ESP32P4_REV_MIN_301=y`.92 In Arduino the same choice is the board name: `esp32-p4-evboard` (ES, < 3.0) versus93 `esp32-p4_r3-evboard` (≥ 3.0).94952. **`platform = espressif32` does not work. Pin the pioarduino URL.** The official96 PlatformIO platform, including 7.1.x, is on Arduino core 2.0.17 and carries **no97 ESP32-P4 board definition whatsoever**. The error is `Unknown board ID98 'esp32-p4-evboard'`, which reads like a typo. Use99 `platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.311/platform-espressif32.zip`.1001013. **`ModuleNotFoundError: No module named 'SCons.Tool.FortranCommon'` at link time is a102 packaging conflict, not your code.** PlatformIO Core 6.2.0 wants `tool-scons103 ~4.41101.0`; pioarduino pins `4.40801.0`, so the platform **deletes104 `~/.platformio/packages/tool-scons` mid-build**, removing SCons from under the running105 process. Either `uv pip install pioarduino` (their Core 6.1.19) or patch one word in106 `~/.platformio/platforms/espressif32/platform.json` — `board-hardware.md` §12.1 has the107 `sed` line. The patch is undone by any platform update.1081094. **PlatformIO builds the partition image from `board_build.partitions` in110 `platformio.ini`, not from `CONFIG_PARTITION_TABLE_*`.** Setting the Kconfig option and111 expecting the image to follow gives you a 1 MB `factory` while the config says112 `SINGLE_APP_LARGE`. Keep both lines in agreement. And check what you actually got:113 `partitions_singleapp_large.csv` yields a **1,536 KB** app slot, stranding 14 MB of a114 16 MB part. `recipes.md` §12 has a 16 MB CSV that builds.1151165. **There is no user LED on this board.** Only D1, a red power indicator on the 3V3 rail,117 not on a GPIO. So blink is not a valid first test unless you wire an LED to JP1 — and118 worse, in `GPIO_MODE_INPUT_OUTPUT` the input buffer reads the **pad**, and an unloaded119 pad follows its own driver, so **a passing read-back proves the pin drives, never that120 it reaches anything**. A self-test can report a pin working perfectly while it is121 wired to the Ethernet PHY and fighting it. Pick from the eleven free JP1 pins in the122 orientation table, and treat "the console prints" as the real first test.1231246. **Four of the twenty-six JP1 positions belong to the ESP32-C6, not the P4.** Pins 20,125 22, 24 and 26 are the radio's own `U0RXD`, `U0TXD`, `IO9` boot strap and `CHIP_PU`,126 brought out so the C6 can be reflashed. Driving any of them takes Wi-Fi down mid-run;127 pin 26 holds the radio in reset permanently. Pin 8 is not connected at all.1281297. **`esp_wifi_init()` alone is not enough, and a failure there is usually not a Wi-Fi130 problem.** The P4 has no radio. Add `espressif/esp_wifi_remote: ^0.14.2` to131 `idf_component.yml` (it pulls `esp_hosted` 2.0.13), configure the SDIO link — slot 1,132 4-bit, 40 MHz, CLK 18 / CMD 19 / D0-D3 14-17, **reset GPIO 54 with133 `CONFIG_ESP_HOSTED_SDIO_RESET_ACTIVE_HIGH=y`** — and make sure the C6 is actually134 running slave firmware. A blank or held-in-reset C6 surfaces as a transport timeout135 inside `esp_hosted` init, not as an `esp_wifi` error.1361378. **The microSD card is powered by the P4's own on-chip LDO channel 4.** Without138 `sd_pwr_ctrl_new_on_chip_ldo(.ldo_chan_id = 4)` on the `sdmmc_host_t` the card is simply139 unpowered and the mount times out, which reads as a bad card or bad wiring. It is140 **SDMMC slot 0**, the IO MUX slot, so the pins are *not* passed in the slot config —141 that absence is correct, not an omission. There is no chip select (it is not SPI), no142 card-detect and no write-protect: pass `SDMMC_SLOT_NO_CD` and `SDMMC_SLOT_NO_WP`.1431449. **Acquire on-chip LDO channel 3 at 2500 mV before any MIPI-DSI call.** It powers145 `VDD_MIPI_DPHY`. Skip it and `esp_lcd_new_dsi_bus` fails or the panel stays dark with no146 useful error. `esp_ldo_acquire_channel({.chan_id = 3, .voltage_mv = 2500})`.14714810. **GPIO11 low means silence whatever else is correct.** The NS4150 amplifier's enable is149 active high and held low by a 10 K pull-down (R19), so audio is muted until firmware150 raises it. Raise it *before* initialising the ES8311, or the first frames pop.15115211. **I2S DOUT is GPIO9 and DIN is GPIO48, from the host's point of view.** The schematic153 names both from the *codec's* side, where the host's output is called `DSDIN` — which154 reads backwards. Worse, the net on GPIO48 is named **`ES7210_SDOUT`** and **there is no155 ES7210 on this board**: it is the ES8311's own ADC output feeding the on-board analog156 microphone. Getting the direction wrong gives a silent speaker and a microphone that157 records nothing, with the codec answering normally on I2C.15815912. **There is exactly one I2C bus and it is already busy.** `SDA = 7`, `SCL = 8`, with160 5.1 K pull-ups on board. The ES8311 (`0x18`), the DSI panel's brightness register161 (`0x45`), a GT911 touch controller (`0x5D` or `0x14`) and the camera's SCCB all live on162 it, and it also reaches CN3 and JP1 pins 23/25. Nothing on this board defaults to163 GPIO7/8 in any framework, so a scan that finds nothing is almost always the pins. Do164 not open a second bus on the same pins for the touch controller — pass the same handle.16516613. **Ethernet needs no pin configuration on this board, and the RMII pins are not167 free-for-all either.** `ETH_ESP32_EMAC_DEFAULT_CONFIG()` for the P4 in ESP-IDF 5.5.5168 already defaults to this board's exact wiring — `mdc 31`, `mdio 52`, clock169 `EMAC_CLK_EXT_IN` on GPIO50, `tx_en 49`, `txd0 34`, `txd1 35`, `crs_dv 28`, `rxd0 29`,170 `rxd1 30` — which is why Guition's demo sets only MDC and MDIO, to the values they171 already had. If you *do* move one: the RMII signals are **IO MUX pads with a short172 per-signal list** (`CRS_DV` 28/45/51, `RXD0` 29/46/52, `RXD1` 30/47/53, `TXD0` 34/41,173 `TXD1` 35/42, `TX_EN` 33/40/49, clock-in 32/44/50), set through174 `emac_dataif_gpio.rmii`; only MDC, MDIO and the PHY reset go through the GPIO matrix175 and can be anywhere. PHY address is **1** and the part is an **IP101** — both from176 Guition's demo sdkconfig, not from the schematic, which labels the PHY only `U4`.177 Finally, **`RMII_TXD1` is GPIO35, the boot strap and SW1**: holding SW1 at reset is178 download mode, which is fine, but anything else pulling GPIO35 low through reset looks179 like "the firmware stopped running".18018114. **RS485 has no direction GPIO and you should stop looking for one.** DE and /RE are182 generated in hardware from the TX line by a 74LVC1G132 + an 8550 PNP one-shot. Pass183 `RTS = UART_PIN_NO_CHANGE`; Guition's own demo then still calls184 `uart_set_mode(UART_MODE_RS485_HALF_DUPLEX)`, which is harmless.18518615. **Match `CONFIG_ESP_CONSOLE_*` to the socket you plugged into.** Three USB-C ports, two187 of which flash the board: the native USB-Serial/JTAG (`CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG`,188 enumerates `303A:1001`) and the CH340C bridge onto UART0 (`CONFIG_ESP_CONSOLE_UART_DEFAULT`,189 needs the CH340 driver on the host). Pick the wrong one and the board flashes, runs,190 and prints nothing — with no LED to check instead.19119216. **Deleting or forgetting `sdkconfig.defaults` breaks two things silently.** Without193 `CONFIG_SPIRAM` the PSRAM component is compiled out entirely, so the failure is a194 *linker* error — `undefined reference to esp_psram_get_size` — rather than a runtime195 zero. And without the revision lines of rule 1 the board stops booting. Both were196 observed in this session.19719817. **The die temperature sensor's range must be contained in one row of the P4 range199 table** (`{50..125} {20..100} {-10..80} {-30..50} {-40..20}`).200 `TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80)` works; a plausible `(-10, 100)` is inside201 none of them, and `temperature_sensor_install()` returns `ESP_ERR_INVALID_ARG` with the202 log line "Out of testing range" — which reads like a missing peripheral rather than a203 bad argument.20420518. **Feed it more than 500 mA.** Guition's own burning instructions say so. The speaker206 amplifier and the backlight boost run from the IP5306's `VOUT-BAT` rail, so a thin207 cable shows up as distorted audio and random resets before it shows up as a power208 problem.209210## When the task is choosing a pin211212Count first, because the answer is smaller than the chip suggests. The P4 has 55 GPIOs and213**none of them are eaten by flash, PSRAM, MIPI or the HS USB PHY** — all of those are on214dedicated silicon pins, so the S3 reflex of "six pins belong to the flash, never touch215them" does not apply. This *board*, however, spends almost everything:216217| GPIO | Note |218|---|---|219| 1, 2, 3, 4, 5 | JP1 pins 7, 9, 11, 13, 15. LP/RTC-capable, touch channels. 2-5 are the pad-JTAG pins at reset |220| 20 | JP1 pin 17, `ADC1_CH4`. The cleanest pin on the header — no strap, no alternate use |221| 32, 33 | JP1 pins 19, 21 |222| 45, 46, 47 | JP1 pins 14, 12, 10. They are SD1 `D4`-`D6`, used only by 8-bit SD, which this board cannot do |223224Then the ones you buy by giving something up: **39-44** cost the card · **9, 10, 11, 12,22513, 48** cost audio · **7, 8** are the shared bus · **26, 27** cost RS485 · **28, 29, 30,22631, 34, 35, 49, 50, 51, 52** cost Ethernet · **21, 22, 23** cost a panel's touch and227backlight · **37, 38** cost the UART console · **24, 25** cost the native USB port.228229Never available: **14-19** and **6** (the C6 link, and 14-19 do not even reach a module230pin), **53** (battery divider), **54** (the C6's enable).231232`36` is free and has a 10 K pull-up, but reaches no connector — module pad only.233234If eleven pins is not enough, the answer is an **I2C expander on JP1 pins 23/25 or CN3**,235at an address outside `0x18`, `0x45`, `0x5D`, `0x14`.236237## When the task is "the board does not work"238239Diagnose in this order; each step only depends on the ones before it.2402411. **Does the ROM banner (`ESP-ROM:esp32p4...`) appear?** It comes out before any of your242 configuration applies. No banner ⇒ cable, wrong socket, or something holding GPIO35 low.2432. **Does anything of yours print?** If the banner appears and your output does not, this244 is rule 15 — the console is built for the other socket. Check which port enumerated:245 `303A:1001` is the native one, a `1A86:*` is the CH340C.2463. **Does it die right after `entry 0x...` with `Illegal instruction`?** Rule 1. Stop here;247 nothing downstream matters.2484. **What does `esp_chip_info().revision` say?** `< 300` is the pre-rev-3 part. Confirm it249 matches the sdkconfig you built with.2505. **Does `esp_psram_get_size()` return 32 MB?** If the symbol does not *link*,251 `CONFIG_SPIRAM` is missing (rule 16). If it returns 0, the same.2526. **Wi-Fi failing?** Rule 7, in that order: component versions, SDIO slot and pins, reset253 polarity on GPIO54, then whether the C6 has firmware at all.2547. **Card not mounting?** Rule 8, in that order: LDO channel 4, then SDMMC not SPI, then255 slot 0, then `width = 4`, then FAT32, then another card.2568. **Panel dark?** Rule 9 first (LDO channel 3), then the panel's own timings — and note257 that Guition's archive ships two *different* sets of porches for the same 800 × 1280258 panel; see `recipes.md` §8.2599. **Audio silent?** GPIO11 first (rule 10), then the DOUT/DIN direction (rule 11).26010. **I2C scan empty?** Rule 12 — the pins. If some addresses answer and one does not, it261 is that device, not the bus.26211. **Ethernet link down?** Rule 13: MDC 31, MDIO 52, reset 51, PHY address 1.26312. **Still lost?** Flash `--minimal`. It touches only the toolchain, the silicon revision,264 the console route and the PSRAM mapping, so it separates "wrong build configuration"265 from "wrong peripheral code" without guessing.266267`template/src/board_report.c` prints the revision, PSRAM state, flash size, reset reason,268measured clock and die temperature, which answers steps 4-5 in one paste.269270## Starting a new project271272Do not hand-assemble one: the `platformio.ini` has a platform URL that cannot be guessed273and the `sdkconfig.defaults` has two lines without which the board does not boot. Scaffold274from `template/`:275276```sh277~/.claude/skills/esp32p4-jc-m3-dev/template/variants/new-project.sh <target-dir> [--full|--minimal]278cd <target-dir> && pio run279```280281- `--minimal` — silicon revision, flash size, PSRAM check, USB console, blink on a free JP1282 pin. **207,224 B flash, 17,220 B RAM.** Flash this first on a board you have not used283 before: with no user LED it is the only way to separate a wrong build configuration from284 wrong peripheral code.285- `--full` (default) — board self-test: chip and revision, MAC, reset reason, the core286 clock **as measured**, flash and JEDEC id, partition layout, internal and PSRAM heaps,287 PSRAM/SRAM/CPU benchmarks, die temperature, an I2C scan, a GPIO read-back, then live288 telemetry once a second. **244,198 B flash, 17,520 B RAM.**289290Both build with zero warnings at the toolchain versions in the orientation table. Nothing291is generated and no paths are embedded, so copying `template/` by hand works identically.292`template/README.md` maps files to subsystems.293294The display, camera, audio, Ethernet, RS485 and Wi-Fi are deliberately **not** in the295template — they need hardware this board does not include, and each is in296`reference/recipes.md` marked with whether it was compiled.297298When the user already has a project, prefer bringing their `platformio.ini` and299`sdkconfig.defaults` in line with the template over rewriting their code — on this board300that is where the failures live.301302Arduino is a supported alternative (`framework = arduino`, arduino-esp32 3.2.x for rev303v1.3 and 3.3.11 for rev v3.x, board `ESP32P4 Dev Module` in the Arduino IDE), and every pin304rule above applies unchanged. Under Arduino the board name *is* the revision selector305(rule 1), so it matters more, not less.306307## Flashing308309```sh310pio run -t upload -t monitor311```312313Three USB-C sockets; two of them can flash the board.314315| | native USB-Serial/JTAG | CH340C | HS USB OTG |316|---|---|---|---|317| Enumerates | `303A:1001` · `/dev/cu.usbmodem*` · `/dev/ttyACM*` | `1A86:*` · `/dev/cu.usbserial*` · `/dev/ttyUSB*` | nothing, until firmware configures it |318| Console option | `CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG` | `CONFIG_ESP_CONSOLE_UART_DEFAULT` | — |319| Auto-reset | yes | yes, RTS/DTR onto `BOOTMODE`/`CHIP_PU` | — |320| Host driver | none | **CH340 driver required** | — |321322When upload fails, the manual sequence is:323324> **hold SW1 (`BOOTMODE`) → tap SW2 (reset) → release SW1 → upload**325326**Bad firmware cannot brick this board.** The ROM bootloader is mask ROM and always answers327that sequence:328329```sh330esptool --chip esp32p4 -p <port> flash-id # chip banner with revision, and 16 MB331esptool --chip esp32p4 -p <port> chip-id332esptool --chip esp32p4 -p <port> erase-flash333```334335esptool **5.3.0** comes with the pinned platform; it renamed `esptool.py` to `esptool` and336the underscore commands to hyphens, keeping the old spellings working with a warning.337338The one genuinely unrecoverable mistake is burning `EFUSE_0PXA_TIEH_SEL_0`, which switches339`VDDO_FLASH` to 1.8 V permanently on a 3.3 V flash. eFuses are one-time. Do not run340`espefuse` on this board.341342## Reporting343344Say what is verified and what is derived.345346**Verified on hardware** (a rev v1.3 board, by the project this skill was extracted from):347the silicon-revision trap of rule 1 and its exact `Illegal instruction` symptom; the SCons348packaging conflict of rule 3 and the manifest patch that fixes it; the partition-table349source of rule 4; the temperature-sensor range trap of rule 17; that the board reports350ESP32-P4 rev v1.3, 32 MB PSRAM, 16 MB flash (JEDEC `0x684018`), 360 MHz measured; and the351memory bandwidth figures in `board-hardware.md` §10.352353**Verified against ESP-IDF 5.5.5 itself** (the copy the pinned platform installs), not354just against the vendor's demos: the revision Kconfig and its "mutually exclusive" wording;355that `ESP32P4_REV_MIN_301` is the default; the SDMMC slot-0 IO MUX pins (`sdmmc_pins.h`356gives CLK 43, CMD 44, D0-D3 39-42, D4-D7 45-48 — the board's wiring exactly) and that slot 1357does not use IO MUX, which is why the C6 sits there; `sd_pwr_ctrl_by_on_chip_ldo.h`, whose358own comment names LDO channel 4 for SDMMC IO; `esp_ldo_regulator.h` and its four channels;359the P4 temperature range table; `ADC2_CHANNEL_4_GPIO_NUM 53`; `SOC_GPIO_PIN_COUNT 55`,360`SOC_I2S_NUM 3`, `SOC_TWAI_CONTROLLER_NUM 3`, `SOC_TOUCH_SENSOR_NUM 14`; the RMII pad lists361in `emac_periph.c`; and that `ETH_ESP32_EMAC_DEFAULT_CONFIG()` for the P4 is this board's362pin set. The esptool command spellings were checked by running the 5.3.0 binary.363364**Verified in this session:** both template variants build clean with zero warnings at365PlatformIO Core 6.2.0 / pioarduino 55.03.311 / ESP-IDF 5.5.5, at the flash and RAM figures366quoted above; the generated sdkconfig carries the revision, PSRAM and console settings; the36716 MB partition CSV in `recipes.md` §12 builds and produces the partition sizes it claims;368and a missing `CONFIG_SPIRAM` fails at link, not at runtime (rule 16).369370**Schematic-derived, high confidence.** Every pin in `board-hardware.md` §2 is traced on371Guition's own schematic sheets. That includes the facts most likely to be got wrong372elsewhere: the JP1 pinout and its four ESP32-C6 positions; that GPIO14-19 never reach a373module pin; that the TF card's VDD comes from on-chip LDO channel 4 through an374always-on switch (`R10` unpopulated, so GPIO45 is free); that `PA_CTRL` has a 10 K375pull-down; that RS485 direction is a hardware one-shot with no GPIO; and the ten Ethernet376RMII pins.377378**Vendor code, high confidence.** The SDIO link parameters, the SD slot and LDO channel,379the DSI LDO channel and voltage, the I2C addresses, the ADC unit/channel for the battery380and the Ethernet MDC/MDIO/PHY-address all come from Guition's own demos in the product381archive, most of which vendor Espressif's `esp32_p4_function_ev_board` BSP unmodified.382383**Primary-source.** The GPIO inventory, strapping tables, boot modes, ADC channel maps and384the three USB controllers in `reference/esp32p4-soc.md` are from the ESP32-P4 Series385Datasheet v0.5 — which is marked **PRELIMINARY** on every page.386387**Corrected during a second verification pass — do not reintroduce these:**388- The RMII data pins are **not** "fixed in copper". They are IO MUX pads with a short list389 of alternatives each, selectable through `emac_dataif_gpio.rmii`; the board simply uses390 the same set ESP-IDF already defaults to.391- `temperature_sensor_install()` fails with **`ESP_ERR_INVALID_ARG`** ("Out of testing392 range"), not `ESP_ERR_NOT_FOUND`.393- A pin in `GPIO_MODE_INPUT_OUTPUT` reads the **pad**, not an output latch. The distinction394 matters: on an unloaded pad the read-back still passes, which is why the GPIO28 mistake395 went unnoticed.396- **IP101** and **PHY address 1** come from Guition's demo sdkconfig. The schematic labels397 the PHY only `U4`, and which strap resistors set the address is not shown.398- esptool 5.3.0 uses `esptool` and hyphenated commands (`flash-id`, `chip-id`,399 `erase-flash`).400- The ESP32-P4 datasheet describes **no CAN FD** — three TWAI controllers, CAN 2.0, up to401 1 Mbit/s — and ESP-IDF defines no FD capability for it, contradicting the CAN FD row in402 `reference/esp32-family.md`, which is second-hand from Espressif's product selector.403- The C6 variant inside the module is not named anywhere in Guition's material; say404 "an ESP32-C6", not a specific part number.405406**Known contradictions — quote them as contradictions, not as facts:**407- **Guition's xiaozhi board file defines `BOOT_BUTTON_GPIO` as 21.** GPIO21 is the touch408 panel's interrupt line. The boot button is SW1 on **GPIO35**. Do not copy that define.409- **The schematic net `ES7210_SDOUT` names a chip this board does not have** (rule 11).410- **Two different DSI porch sets** for the same 800 × 1280 panel ship in the same archive —411 Guition's xiaozhi board file and Espressif's BSP disagree. `recipes.md` §8.412- **The specification PDF claims "up to 400 MHz"**; a rev v1.3 board runs 360, and reports413 360.414- **The Getting Started PDF is for a different Guition board** (`JC1060P470`) and says so415 in its own text. Its Arduino IDE steps still apply.416417**Not verified anywhere.** No DSI panel, camera, SD card, Ethernet cable, RS485 device,418speaker, microphone or battery was attached in this session, and nothing was flashed here.419The display, audio, storage, Ethernet, RS485, battery and Wi-Fi recipes are marked420"not compiled in this session" individually — say so rather than presenting them as421certain.