technique

Chips, boards, and configs

The ESP32 family as the ESP32 Inspector catalogs it: which chips and boards exist on the workbench, and the five configs that group them by processor core and USB path.

Before this

This page assumes you are comfortable with:

Why you need this

Every later step depends on two facts about the board in your hand: which processor core it has, and how its USB port reaches that core. The core decides which compiled programs and which assembly will run on it. The USB path decides how you flash it, how it resets, and how a program talks back to your computer. Get either one wrong and a correct program refuses to flash, or flashes and then stays silent.

The idea

Three words get mixed up, so pin them down first.

Word What it is Example
Chip The silicon: processor cores, RAM, radios, and peripherals in one package. ESP32-C6
Module A chip on a small shielded board together with flash memory, a crystal, and an antenna. ESP32-C6-WROOM-1-N4 (4 MB of flash)
Board A module plus what makes it usable on a desk: a USB connector, a voltage regulator, buttons, pin headers, maybe a screen. ESP32-C6-DevKitM clone

An instruction set is the list of machine instructions a processor core understands. The ESP32 family uses two of them. The classic ESP32 has Xtensa LX6 cores and the ESP32-S3 has Xtensa LX7 cores; the ESP32-C6 and ESP32-P4 have RISC-V cores. A program compiled for Xtensa is meaningless to a RISC-V core, and the reverse.

The USB path is how bytes get from your computer to the core. There are two kinds.

  • A bridge chip. A separate chip on the board (CH340, CP2102, or CH343) converts USB into UART0, the chip's first plain serial port (a UART, universal asynchronous receiver-transmitter, sends bytes one bit at a time on a wire).
  • Native USB-Serial-JTAG. A USB block inside the chip itself, which your computer sees as a serial port (and as a debugger). No bridge chip.

A config is core plus USB path. The ESP32 Inspector sorts every board it knows into five configs, and this page mirrors its catalog. New configs join the Inspector over time; when one does, this table grows with it.

Config Chip Core USB path Boards
lx6-uart0 ESP32 Xtensa LX6 UART0 through a CH340 or CP2102 bridge, 115200 baud CYD, CYDE, WROOM-32 DevKit
lx7-uart0 ESP32-S3 Xtensa LX7 UART0 through a CH343 bridge YD-ESP32-S3 (its right-hand port)
lx7-usbjtag ESP32-S3 Xtensa LX7 native USB-Serial-JTAG Adafruit Feather ESP32-S3, Super Mini ESP32-S3
rv32-usbjtag ESP32-C6 RISC-V (RV32IMAC) native USB-Serial-JTAG at 0x6000F000 ESP32-C6-DevKitM clone
rv32p4-usbjtag ESP32-P4 RISC-V (RV32IMAFC) native USB-Serial-JTAG at 0x500D2000 Waveshare ESP32-P4 Core DevKit

Boards in one config behave the same because a small program only ever touches the core and the serial path's registers. The CYD, the CYDE, and the WROOM-32 DevKit look nothing alike, but the Inspector flashes the same lx6-uart0 echo program to all three and it runs unchanged. The screen on the CYD does not matter to the echo.

What changes from one config to the next:

Thing Classic ESP32 ESP32-S3 ESP32-C6 ESP32-P4
Instruction set Xtensa LX6 Xtensa LX7 RISC-V RISC-V
Cores two, 240 MHz two, 240 MHz one at 160 MHz plus a low-power core two at 360 MHz plus a low-power core
Radios WiFi, Bluetooth Classic, Bluetooth Low Energy (BLE) WiFi, BLE WiFi 6, BLE, 802.15.4 (the radio Zigbee and Thread use) none
Bootloader flash offset 0x1000 0x0 0x0 0x2000
USB host possible no (no USB OTG in the silicon) yes no yes (separate USB 2.0 OTG header on the Waveshare kit)

The P4 is the odd one: it has no radio at all, so anything network-shaped on that kit needs another chip.

The workbench boards

These facts come from the author's board notes and the Inspector's catalog. The USB id is the vendor id and product id (VID:PID) a computer reads the moment you plug a board in.

Board Config USB id (VID:PID) Flash and PSRAM on the author's unit
CYD (ESP32-2432S028, the Cheap Yellow Display) lx6-uart0 0x1A86:0x7523 (CH340) 4 MB-class module
CYDE (Sunton E32R28T) lx6-uart0 0x1A86:0x7523 (CH340) 4 MB flash
WROOM-32 DevKit lx6-uart0 0x10C4:0xEA60 (CP2102) 4 MB flash
YD-ESP32-S3 lx7-uart0 0x1A86:0x55D3 (CH343, right port); 0x303A:0x1001 (native USB, left port) 16 MB flash, 8 MB PSRAM
Adafruit Feather ESP32-S3 lx7-usbjtag 0x303A:0x1001; Adafruit's vendor id 0x239A while CircuitPython runs 8 MB flash, or 4 MB flash with 2 MB PSRAM, by variant
Super Mini ESP32-S3 lx7-usbjtag 0x303A:0x1001 4 MB flash, 2 MB PSRAM
ESP32-C6-DevKitM clone rv32-usbjtag 0x303A:0x1001 4 MB flash
Waveshare ESP32-P4 Core DevKit rv32p4-usbjtag 0x303A:0x1001 32 MB flash, 32 MB PSRAM

