ESP32 Peripheral Bring-up
Bring a bus up in small, verifiable steps: pins → electrical → minimal config → probe → read known register → full speed → error handling.
Tools
If the esp32-workbench MCP server is connected, call its tools; otherwise run the
CLI. If esp32wb is not on PATH, use
uvx --from git+https://github.com/agodianel/esp32-claude-workbench esp32wb <args>.
Add --json for machine-readable output.
| Need | MCP tool | CLI |
|---|---|---|
| Is this pin usable on this chip? | chip_info, pin_audit | esp32wb chip <target>, esp32wb pins . |
| Driver API / limits for the target (always before writing driver code) | search_esp_docs | esp32wb docs search "i2c master probe" --target T (index once: esp32wb docs index, needs pip install 'esp32-workbench[docs]') |
| Summarise error output | log_summary | esp32wb logs monitor.log |
Before writing driver code
- Target chip + ESP-IDF version (API generation differs: v5.x has new I2C master,
esp_adconeshot, etc.). - Pin plan checked with
esp32wb pins .— no flash/PSRAM/USB/console pins, strapping pins only with a reason, input-only pins only as inputs. - Peripheral instance count for the chip (number of I2C/SPI/UART ports, LEDC channels, ADC units differs per target) — check docs, do not assume classic ESP32.
- Device datasheet: voltage levels (3.3 V I/O — never 5 V into a GPIO), address/mode, timing, power-up delay.
- An implementation contract exists for the change.
Per-peripheral quick guide
I2C
- External pull-ups on SDA/SCL (typ. 2.2–4.7 kΩ to 3.3 V); internal pulls are too weak.
- Start at 100 kHz; use
i2c_master_probe()(new driver) to scan. - 7-bit addresses (datasheet
0xD08-bit write address =0x68). - Don't mix the legacy
driver/i2c.hand newdriver/i2c_master.hAPIs in one build unless the IDF version explicitly allows it. - Full procedure: I2C bring-up.
SPI
- Mode (CPOL/CPHA) from the device datasheet — the #1 failure cause.
- Start at 1 MHz;
.lengthis in bits. - IOMUX pins allow the highest clock; GPIO-matrix routing lowers the max — check the SPI master timing section for your chip.
- DMA buffers from
MALLOC_CAP_DMAmemory. - Full procedure: SPI bring-up.
UART
- Match baud, data bits, parity, stop bits, and flow control on both ends; cross TX→RX.
- Do not take UART0 console pins unless the console is moved.
- RX buffer passed to
uart_driver_install()must exceed the hardware FIFO. - Full procedure: UART bring-up.
ADC
- Use
esp_adc(adc_oneshot_*+adc_cali_*) on IDF v5; legacydriver/adc.his deprecated. - ADC2 + Wi-Fi is chip-specific (classic ESP32: unusable with Wi-Fi; S2/S3: arbitrated, reads can fail; C3: ADC2 oneshot unsupported) → prefer ADC1.
- Calibrate and report millivolts, not raw counts; attenuation sets the input range.
- Full procedure: ADC bring-up.
LEDC (PWM)
LEDC_HIGH_SPEED_MODEexists only on classic ESP32; other chips useLEDC_LOW_SPEED_MODE.- Frequency × 2^resolution must be achievable from the timer clock source.
- Full procedure: LEDC bring-up.
Bring-up procedure (all buses)
- Power and wiring: measure supply at the device, common ground, short wires.
- Minimal config at the slowest sensible speed, explicit pins (never rely on defaults).
- Probe: I2C probe / SPI read of a WHO_AM_I or ID register / UART loopback / ADC on a known voltage / LEDC on a scope or LED.
- Check every
esp_err_t; log withesp_err_to_name(). - Scale up: target speed, DMA, interrupts, multiple devices.
- Harden: timeouts, retries, bus recovery, de-init path, mutex if the bus is shared between tasks.
- Evidence: serial log of probe + readings, logic-analyzer capture if available.
Report
markdown# Bring-up — <device> on <bus> (target: <chip>, IDF <ver>) | Signal | GPIO | Chip category (esp32wb) | Notes | ## Configuration (speed, mode, address, pulls) ## Results (probe / ID register / readings, with log excerpts) ## Issues found and fixes ## Not verified (e.g. no scope available)
Rules
- Never hallucinate peripheral limits; search the docs for the target first.
- Pin choices must pass
esp32wb pinsfor the configured target. - Any code change goes through the mission/contract workflow.


