Has this ever happened to you? You're working on an Arduino sketch, happily uploading it to your board, then suddenly Arduino says it can't upload since the COM / Serial port "doesn't exist". This unfortunately seems to happen quite often. It typically occurs with boards that use "native USB" to provide the serial port. What is native USB? And why do these boards tend to lose their serial ports?

This guide discusses what a "native USB" board is and how they provide their COM port connection. For contrast, boards that lack native USB and instead rely on a dedicated USB-to-serial converter are also discussed. This should help to better understand the general nature of these two board designs and why native USB boards behave the way they do. Additionally, ways of dealing with and recovering from native USB boards that have lost their COM ports, or just generally are acting weird, are covered.

On windows, serial ports are called COM ports. They're the same thing!

Terms

Before going into more detail, let's briefly describe the two main classes of Arduino boards and the terminology used to refer to them.

  • USB-to-Serial Converter Boards - These boards have a dedicated piece of hardware, a USB-Serial bridge chip, separate from the main processor, that "bridges" the connection between the host PC's USB and the processor's serial interface.
  • Native USB Boards - These boards use processors that have a USB peripheral interface "native" to the processor itself, so the processor and host PC's USBs can be connected directly.

Now let's look at these two in more detail.

First let's look at the USB-to-serial converter setup. This configuration is historically older, but is still generally relevant. While more and more processors are being provided with a USB interface peripheral (native USB), it's still not as universal as I2C, SPI, and good old fashioned serial UART. So plenty of modern Arduino boards are still using this configuration.

The main processor is where the Arduino sketch is loaded and runs. It only has a serial interface for uploading new sketch code. This serial interface can not directly connect to a host's USB port. Therefore, a separate specialized chip, called a USB-to-serial converter (or adapter), is used to "bridge" the host PC's USB to the processor's serial interface.

USB-to-Serial adapter chips are also called CP2102, CP2104, FT232, CH340, CH9102F, or other part numbers. They all perform the same task.

Also note the reset behavior. Pressing the reset button on the Arduino board resets the main processor. However, the USB-to-serial converter is not reset and remains powered. Therefore, from the point of view of the host PC, it never sees a USB disconnect when the processor resets. It just sees the USB-to-serial converter sitting there happily providing a COM port.

Example Boards

Here are some example boards that have processors that lack any USB connectivity and therefore use a USB-to-serial adapter. Both of the main processor and the USB-to-serial adapter are shown.

On the UNO R3, the USB-to-serial adapter is actually another microprocessor!

On the Feather ESP32 V2, the USB-to-serial adapter is a dedicated special purpose chip.

Other common boards that have a USB-Serial chip are:

  • Any ESP8266 board
  • Any ESP32 board (not ESP32-Sx or ESP32-Cx)
  • Any ATmega328 board
  • Any ATmega2560 board

Drawbacks

Since the USB-to-serial adapter provides a constant and reliable COM port connection to the host PC, these style Arduino boards are generally less prone to COM port weirdness when trying to upload an Arduino sketch. So why not use this approach for all boards?

The main drawback is that the USB-to-serial converter does one thing and one thing only - it acts as a COM port. From the point of view of the host PC, it'll never be anything but a COM port. That's all it can do.

That's great when it comes to uploading sketches, since that's done via the COM port. But what if you wanted to emulate a USB keyboard, mouse, mass storage (MSD), or some other USB device? You can't. At least not via this "USB connection".

This is why boards that use USB-to-serial converters will NOT show a CIRCUITPY folder. They can also never be used as HID keyboard/mouse devices

Another drawback is the potential need to install drivers. There are numerous companies that make dedicated USB-to-serial adapter chips. For these to work properly, and show up as a COM port, company provided and device specific drivers may need to be installed. That typically requires going to the company's website and hunting down and installing these drivers for a given operating system.

There's also an associated cost and board size increase required for the extra circuitry

OK, now let's look at "native USB" boards. They are not drastically different than the USB-to-serial converter boards discussed previously. The key feature is that the main processor has a dedicated USB peripheral and therefore can be connected directly to the host PC's USB port. Since the USB peripheral is a part of the main processor itself, it is referred to as "native", i.e. it's "native" to the processor.

As before, the main processor is where the Arduino sketch is loaded and runs. This is also still done via a COM port. However that COM port is now provided by the main processor itself. The USB peripheral on the processor is usually* general purpose - it's not "just" a COM port. So to show up as a COM port on the host PC, as needed for uploading an Arduino sketch, properly running firmware is needed on the main processor.

But the most important thing to notice is...

The same processor that runs the Arduino sketch must manage the USB connection.

The reset behavior is very different relative to a board with a USB-to-serial converter.

When the reset button on the Arduino board is pressed, this resets the main processor. Since that also resets the firmware that was presenting the native USB as a COM port, from the point of view of the host PC it looks like a USB disconnect followed by a reconnect. This is like unplugging the USB cable, waiting a second, then plugging it back in.

This happens with every new sketch upload, since the board is reset after the sketch is uploaded so the new sketch code will run.

