What Is the Default Upload Baud Rate in esp_flasher and How It Handles Rate Fallback

The esp_flasher CLI defaults to 1,500,000 bps (1.5 Mbaud) for firmware uploads and automatically falls back to 115,200 bps when the target ESP32 chip cannot communicate at the higher speed.

The jason2866/esp_flasher tool optimizes flashing speed by attempting uploads at the default upload baud rate while maintaining reliability through intelligent rate fallback logic. When you flash firmware to ESP32 devices, the tool validates the high-speed connection before proceeding, seamlessly reverting to the ROM-safe default of 115,200 bps if the chip does not support the requested rate.

Default Upload Baud Rate Configuration

In esp_flasher/__main__.py, the argument parser sets the default upload baud rate to 1,500,000 bps (lines 44-48):

parser.add_argument(
    '--upload-baud-rate',
    default=1500000,
    type=int,
    help='Baud rate for flashing firmware (default: 1500000)')

This default applies to the --upload-baud-rate CLI flag, meaning standard invocations attempt high-speed uploads at 1.5 Mbaud.

How esp_flasher Handles Rate Fallback

When initiating a flash operation, esp_flasher implements a validation and fallback process across four distinct stages to ensure reliable communication.

Attempting High-Speed Switch

If the requested rate differs from the UART-ROM default of 115,200 bps and the target belongs to the ESP32 family, the tool calls stub_chip.change_baud() to switch speeds (lines 153-156):

if (args.upload_baud_rate != 115200) and ("ESP32" in info.family):
    stub_chip.change_baud(args.upload_baud_rate)

This reconfigures the UART peripheral for faster data transfer before the firmware write begins.

Validating Communication

Immediately after the baud rate change, esp_flasher tests the connection by calling detect_flash_size(stub_chip). This validation step confirms that the chip can reliably communicate at the new speed. If detection succeeds, the flashing session continues at the higher baud rate for improved throughput.

Fallback to Safe Default

When detect_flash_size() raises an Esp_flasherError, indicating the chip cannot operate at the requested speed, esp_flasher executes a fallback sequence (lines 61-73):

  1. Log the incompatibility: Chip does not support baud rate <requested>, changing to 115200
  2. Close the current serial port (stub_chip._port.close())
  3. Recreate the chip instance using detect_chip() at 115,200 bps
  4. Restart the stub loader at the ROM-safe default speed

This ensures that incompatible hardware still receives the firmware successfully, albeit at a slower transfer rate.

Restoring Post-Flash Baud Rate

After flashing completes, esp_flasher forces the serial port back to 115,200 bps to maintain readable log output (lines 34-40):

stub_chip._port.baudrate = 115200
time.sleep(0.05)
stub_chip._port.flushInput()

This prevents garbled console output that would occur if the device continued transmitting at the elevated upload speed.

Practical Usage Examples

Run with the default 1.5 Mbaud:

esp_flasher -p /dev/ttyUSB0 firmware.bin

Specify a slower rate to avoid fallback attempts:

esp_flasher -p /dev/ttyUSB0 --upload-baud-rate 921600 firmware.bin

Force the ROM-safe default explicitly:

esp_flasher -p /dev/ttyUSB0 --upload-baud-rate 115200 firmware.bin

Implementation Details

The complete fallback mechanism operates as follows, according to the source code in esp_flasher/__main__.py:

if (args.upload_baud_rate != 115200) and ("ESP32" in info.family):
    stub_chip.change_baud(args.upload_baud_rate)   # try high speed

    try:
        flash_size = detect_flash_size(stub_chip)  # test communication

    except Esp_flasherError:
        # Rate fallback sequence

        print(f"Chip does not support baud rate {args.upload_baud_rate}, changing to 115200")
        stub_chip._port.close()
        chip = detect_chip(args.port, 115200)      # reconnect at safe default

        stub_chip = chip.run_stub()

The ROM default of 115,200 bps is defined as ESP_ROM_BAUD in esp_flasher/own_esptool.py, representing the baud rate used by the ESP32 ROM bootloader before any stub code execution.

Summary

  • Default Rate: esp_flasher uses 1,500,000 bps as the default upload baud rate, configured in esp_flasher/__main__.py.
  • Speed Validation: The tool tests high-speed communication using detect_flash_size() before committing to the full flash operation.
  • Automatic Fallback: If validation fails, esp_flasher recreates the chip connection at 115,200 bps, the ROM-safe default.
  • Connection Restoration: After flashing, the serial port resets to 115,200 bps to ensure readable device logs.
  • Helper Functions: Chip detection and flash size validation utilize esp_flasher/helpers.py.

Frequently Asked Questions

What happens if my ESP32 doesn't support 1.5 Mbaud?

If the chip cannot communicate at the default upload baud rate, esp_flasher catches the Esp_flasherError exception, closes the serial port, and reconnects at 115,200 bps. The tool logs this change and proceeds with flashing at the slower, universally compatible speed.

Can I disable the automatic baud rate fallback?

No, the fallback mechanism is integral to the flash initialization sequence in esp_flasher/__main__.py. However, you can prevent the initial high-speed attempt by explicitly setting --upload-baud-rate 115200, which skips the change_baud() call entirely.

Why does esp_flasher reset to 115200 after flashing?

The serial port baud rate resets to 115,200 bps after flashing (lines 34-40 of esp_flasher/__main__.py) because the ESP32's bootloader and application firmware typically transmit debug output at this standard rate. Maintaining the higher upload speed would render subsequent serial monitor output unreadable.

Where is the ROM default baud rate defined?

The safe default of 115,200 bps is defined as ESP_ROM_BAUD in esp_flasher/own_esptool.py. This constant represents the baud rate used by the ESP32 ROM bootloader before any stub code or user configuration takes effect.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →