The overview, with examples running, is on the board page and The ESP32-S3 model (every register).
What it is
The ESP32-S3-DevKitC-1, Espressif's board for the ESP32-S3, running on our own Xtensa core. Firmware is an Xtensa ELF talking to the real ESP32-S3 addresses, and almost every one of those addresses was checked against Espressif's technical reference manual.
The board is 62.7 by 25.4 mm and its two rows of 22 pins are 0.9 inch apart, so it straddles a breadboard's center channel with one row of holes left free on each side, like the classic ESP32 DevKit.
The pins
Twenty-two down each long edge, the two micro-USB sockets at the bottom, the module and its antenna at the top. The silkscreen names each GPIO by its number.
J1, the left column, top to bottom: 3V3, 3V3, RST, 4, 5, 6, 7,
15, 16, 17, 18, 8, 3, 46, 9, 10, 11, 12, 13, 14, 5V,
G.
J3, the right column, top to bottom: G, TX, RX, 1, 2, 42, 41,
40, 39, 38, 37, 36, 35, 0, 45, 48, 47, 21, 20, 19, G,
G.
TX and RX are GPIO 43 and 44, UART0. RST is the chip enable. 5V is the
USB rail. This is a 3.3 volt board and its pins are not 5 V tolerant.
Things the pinout does to you
- GPIO 35, 36 and 37 belong to the PSRAM on the octal-PSRAM boards (the N8R8 most people buy). They are on the header, and on those boards you must not use them. Mokxi has no PSRAM, so here they work, which a desk might not.
- GPIO 19 and 20 are the USB port's D- and D+. Drive them and the "USB" socket stops working on a real board. Here the USB serial port keeps going, which is kinder than the silicon.
- GPIO 0, 3, 45 and 46 are strapping pins, so what is wired to them at power on matters. GPIO 0 is also the BOOT button.
- Some pins power up with their input switched off. GPIO 4 to 8, 15, 16 and
19 to 21 read 0 until
pinModeturns the input buffer on, which is the chip's reset state.pinModealways does it, so a sketch never notices.
The RGB LED
The board has no plain LED. It has an addressable RGB LED, a WS2812-type
part, on GPIO 48 on the first boards and on GPIO 38 on v1.1, which
Espressif lists as the only difference between the two revisions. The board's
revision property picks which one is on your breadboard.
LED_BUILTIN on this board is not a GPIO number: as in the Arduino core, it is
the GPIO count plus the LED's pin, and digitalWrite(LED_BUILTIN, HIGH) sends
the LED a frame that lights it white at a quarter brightness. For color,
rgbLedWrite(RGB_BUILTIN, red, green, blue). Both go out through the chip's
RMT peripheral, 24 bits green first, every bit inside the WS2812B
datasheet's timing, and the LED on the board lights with whatever color the
frame carries.
The examples are built for GPIO 48, as the Arduino core's board definition is.
On a v1.1 board the LED is on GPIO 38, so the same sketch leaves it dark, which
is what would happen on a desk. The pin is also on the header, so a ws2812
strip wired to 48 sees the same frames.
analogRead: ten channels, and 2.9 V is the top
ADC1's ten channels are GPIO 1 to 10: channel n is GPIO n + 1. Twelve
bits. At the default 12 dB attenuation the datasheet's measurement range ends at
2.9 V, and Mokxi reads 4095 from there up, so a potentiometer across the
3.3 V rail reads 4095 over the top eighth of its travel. The knob example
prints the raw number so that is not a mystery.
That straight line up to 2.9 V is an approximation: a real S3 keeps a little headroom above the range and bends at both ends, corrected from calibration burned into the chip. ADC2 is not modeled.
analogWrite is LEDC, and it costs the core nothing
analogWrite(pin, 0..255) attaches one of LEDC's eight channels to the pin:
eight bits at 1 kHz, on any GPIO, through the GPIO matrix.
ledcAttach(pin, frequency, bits) and ledcWrite(pin, duty) are there when the
frequency matters. On the S3, LEDC settings only take effect when an update bit
is written, and the runtime writes it; a fading LED costs the core nothing.
Serial, and the two USB sockets
A real DevKitC-1 has two micro-USB sockets. "UART" goes through a
USB-to-UART bridge to UART0: that is Serial, as in the Arduino core with USB
CDC On Boot switched off, its default for this board. "USB" is the chip's
own USB Serial/JTAG controller: that is USBSerial, which sends a 64-byte
packet at a time, at the end of each line.
The serial monitor here listens to both at once, so either one prints in the same place, and what you type goes to both.
One core, not two
A real S3 has two Xtensa LX7 cores, and an Arduino sketch here runs on
one. A sketch written around setup() and loop() never notices.
Anything that starts a task on core 1 will not run.
A firmware you built yourself is different: MicroPython and an ESP-IDF build run on a model of the whole chip, where both cores do run (below).
What is modeled
The Xtensa LX7, which for everything a compiler emits from C is the classic
ESP32's LX6 instruction set: the same windowed ABI, and the S3 compiler's output
was checked byte for byte against the ESP32 compiler's. Around it: 416 KB of
SRAM seen through both buses, the GPIO matrix and IO MUX with the manual's reset
pulls on every pin, UART0, the USB Serial/JTAG serial port, SYSTIMER behind
millis() and micros(), ADC1, LEDC, the RMT's four transmit channels, the
clock gates, and as much of the interrupt matrix as four sources need.
WiFi, simulated
There is no radio. What there is is Mokxi's simulated network, the same
one the classic ESP32 and the ESP32-C3 have, behind a block that is Mokxi's own
rather than the chip's, at an address the S3 leaves unmapped. WiFi.h,
HTTPClient.h and WebServer.h work the way a tutorial expects: the board
joins an access point whose name and password are properties of the board,
fetches a page from a made-up address under .mokxi, or serves one to the Web
panel. There is no 802.11, no TCP, no TLS and no real internet. The one
exception is the Real internet switch in the
Cloud panel, which sends requests for other names out through Mokxi's gateway.
Bluetooth LE is simulated the same way, with a phone in the editor's Bluetooth
pane (Bluetooth, simulated).
WiFi, simulated is how to use it; Simulated WiFi is the contract.
What is not
A radio of any kind: WiFi and Bluetooth LE are simulated, with no radio
under them. The second core. The FPU and the
S3's vector instructions: both fault rather than returning a wrong number, and
the runtime is soft float. SRAM0, the cache, flash and PSRAM. The RTC, the
ULP coprocessors and deep sleep. ADC2, the touch sensor and the
temperature sensor. The timer groups' timers (their watchdogs are modeled, for the task
watchdog). UART1 and UART2,
the I2C and SPI controllers, I2S, the camera interface, TWAI and USB OTG.
Wire and SPI in the runtime are software on ordinary pins, as on every board
here: SDA on 8, SCL on 9, and SPI on 10 to 13.
Vendor ESP-IDF and Arduino-core binaries will not run here: the runtime is ours.
Compiling your sketch
Edit the sketch and press Run: it compiles in the tab with Espressif's clang
for Xtensa, the same toolchain as the classic ESP32 and the ESP8266 (clang-v3,
about 80 MB, downloaded once). Nothing is uploaded. An untouched example runs
its prebuilt program, built with Espressif's GCC for the S3; nothing of GCC is
linked into it.
Floating-point arithmetic works: this model has no FPU, so the build does
float and double sums in software, as on the boards with no FPU at all.
Compiling in the browser has the full account.
The examples
Blink, Rainbow, Button, Serial, USB serial, Fade, Knob, and the four WiFi ones: WiFi: join the network, WiFi: fetch the weather, API lab: fetch JSON and WiFi: a lamp on a web page.
A firmware you built yourself
An Arduino sketch is built here, and it runs on one core. A program built
somewhere else, with ESP-IDF or in Rust (esp-hal, esp-idf-hal), runs too, on
a model of the whole chip with both cores: upload its .bin or .elf in
the Firmware panel, and the board boots it as after idf.py flash. Wi-Fi and
Bluetooth are the gap, since their drivers are Espressif's closed libraries:
a firmware that starts either one stops with a line saying so. The steps and
the whole list are in
Run a prebuilt firmware.
MicroPython and CircuitPython
Pick MicroPython (main.py) in the board's Firmware panel and Run boots the
official MicroPython v1.29.0 firmware for the ESP32-S3 with your main.py, on
a model of the whole chip booted from Espressif's own ROM. machine.Pin,
PWM, ADC, I2C, SPI, UART(1) and neopixel work, and network.WLAN
joins the simulated network. See
MicroPython on the ESP32.
Pick CircuitPython (code.py) instead and Run boots the official CircuitPython 10.3.1 firmware for this board, with its CIRCUITPY drive and its REPL on the S3's own USB port. WiFi is not simulated under CircuitPython here. See CircuitPython on the Pico, which covers this board too.
Elsewhere
- The board page: /boards/esp32-s3
- The contract document: the ESP32-S3 model, whose section 6 lists the few numbers that are believed rather than checked
- The other Xtensa boards: the ESP32 DevKit and the ESP8266 NodeMCU
- The same chip on other boards: the XIAO ESP32-S3 and the Arduino Nano ESP32