Boards and ports

Find attached boards, name them, bind a project to one, and pick the port and baud rate.

With one board attached you never name a port. This page is for everything else: finding boards, telling several apart, and pinning a project to the right one.

List attached boards

espx devices

devices lists the serial ports with a dev board on them. Each row has the port, the USB serial interface and the board's name if you gave it one:

InterfaceUSB vendor id
native USB (the chip's own USB serial/JTAG)303A
CP210x bridge10C4
CH34x bridge1A86
FTDI bridge0403
PL2303 bridge067B

Ports with any other vendor id are left out. --all lists every serial port, including the Bluetooth and debug-console ports macOS has built in. On macOS espx lists only the /dev/cu.* device of each port, never its /dev/tty.* twin.

--json prints the ports as one document, with the USB vendor and product ids, serial number, manufacturer and product of each. See JSON events.

Identify the chip

espx devices --probe

--probe runs espflash board-info on every port and adds the chip to each row, or unknown with the error. This connects to and resets every board listed. Plain espx devices only lists ports and touches nothing.

For one board, espx info prints its chip, revision, crystal, flash size, features and MAC address. It resets the board too.

Watch boards come and go

espx devices --watch
espx devices --watch --json

--watch keeps running and prints attached and detached as boards are plugged in and unplugged, until Ctrl+C. With --json each change is one event per line. It cannot be combined with --probe or --all.

Board ids

espx keys every physical board on its id: the USB serial number when the port reports one, else the port path. On native-USB chips the serial number is the chip's MAC address, so it stays the same across ports and replugs. Names, [board] id bindings, agent policies and leases all use this id, and ids compare without regard to case.

espx devices --json shows the serial number as usb.serial_number. A port without one has its path as its id.

Name a board

espx boards name /dev/cu.usbmodem2101 bench-c6
espx devices

boards name takes the board's id, its current port or its current name, and writes the name to ~/.espx/boards.toml:

~/.espx/boards.toml
[names]
"58:8C:81:53:AD:2C" = "bench-c6"

Names are unique, at most 64 characters of ASCII letters, digits, -, _ and ., starting with a letter or digit. espx devices then shows bench-c6 next to the port, and every --port flag accepts it. espx rewrites the file when it saves a name, so comments you add by hand do not survive.

How espx picks a board

flash, run and monitor pick their board in this order:

  1. The --port flag: a port path, a board id or a name.
  2. [board] id in the project's espx.toml.
  3. [connection] serial in the project's espflash_ports.toml.
  4. The single connected board.

A value matches an attached board by id, by port or by name. A bound board that is not connected is an error (board_not_attached), never a quiet switch to another board. With no board at all, or several and nothing chosen, espx stops with port_required and lists the candidates by name.

The order also decides which board [board] id affects. It is the board flash and run write to and monitor reads, not only the board an agent may touch.

erase and info take a plain serial port in --port and leave the choice to espflash, unless another espx process holds the boards; then they resolve the board the same way and borrow it.

Bind a project to a board

espx.toml sits next to the project's Cargo.toml. Its [board] table names the board the project flashes by default and the speed to flash it at:

espx.toml
[board]
id = "58:8C:81:53:AD:2C"   # a board id, a name or a port
baud = 460800              # flashing speed when --baud is not given

espx new <name> --board-id <id> writes the [board] section for you. The same file holds the [agent] policy, described in Agent policy. An unknown key is an error that names the file, the line and the key.

Pin a port

espflash_ports.toml is espflash's own file. espx reads it as step 3 above and passes the chosen port to espflash:

espflash_ports.toml
[connection]
serial = "/dev/cu.usbmodem101"

espx new <name> --port <port> writes it. A port path changes when you plug the board into another USB socket, so prefer [board] id when the board has a serial number.

Baud rates

There are two speeds. The flashing speed is how fast espflash talks to the bootloader. The monitor speed is the firmware's UART rate.

SpeedSet by, strongest first
Flashing (flash, run)--baud on flash, then [board] baud in espx.toml, then espflash's own ESPFLASH_BAUD, baudrate in espflash.toml, or its default
Monitor (monitor, run, flash --monitor)--baud on monitor, then MONITOR_BAUD, then 115200

When the bootloader does not answer, espx retries the flash once at 115200 by itself. espflash.toml can also hold a [flash] table with the flash mode, size and frequency; espx reads its size for the partition check.

Environment variables

VariableRead byEffect
MONITOR_BAUDespx and espflashThe monitor speed when --baud is not given
ESPFLASH_BAUDespflashThe flashing speed when neither --baud nor [board] baud is set
ESPFLASH_PORTespflashThe port when espx leaves the choice to espflash: erase and info without --port, and flash -i

espx's own board selection does not read ESPFLASH_PORT. When espx picks a board it passes the port to espflash explicitly, which overrides the variable.

Driver warnings

On macOS a WCH CH34x or CH9102 bridge without WCH's own driver runs on Apple's built-in serial driver. The port shows up as /dev/cu.usbmodem… instead of /dev/cu.wchusbserial…. That driver corrupts large writes: the monitor reads fine, but every flash fails. espx spots the pairing from the port alone and warns on stderr:

warn: /dev/cu.usbmodem1101: this CH34x bridge runs on macOS's built-in serial driver (…), which corrupts large writes, so flashing will most likely fail. …

espx devices, espx doctor, the MCP devices tool and the desktop app all show it, and --json carries it as the port's warning. Install WCH's CH34x driver and turn it on in System Settings > General > Login Items & Extensions > Driver Extensions, or plug the cable into the board's native USB port (labelled USB on ESP32-S3 DevKits).

Board models

espx also knows a few dev board models and their pins:

espx boards                  # id, chip and name of each known board
espx board xiao-esp32c6      # LED, BOOT button, UART pins, USB ids, documentation

devices names a model only when a board's USB ids identify exactly one. Native USB (303A:1001) and the generic bridges never do, because every board with them reports the same ids. The Chips and boards reference has the table.