Topic hub
ESP32 development: assembly, C, MicroPython, and CircuitPython
How to program ESP32 boards four ways, from Python on a REPL down to assembly on bare silicon, with the electronics and computer basics underneath.
The problem
ESP32 is a family of chips from Espressif. The boards this cluster covers fall into five configs, defined by two things: the processor design (Xtensa on the original ESP32 and the S3, RISC-V on the C6 and P4) and how USB reaches the chip (a separate bridge chip into the first serial port, or the chip's own USB block). Every chip here except the P4 has a WiFi and Bluetooth radio. On top of that, this cluster programs them four ways, each with its own workflow, tools, and failure modes. Many lost hours come from the combinations: a program built for the wrong processor design, flashed at the wrong offset, or listening on the wrong USB path. Chips, boards, and configs sorts that out before anything else.
This cluster teaches all four ways side by side. MicroPython and CircuitPython let you type Python at the board and see the result immediately. C with ESP-IDF, Espressif's own framework, gives you the whole chip at full speed. Assembly shows you exactly what the processor does, one instruction at a time, in both of the family's instruction sets. Underneath them sit a handful of first-year ideas about electricity, binary numbers, and how a processor runs a program. Each of those has its own page. Follow the "Before this" links downward until you reach something you already know, then read back up.
The pipeline
Every page points back to this picture of an ESP32 project.
| Stage | Question it answers | Techniques that live here |
|---|---|---|
| 1. Choose | Which board, which config, and which language fit the job? | Chips, boards, and configs, Choosing a language |
| 2. Write the program | What does the same program look like in each language? | MicroPython on the ESP32, CircuitPython on the ESP32-S3, C with ESP-IDF, RISC-V assembly, Xtensa assembly |
| 3. Flash and boot | How does code get onto the chip, and what runs before your first line? | Flashing and the ROM bootloader, The boot sequence |
| 4. Talk to hardware | How does the program use pins, serial, buses, and a screen? | GPIO: buttons and LEDs, Serial over UART and USB, I2C and SPI peripherals, Driving the CYD display |
| 5. Go wireless | How do boards join WiFi, talk to each other, and update themselves? | WiFi and MQTT, ESP-NOW and Bluetooth LE, Over-the-air updates |
| 6. Debug | Why does the board reset, loop, or go silent? | Debugging resets and crashes |
Two stage 3 problems from the author's own projects: a P4 bootloader written at the wrong offset, which left the chip's ROM looping on "invalid header", and a C6 that reset-looped across several debugging sessions because of its boot path, not because of a bug in the program. Debugging resets and crashes tells the C6 story.
Which page for which job
You have a board and do not know what it is. Start at Chips, boards, and configs. The ESP32 Inspector's board detection page identifies a board plugged into a desktop Chromium browser over USB and tells you its config.
You want the fastest path to a blinking LED. Choosing a language, then MicroPython on the ESP32, then GPIO: buttons and LEDs.
You want to understand what the chip is really doing. How a CPU runs instructions, Memory maps and registers, then RISC-V assembly.
The board will not flash, or flashes and then does nothing. Flashing and the ROM bootloader, The boot sequence, then Debugging resets and crashes.
You want a sensor reading on your phone. I2C and SPI peripherals, then WiFi and MQTT.
You have a CYD (Cheap Yellow Display). Driving the CYD display, after the I2C and SPI page.
The running example
Two threads run through the cluster.
The uppercase echo: type a letter on your computer, and the board sends it back uppercase. It is a small program that proves a board can receive, compute, and send. It exists, hardware-proven, in assembly for every configuration the ESP32 Inspector supports, and this cluster adds short MicroPython, CircuitPython, and C versions so the language pages can compare all four. Those three are labeled as written for this site and not tested on hardware.
The real projects: each technique page's deep example is excerpted from working projects built on these boards: the ESP32 Inspector's test programs, a sensor dashboard that publishes over MQTT, a USB keyboard reader with an ESP-NOW display, a teaching machine on a CYD, a CYD that flashes another ESP32 through its ROM bootloader, and a memory-debugger program written in assembly for the C6. Every code block on every page says where it came from.
The basics underneath
None of these needs more than first-year college material, and most need less.
| You need | For |
|---|---|
| Voltage, current, and Ohm's law | Wiring an LED and a button without damaging anything. |
| Digital logic and pull-up resistors | Why a pin reads 0 or 1, and why an unconnected one reads garbage. |
| Binary and hexadecimal | Reading addresses, registers, and bit masks. |
| Memory maps and registers | How writing to an address talks to hardware. |
| How a CPU runs instructions | The model every language here ends up running on. |
| Interpreters and compilers | Why Python on a board feels different from C or assembly. |
| Flash, RAM, and partitions | Where code and files live, and what survives a power cut. |
| Serial communication basics | How a byte travels down one wire. |
| Polling and interrupts | Two ways a program notices that something happened. |
| Networking basics | WiFi, IP, TCP and UDP, HTTP, and publish-subscribe. |
Conventions used across this cluster
So the pages agree with each other:
- Chips are the ESP32 (the original), ESP32-S3, ESP32-C6, and ESP32-P4. The ESP32 and S3 use Xtensa processor cores; the C6 and P4 use RISC-V.
- Configs are the ESP32 Inspector's groupings of processor core plus USB path:
lx6-uart0,lx7-uart0,lx7-usbjtag,rv32-usbjtag,rv32p4-usbjtag. Boards in the same config behave the same way. New configs join the Inspector over time, and Chips, boards, and configs mirrors its catalog. - Numbers in hex are written
0x6000F000; binary is written0b0110. For memory and flash, 1 KB is 1024 bytes. - Pins are written GPIO 21. Logic is 3.3 V.
- C means C with ESP-IDF throughout. There is no C++ here.
- Every code block is labeled: excerpted from a named project (hardware-proven), written for the page (not hardware-tested), or from official documentation.
Recommended software
One tool per job. Names only, except the Inspector, which is linked because it is part of this site's family.
| Job | Pick | Why | Also fine |
|---|---|---|---|
| Identifying a board, flashing it, and checking it works, from a browser | The ESP32 Inspector (board detection page) | Detects the chip and board over USB, flashes a known-good test program for its config, and checks the board echoes back. Desktop Chromium only, because it uses Web Serial. | |
| Flashing from the command line | esptool | Espressif's own flasher; every other tool uses its protocol. | The ESP-IDF idf.py flash command, which calls it |
| C development | ESP-IDF | Espressif's framework: drivers, FreeRTOS, WiFi, and the build system the Inspector's own test programs use. | Its editor extension for VS Code |
| MicroPython | Thonny for a first REPL; mpremote once you script it | Thonny shows the REPL and the board's files in one window; mpremote is MicroPython's own command-line tool. | ampy, rshell |
| CircuitPython | The CIRCUITPY drive with any text editor, or the web workflow | On boards with native USB the board appears as a drive and reruns code.py when you save it. |
Mu editor |
| Assembly | The ESP32 Inspector's assembly pages, or ESP-IDF with a .S file |
The Inspector assembles in the browser and flashes the result; ESP-IDF builds .S files alongside C. |
|
| Watching serial output | Any serial monitor | The Inspector's Monitor tab, idf.py monitor, or Thonny's shell all work. |
PuTTY, screen, minicom |
Settings that matter in any tool. One board plugged in at a time while you learn: two boards with the same USB bridge chip can swap port names. Match the baud rate (115200 is the usual) on UART boards. Close every other program holding the serial port before you flash.
Prices and versions are deliberately absent except where a page pins a version its example was proven on.
How to read this cluster
The learning path below is sorted so that each row depends only on the rows above it. If you already know some electronics, skip to Chips, boards, and configs. If you are here for one language, start at its page and follow its links back only as far as you need.
Learning path
Each row depends only on rows above it. Read top to bottom, or jump to a technique and follow its "Before this" links downward.
- prerequisiteBinary and hexadecimalHow computers write numbers in base 2 and base 16, and how to read and flip individual bits.
- prerequisiteVoltage, current, and Ohm's lawWhat voltage, current, and resistance are, and the one equation that relates them, enough to wire an LED and a button safely.
- prerequisiteNetworking basicsJust enough networking for a microcontroller: WiFi joining, IP addresses, TCP and UDP, HTTP, and publish-subscribe messaging.
- prerequisiteDigital logic and pull-up resistorsHow a pin decides between 0 and 1, why an unconnected input floats, and how pull-up and pull-down resistors fix it.
- prerequisiteMemory maps and registersHow a chip gives every RAM byte and every hardware control a numbered address, so reading or writing an address talks to the hardware.
- prerequisiteHow a CPU runs instructionsThe fetch-decode-execute loop, registers, the program counter, the stack, and function calls, the model every language here compiles or interprets down to.
- prerequisiteFlash, RAM, and partitionsWhere code and data live on an ESP32: flash that survives power-off, RAM that does not, PSRAM, and the partition table that divides flash into regions.
- prerequisiteInterpreters and compilersThe difference between running source code through an interpreter on the chip and translating it to machine code before it ever reaches the chip.
- prerequisitePolling and interruptsTwo ways a program notices that something happened: asking over and over, or being interrupted when it does.
- prerequisiteSerial communication basicsHow bytes travel one bit at a time over a wire: baud rate, start and stop bits, and the difference between a UART and USB.
- techniqueChips, boards, and configsThe 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.
- techniqueI2C and SPI peripheralsThe two buses most sensors and displays use: I2C addresses and pull-ups, SPI clock and chip selects, and how to find a device that will not answer.
- techniqueChoosing a languageMicroPython, CircuitPython, C with ESP-IDF, or assembly: what each is good at, what it costs, and the same uppercase echo in all four.
- techniqueFlashing and the ROM bootloaderHow a program gets into flash: download mode, the ROM bootloader's serial protocol, esptool, the offsets that differ per chip, and flashing from a browser.
- techniqueDriving the CYD displayPutting pixels on the Cheap Yellow Display's ILI9341 screen: SPI commands, initialization, orientation, colors, the backlight, and touch.
- techniqueESP-NOW and Bluetooth LETalking board to board without a router using ESP-NOW, and to phones and computers with Bluetooth Low Energy.
- techniqueSerial over UART and USBThe two ways an ESP32 talks to your computer, UART0 through a bridge chip or the chip's own USB-Serial/JTAG, and why the echo program differs between them.
- techniqueC with ESP-IDFEspressif's own framework: an ESP-IDF project's layout, app_main, components, menuconfig and sdkconfig, building and flashing with idf.py, and FreeRTOS tasks.
- techniqueCircuitPython on the ESP32-S3Adafruit's Python for microcontrollers on the ESP32-S3: the CIRCUITPY drive or web workflow, code.py, the board module, and how it differs from MicroPython.
- techniqueThe boot sequenceWhat runs between power-on and your first line of code: the ROM, the second-stage bootloader, the app image, and how to read the boot log.
- techniqueGPIO: buttons and LEDsDriving outputs and reading inputs on ESP32 pins in all four languages, with pull-ups, debouncing, interrupts, and the pins you must not use.
- techniqueMicroPython on the ESP32Writing and running MicroPython on an ESP32: the REPL, boot.py and main.py, the board's filesystem, the machine module, and the gotchas that bite.
- techniqueRISC-V assembly on the ESP32-C6 and P4Writing RISC-V assembly for the C6 and P4: registers and ABI names, load, store, branch, and li, the uppercase echo line by line, and running it inside ESP-IDF or as a bare image.
- techniqueDebugging resets and crashesWhy a board reboots, loops, or goes silent, and a method for finding out: reset reasons, watchdogs, boot modes, and leaving yourself notes in memory that survives a reset.
- techniqueWiFi and MQTTJoining a WiFi network from an ESP32, making an HTTPS request, and publishing sensor readings to an MQTT broker.
- techniqueXtensa assembly on the ESP32 and ESP32-S3The other instruction set in the family: Xtensa LX6 and LX7 on the classic ESP32 and the S3, with register windows, literal pools, and the same echo for comparison.