The QT Py ESP32-S3 microcontroller ships running a NeoPixel rainbow swirl example. It's lovely, but you probably had other plans for the board. As you start working with your board, you may want to return to the original code to begin again, or you may find your board gets into a bad state. Either way, this page has you covered.
You're probably used to seeing the QTPYS3BOOT drive when loading CircuitPython or Arduino. The QTPYS3BOOT drive is part of the UF2 bootloader, and allows you to drag and drop files, such as CircuitPython. However, on the ESP32-S2/S3 the UF2 bootloader can become damaged.
Is double tapping the reset button not working to get you into the BOOT drive? Head down to the Factory Reset and Bootloader Repair section!
If you have a bootloader still installed - which means you can double-click to get the QTPYS3BOOT drive to appear, then you can simply drag this UF2 file over to the BOOT drive.
To enter UF2 bootloader mode, plug in the board into a USB cable with data/sync capability. Press the reset button once, wait till the RGB LED turns purple, then quickly press the reset button again. (You are doing a "slow double-click"). Then drag this file over:
There are two versions of this board: one with 8MB Flash/No PSRAM and one with 4MB Flash/2MB PSRAM. Each version has their own Factory Reset UF2. There isn't an easy way to identify which version of the board you have by looking at the board silk.
However, on the chip there is some text that denotes flash and ram size. If you see the text FN8C0, then it is the 8MB Flash/No PSRAM version. If you see the text FH4R2, then it is the 4MB Flash/2MB PSRAM version.
This text can be hard to see though since its so small. If all else fails you can try either build to see which one works.
Your board is now back to its factory-shipped state, running again with the original factory program. You can now begin again with your plans for your board.
Re-loading the factory reset UF2 isn't necessary to start over with the board, but it's a good way to show the board is working.
What if you tried double-tapping the reset button, and you still can't get into the UF2 bootloader? Whether your board shipped without the UF2 bootloader, or something damaged it, this section has you covered.
There is no protection for the UF2 bootloader. That means it is possible to erase or damage the UF2 bootloader, especially if you upload an Arduino sketch to an ESP32-S2/S3 board that doesn't "know" there's a bootloader it should not overwrite!
It turns out, however, the ESP32-S2/S3 comes with a second, built-in, bootloader, the ROM bootloader, which cannot be erased or damaged. You can always reload the UF2 bootloader using the ROM bootloader.
There are three ways to do a factory reset and bootloader repair. The first and easiest is to use the OPEN INSTALLER button on the page for your board on circuitpython.org. This method requires no manual downloads and guides you through the steps interactively. We highly recommend this method as your first choice.
The second method is to use the browser-based Adafruit WebSerial ESPTool, and the third is to use esptool.py via the command line.
For both OPEN INSTALLER and the Adafruit WebSerial tool, you must use a Chromium-based browser such as Chrome, Edge, Opera, or Chromium.
Installing the UF2 bootloader will erase everything on your board, including CircuitPython, any Arduino program, and any files stored in flash! Be sure to back up your data first.
The OPEN INSTALLER button on circuitpython.org is the easiest way to install or update the UF2 bootloader. See the Learn Guide Using the OPEN INSTALLER Button on circuitpython.org for all the details.
Adafruit WebSerial ESPTool and esptool.py Methods for UF2 Bootloader Installation
The other methods for bootloader installation require you to download the bootloader yourself. The next section walks you through the prerequisite steps needed for both of these methods.
Clik on the green button below to download the .bin file you need (there may be more than one listed), and save wherever is convenient for you. You will need to be able to access the file from the Adafruit WebSerial ESPTool or another upload method.
Note that this file is approximately 3MB. This is not because the bootloader is that large, but because the bootloader needs to write data at both the beginning and end of flash. Most of the file is empty.
There are two versions of this board: one with 8MB Flash/No PSRAM and one with 4MB Flash/2MB PSRAM. Each version has their own Factory Reset .bin file. There isn't an easy way to identify which version of the board you have by looking at the board silk. If you aren't sure which version you have, try either build to see which one works.
Check whether your board has 4MB Flash/2MB PSRAM or 8MB Flash/No PSRAM. For 4MB boards, choose the correct bootloader, depending on which version of CircuitPython you will be using.
This TinyUF2 bootloader provides a single 2.8MB firmware partition, which is needed for CircuitPython 10.0.0-alpha.5 and later versions. For CircuitPython 9.1.x and 9.2.x, either 4MB version below will work. See Update TinyUF2 Bootloader for CircuitPython 10 (4MB boards only) for more details.
This TinyUF2 bootloader provides two 1.4MB firmware partitions, required for CircuitPython 9.0.x and earlier, to support dualbank functionality:
This TinyUF2 bootloader is for 8MB Flash boards:
Step 2. Enter ROM bootloader mode
Entering the ROM bootloader is easy. Complete the following steps.
Before you start, make sure your ESP32-S2/S3 is plugged into USB port to your computer using a data/sync cable. Charge-only cables will not work!
To enter the bootloader:
- Press and hold the BOOT/DFU button down. Don't let go of it yet!
- Press and release the Reset button. You should still have the BOOT/DFU button pressed while you do this.
- Now you can release the BOOT/DFU button.
No USB drive will appear when you've entered the ROM bootloader. This is normal!
Now that you've downloaded the .bin file and entered the ROM bootloader, you're ready to continue installing the UF2 bootloader. The next two sections walk you through using the Adafruit WebSerial ESPTool (Alternative A) or esptool.py (Alternative B).
(There is also an Alternative C below, using the Arduino IDE, but it is less desirable, because it does not allow you to choose the bootloader that will be used.)
We highly recommend using the Adafruit WebSerial ESPTool method to perform a factory reset and bootloader repair. However, if you'd rather use esptool.py via the command line, you can skip this section and use Alternative B instead.
This method uses the Adafruit WebSerial ESPTool through Chrome or a Chromium-based browser (including Opera and Edge). Adafruit WebSerial ESPTool is a web-based option for programming ESP32-S2/S3 boards. It allows you to erase the the microcontroller flash and program up to four files at different offsets.
You have to use a Chromium-based browser (Chrome, Opera, Edge, etc.) for this to work. Safari and Firefox are not supported because they don't have adequate support for Web Serial functionality.
Follow the steps below to flash the UF2 bootloader.
Connect
You should have plugged in only the ESP32-S2/S3 that you intend to flash. That way there's no confusion in picking the proper port when it's time!
In the Chrome browser visit https://adafruit.github.io/Adafruit_WebSerial_ESPTool/. You should see something like the image shown.
Leave the No reset for Passthrough updates toggle off.
Press the Connect button in the top right of the web browser. You will get a pop up asking you to select the COM or Serial port.
Remember, you should remove all other USB devices so only the ESP32-S2/S3 board is attached, that way there's no confusion over multiple ports!
On some systems, such as MacOS, there may be additional system ports that appear in the list.
The JavaScript code will now try to connect to the ROM bootloader. It may timeout for a bit until it succeeds. On success, you will see that it is Connected and will print out a unique MAC address identifying the board along with other information that was detected.
To erase the contents, click the Erase button. You will be prompted whether you want to continue. Click OK to continue or if you changed your mind, just click cancel.
You'll see "Erasing flash memory. Please wait..." This will eventually be followed by "Finished." and the amount of time it took to erase.
Do not disconnect! Immediately continue on to programming the ESP32-S2/S3.
Programming the ESP32-S2/S3 can be done with up to four files at different locations, but with the board-specific bootloader .bin file, which you should have downloaded under Step 1 on this page, you only need to use one file.
Click on the first Choose a file.... (The tool will only attempt to program buttons with a file and a unique location.) Then, select the bootloader .bin file you downloaded in Step 1 that matches your board.
Verify that the Offset box next to the file location you used is (0x) 0.
Once you choose a file, the button text will change to match your filename. You can then select the Program button to begin flashing.
Once completed, you can skip down to the section titled Reset the Board.
If you used Adafruit WebSerial ESPTool, you do not need to complete the steps in this section!
Once you have entered ROM bootloader mode, you can then use Espressif's esptool program to communicate with the chip! esptool is the 'official' programming tool and is the most common/complete way to program an ESP chip.
Install esptool.py
You will need to use the command line or Terminal to install and run esptool.
You will also need to have pip and Python installed (any version!).
Install the latest version using pip (you may be able to run pip without the 3 depending on your setup):
pip3 install --upgrade esptool
Then, you can run:
esptool.py
Test the Installation
Run esptool.py in a new terminal/command line and verify you get something like the below:
Find the Serial Port
First, you need to determine the name of the serial port you board has when it's plugged in and ROM bootloader mode.
- For Windows, it will be a COM port, such as
COM5. Look in Device Manager -> Ports. - For macOS, you can do
ls /dev/tty.*in a Terminal to find the names of the serial ports. - For Linux, you can do ls
/dev/tty*in a terminal window. The name is often /dev/ttyACM0 or similar.
If you are not sure you've found the right port, unplug the board, and see if the port disappears.
For more information on determining serial ports, follow these links for help on Windows, macOS, or Linux.
Connect
Run the following command, replacing the identifier after --port with the COMxx, /dev/cu.usbmodemxx or /dev/ttySxx you found above.
For example, if you're using Windows, and you think the board is on COM88, type this following:
esptool.py --port COM88 chip_id
You should get a notice that it connected over that port and found an ESP32-S2/S3.
Erase the Flash
Before programming the board, it is a good idea to erase the flash. Run the following command.
esptool.py erase_flash
You must be connected (by running the command in the previous section) for this command to work as shown.
Flash the UF2 Bootloader
Run this command and replace the serial port name with your matching port and the file you just downloaded
esptool.py --port COM88 write_flash 0x0 tinyuf2-some-board-0.32.0-combined.bin
Don't forget to change the --port name to match.
Adjust the bootloader filename accordingly if it differs from tinyuf2-some-board-0.32.0-combined.bin.
There might be a bit of a 'wait' when programming, where it doesn't seem like it's working. Give it a minute, it has to erase the old flash code which can cause it to seem like it's not running.
You'll finally get an output like this:
Once completed, you can continue to the next section.
The board should restart automatically, and start up the UF2 bootloader. If not, press the reset button to start the bootloader.
The NeoPixel LED on the QT Py ESP32-S3 will light up in a rainbow swirl.
You've successfully returned installed the UF2 bootloader on your board. If you now want to return the board to a factory reset state, follow the instructions at the top of the page to Install the Factory Reset Firmware UF2.
We suggest updating to Chrome 89 or newer, as Web Serial is enabled by default.
If you must continue using an older version of Chrome, follow these steps to enable Web Serial.
If you receive an error like the one shown when you visit the Adafruit WebSerial ESPTool site, you're likely running an older version of Chrome.
You must be using Chrome 78 or later to use Web Serial.
To enable Web Serial in Chrome versions 78 through 88:
- Visit chrome://flags from within Chrome.
- Find and enable the Experimental Web Platform features
- Restart Chrome
Step 3: Alternative C. The Flash an Arduino Sketch Method
This section outlines flashing an Arduino sketch onto your ESP32-S2/S3 board, which automatically installs the UF2 bootloader as well. However, it does not allow you to choose which UF2 bootloader to install, so Alternative A or B above are preferred.
Arduino IDE Setup
If you don't already have the Arduino IDE installed, the first thing you will need to do is to download the latest release of the Arduino IDE. ESP32-S2/S3 requires version 1.8 or higher. Click the link to download the latest.
After you have downloaded and installed the latest version of Arduino IDE, you will need to start the IDE and navigate to the Preferences menu. You can access it from the File > Preferences menu in Windows or Linux, or the Arduino > Preferences menu on OS X.
The Preferences window will open.
In the Additional Boards Manager URLs field, you'll want to add a new URL. The list of URLs is comma separated, and you will only have to add each URL once. The URLs point to index files that the Board Manager uses to build the list of available & installed boards.
Copy the following URL.
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
Add the URL to the the Additional Boards Manager URLs field (highlighted in red below).
Click OK to save and close Preferences.
In the Tools > Boards menu you should see the ESP32 Arduino menu. In the expanded menu, it should contain the ESP32 boards along with all the latest ESP32-S2 boards.
Now that your IDE is setup, you can continue on to loading the sketch.
Open the Blink sketch by clicking through File > Examples > 01.Basics > Blink.
For the Arduino IDE to upload TinyUF2 you must select a TinyUF2 partition layout, under the Tools > Partition Scheme menu.
If you have a 4MB board, won't be doing Over-The-Air firmware updates (OTA), or are unsure, then choose the 'No OTA' TinyUF2 entry.
Finally, click Upload from the sketch window.
Once successfully uploaded, the little red LED will begin blinking once every second. At that point, you can now enter the bootloader.
If you change LED_BUILTIN to 13, the sketch will compile and upload. Be aware that, once the sketch is loaded, nothing will happen on the board. However, you will have a bootloader. The updated code would look like this:
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}
Alternatively, you could load a different sketch. It doesn't matter which sketch you use.
Page last edited June 30, 2025
Text editor powered by tinymce.