*The ESP32-C3 is a weird exception: it has a native USB peripheral that is a COM port only. It's like a built in USB-to-serial converter, so it cannot act as an HID Keyboard/Mouse but it also does lose the serial port device when reset!

Example Boards

Here are some example boards that have processors with native USB. The host PC's USB connection goes directly to the main processor.

On the Feather ESP32-S3, the USB data lines go directly into the ESP32-S3 processor itself.

On the Feather M4, the USB data lines go directly into the M4 processor itself.

Drawbacks

The main drawback relates to the reset behavior. Since pressing reset and/or uploading a new sketch resets the processor, it also resets the native USB peripheral and the host PC sees that as a disconnect. Different operating systems handle this in different ways. On Windows, for example, this can end up leading to alternating between two COM ports with each sketch upload.

Each new sketch upload is seen as a USB disconnect / reconnect event on the host PC.

Another drawback is the dependence on properly running firmware on the main processor for the COM port to be functional and show up on the host PC. Unfortunately, it is possible for a user sketch to interfere with this, which then prevents any new sketch uploads.

It's possible for a user sketch to "crash" the board and prevent a COM port from showing up. In fact this happens ALL THE TIME!

Alright, dude, so where is my COM port?

Below is a run through of various scenarios and what can be done to get basic sketch uploading functionality working again and recover that missing COM port.

Is The Correct Board Selected?

This really isn't a COM port issue but is important to mention here. It is a very common source of issues and can also appear to be a failed upload. It doesn't help when there are a ton of similarly sounding board names - the Feather ESP32, Feather ESP32 V2, Feather ESP32-S2, and Feather ESP32-S3 are all different boards. Double check the correct board is selected in the Arduino IDE.

Did COM Port Change Location?

This seems to mainly happen on Windows. However, it's easy to check for any setup. Before uploading a sketch, double check the COM port setting in the Arduino IDE. Maybe it's there, but just given a new location that must be re-chosen in the Arduino IDE before uploading the sketch.

Serial Monitor or Plotter Left Open?

Leaving the Arduino Serial Monitor or Plotter open between sketch uploads may interfere. The host PC may retain whatever COM port it was using, waiting for more serial output. Then, when the board resets, the host PC may give it a new different COM port assignment. But the Arduino IDE is still set to the other one. So try closing the Serial Monitor and/or Plotter. If they are closed and the sketch upload is still failing, double check the Port setting in the Arduino IDE.

COM Port Not Showing Up Anywhere?

This process applies to boards with the following processors:

  • ATmega32u4
  • ATSAMD M0 and M4

If a COM port used to show up, but now can't be found anywhere, then recovery with some manual intervention is suggested. This situation generally happens as a result of a malformed sketch that "crashes" the board. So the general idea is to upload a known good sketch (Blink) and sort of "kick" the board during the upload process (press reset).

Why any given sketch causes this to happen is beyond the scope of this guide. Here, we only provide a way to recover basic functionality. This is important to help verify that the board hardware itself is OK.

  1. Turn on verbose upload in the Arduino IDE preferences.
  2. Plug in the Arduino board. It won't show up as a COM port. That is OK at this point.
  3. Open up the Blink example: File->Examples->Basics->Blink
  4. Double check the correct board in the Tools menu. Physically check your board to make sure you have the right one selected!
  5. Compile the sketch via the Verify (check mark) button just to make sure it works. This does not upload the sketch. That's next.
  6. Now click the Upload (arrow) button to attempt to upload the sketch.
  7. The IDE will print out a bunch of COM ports as it tries to upload. During this time, double-click the reset button.
  8. The board should show up as a COM port.
  9. The IDE should see that COM port and upload properly.
Arduino
The COM port that shows up at step 8 is actually the bootloader COM port.

Boards with ROM Bootloaders and Native USB COM Ports

This process applies to boards with the following processors:

  • ESP32-S2
  • ESP32-S3
  • ESP32-C3

This is similar to the above process, but is specific to boards that also have a ROM bootloader along with native USB used to provide the COM port. For these boards, manually entering ROM bootloader first can be used as a way to recover.

To enter ROM bootloader mode:

  • Hold down the BOOT button
  • Press and release the RESET button
  • Release the BOOT button

A COM port should now show up and the Arduino IDE should be able to upload the Blink sketch.

RP2040 ROM Bootloader Specific

The Raspberry Pi RP2040 has native USB and a ROM bootloader. However, the ROM bootloader does not provide any serial connection and therefore no COM port. Instead, it only provides a USB Mass Storage Device (MSD) interface, which shows up as a folder named RPI-RP2. If an RP2040 board is refusing to accept an Arduino sketch upload for some reason, it should be possible to:

  • Manually enter bootloader mode so the RPI-RP2 folder shows up in the host PC's file explorer (not in Arduino). See board specific info for how to enter bootloader mode.
  • In Arduino, leave the Port selection blank.
  • Double check the correct Board is selected.
  • Upload the Blink example sketch.

Once the sketch upload is complete, the board should reset, the RPI-RP2 folder will not show up, the onboard LED should blink, and a now a serial port should be showing up in the Arduino IDE's Port selection.

This guide was first published on Feb 07, 2023. It was last updated on Mar 08, 2024.