USB functions
Use Interfaces → USB in esp32-config to choose host mode, a serial
connection, or a USB network connection. The standard
full board image includes the controller
and ACM/ECM gadget support; the menu offers only the functions available in the image.
Run the board commands below as root.
These settings control DWC2. The fixed USB Serial/JTAG port is a separate peripheral. Use the board schematic to identify the DWC2 connection, and keep a separate console available when changing its role.
Choose a USB function
Selection |
Use |
|---|---|
Host |
Connect a USB peripheral, including storage |
USB serial connection |
CDC ACM application port or Linux login console |
USB network connection (ECM) |
Direct IPv4 connection to a computer with an ECM driver |
Before changing from host mode to a device function, unmount all USB-backed filesystems and stop USB-backed swap. Use Memory and storage for devices managed by the tool. The role change is refused while those devices are in use. Disconnect host peripherals before attaching the device-mode cable.
The selected mode is saved and restored at startup. Applying a different USB function disconnects the current USB connection.
USB serial
Choose USB serial connection, then select Application serial port or Linux login console. For a login console from the command line:
esp32-config usb configure serial 1
esp32-config usb status
Connect the DWC2 port to the computer and open the newly enumerated serial
port. For the login console, log in with the board’s account credentials.
For an application port, use serial 0 instead; your application opens the
board-side /dev/ttyGSN path shown by usb status.
The number is discovered from the ACM function. It may differ from ttyGS0
when the fixed USB Serial/JTAG driver already uses that name.
USB network
Choose USB network connection (ECM) and set the board’s address, or run:
esp32-config usb configure network 0 192.168.7.2/24
esp32-config usb status
Configure the computer’s USB network interface with a different address on
the same subnet, such as 192.168.7.1/24. The board does not start a DHCP
server. For example, on a Linux computer, replace USB_IFACE with the actual
new interface name:
sudo ip address add 192.168.7.1/24 dev USB_IFACE
sudo ip link set USB_IFACE up
ping 192.168.7.2
Choose another subnet if that one is already used by a different connection. The USB address is independent of the Wi-Fi address. Applications can use ordinary network sockets over this link.
Return to host mode
Close programs using the USB connection, then run from the separate console:
esp32-config usb configure host
Disconnect the device-mode cable before reconnecting host peripherals.
Configure a custom ACM function
For a custom gadget with your own USB identifiers, use the configfs recipe below. It is source-derived; USB gadget mode remains outside the standard HIL suite. Complete the common pin and overlay checks, and release any gadget created by the configuration tool first:
esp32-config usb stop
This keeps the saved USB selection, which will return at the next boot.
First inspect storage use:
cat /proc/mounts
cat /proc/swaps
Unmount every filesystem on USB storage and run swapoff for every
USB-backed swap entry, using the actual listed path. Disconnect the USB drive
before connecting the device-mode cable. Then apply the role overlay:
s31-overlay apply usb-device --volatile
[ -d /sys/kernel/config/usb_gadget ] || mount -t configfs none /sys/kernel/config
ls /sys/class/udc
Use your project’s USB vendor/product IDs. Enter each hexadecimal value with
a 0x prefix so configfs interprets it as hexadecimal.
Run this in one shell, stopping if a command fails or
if s31-acm already exists:
printf 'USB vendor ID (hex): '
read -r S31_USB_VID
printf 'USB product ID (hex): '
read -r S31_USB_PID
S31_GADGET=/sys/kernel/config/usb_gadget/s31-acm
mkdir "$S31_GADGET"
echo "$S31_USB_VID" > "$S31_GADGET/idVendor"
echo "$S31_USB_PID" > "$S31_GADGET/idProduct"
mkdir "$S31_GADGET/strings/0x409"
echo 's31-example-001' > "$S31_GADGET/strings/0x409/serialnumber"
echo 'S31 development' > "$S31_GADGET/strings/0x409/manufacturer"
echo 'S31 CDC ACM example' > "$S31_GADGET/strings/0x409/product"
mkdir "$S31_GADGET/configs/c.1"
mkdir "$S31_GADGET/configs/c.1/strings/0x409"
echo 'CDC ACM' > "$S31_GADGET/configs/c.1/strings/0x409/configuration"
mkdir "$S31_GADGET/functions/acm.usb0"
ln -s "$S31_GADGET/functions/acm.usb0" "$S31_GADGET/configs/c.1/acm.usb0"
S31_UDC=$(ls /sys/class/udc | head -n 1)
: "${S31_UDC:?No UDC found}"
echo "$S31_UDC" > "$S31_GADGET/UDC"
S31_ACM_PORT=$(cat "$S31_GADGET/functions/acm.usb0/port_num")
printf 'Device serial node: /dev/ttyGS%s\n' "$S31_ACM_PORT"
The host should enumerate a CDC ACM serial interface; inspect its newly created serial device. Open it on the host, then send a line from the S31:
printf 'hello from S31\n' > "/dev/ttyGS$S31_ACM_PORT"
The S31 write can wait until the host opens the interface. Do not assume
the gadget is /dev/ttyGS0: the fixed USB Serial/JTAG driver may already own
that name, and the gadget allocator skips occupied names. The configfs
port_num attribute gives the actual number. Close both ends before cleanup:
echo '' > "$S31_GADGET/UDC"
rm "$S31_GADGET/configs/c.1/acm.usb0"
rmdir "$S31_GADGET/functions/acm.usb0"
rmdir "$S31_GADGET/configs/c.1/strings/0x409"
rmdir "$S31_GADGET/configs/c.1"
rmdir "$S31_GADGET/strings/0x409"
rmdir "$S31_GADGET"
s31-overlay remove usb-device --volatile
The cleanup releases the function and restores the base host role. Disconnect the device-mode cable before reconnecting host peripherals. Sources: kernel configfs lifecycle, S31-aware serial allocation, ACM port number.