PSRAM is extra RAM in a separate chip or package, slower than the chip's own SRAM. 0x303A is Espressif's vendor id, and 0x1001 is what every native USB-Serial-JTAG port reports, so five different boards share that one id.

Four clues that identify a board

  1. USB VID:PID. Free and instant. It names the bridge chip or says "native USB". It does not name the board.
  2. Chip id from the ROM. The ROM bootloader is code built into the chip at the factory. In download mode it answers a flashing tool (esptool, or the Inspector in the browser) with the chip type and silicon revision. That narrows the list to one chip family.
  3. MAC address. A unique number burned into each chip. It names a specific unit, but only if you wrote that unit's MAC down earlier. Record one per board.
  4. The firmware already on it. This is the weakest clue. Firmware identifies what it was built for, not what it is running on. The author's P4 kit arrived running a demo for a different Waveshare product with a touch screen, and was first logged as that product until photos of the silkscreen settled it.

The ESP32 Inspector's board detection page runs clues 1 to 3 for you in desktop Chromium over Web Serial, compares them with its catalog, and names the config.

Worked example

A board with one USB-C port and no screen turns up in a drawer. Here is the identification, one clue at a time.

Step What you do What you see Boards still possible
1 Plug it in and read the USB id 0x303A:0x1001, "USB Serial Device" YD-ESP32-S3 (left port), Feather ESP32-S3, Super Mini ESP32-S3, C6 DevKitM clone, P4 Core DevKit: 5
2 Hold BOOT, tap reset, ask the ROM ESP32-C6, revision v0.2 C6 DevKitM clone: 1
3 Read the config off the table RISC-V core, native USB-Serial-JTAG config rv32-usbjtag
4 Read the MAC and compare with your records matches a recorded C6 unit, or becomes a new record that exact unit
5 Flash the rv32-usbjtag echo and type abcXYZ ABCXYZ comes back proven: core, USB path, and flash all work

Step 1 cut eight catalog boards to five. Step 2 cut five to one. Step 5 is the real test: a board that echoes has a working core, a working USB path, and a working flash.

Now a contrast. A second board with a screen reports 0x1A86:0x7523, a CH340. Step 1 leaves the CYD and the CYDE. Step 2 says ESP32-D0WD-V3 for both, because they carry the same die. Only a recorded MAC tells them apart. But you do not need to know which one it is to flash it: both are lx6-uart0, so the same programs, offsets, and pin map apply. The config is the answer that matters; the board name is bookkeeping.

In an ESP32 project

This is stage 1 of the pipeline on the hub: Choose. The config you settle on here picks almost everything downstream: which echo payload proves the board, whether you read RISC-V assembly or Xtensa assembly, which bootloader offset Flashing and the ROM bootloader uses, and which half of Serial over UART and USB applies. The other half of stage 1 is Choosing a language, and not every language runs on every chip.

Common mistakes

  • Two boards with the same bridge plugged in at once. The CYD and the CYDE both enumerate as CH340, and their COM port names can swap. Symptom: you flash one board and the new program shows up on the other, or not at all.
  • Assuming CYD knowledge carries to an S3 or a C6. S3 boards use different GPIO assignments and a different bootloader offset, and the C6 is not even Xtensa. Symptom: a boot loop, or a program that runs but drives the wrong pins.
  • Trusting the firmware banner. Symptom: you wire to pins from the wrong product's documentation. The author's P4 kit, running its factory demo, also hung with a task-watchdog message every 5 seconds because the demo expected a display that was not attached. That is not a fault, just the wrong firmware.
  • Wrong bootloader offset. Writing the P4's bootloader at 0x0 instead of 0x2000 leaves the ROM looping on "invalid header".
  • The wrong port on the YD-ESP32-S3. Its left port is the S3's own USB (host or device), and its right port is the CH343 bridge to UART0. The author's notes flash and monitor through the right port. Symptom: no COM port with the name you expected, or a port that never answers.
  • Missing driver for the CP2102 on Windows. Symptom: Device Manager shows the WROOM-32 DevKit in an error state and no COM port appears until the Silicon Labs CP210x driver is installed.

Cost

Identifying a board costs a minute with the Inspector or esptool and a written note of the MAC. Skipping it costs far more: most "my code does nothing" sessions on a mixed desk turn out to be the wrong board, the wrong port, or the wrong offset. The board choice also sets your resource ceiling for the life of the project. A 4 MB flash board (CYD, C6 DevKitM) holds an interpreter plus a modest program, while the YD-ESP32-S3 (16 MB flash, 8 MB PSRAM) and the P4 kit (32 MB of each) leave room for images, fonts, and logs. Power matters too if a board runs from a battery: the author's Feather ESP32-S3 notes give about 100 µA in deep sleep. And radio needs rule boards out entirely: no WiFi project fits on the P4 kit by itself.

Going further

  • Choosing a language, the other half of stage 1
  • Flashing and the ROM bootloader, for what the ROM's chip id conversation looks like on the wire
  • Espressif's datasheet for each chip, which lists cores, memory, and radios
  • esptool's chip-id and flash-id commands, run against each board on your desk
  • The ESP32 Inspector's product appendix, which keeps this catalog current

Leads to

Back to ESP32 development: assembly, C, MicroPython, and CircuitPython