FDomain can run over a physical serial port (UART), allowing developers to interact with and debug Fuchsia devices that have no active network or USB connectivity.
The UART transport runs the FDomain protocol over an asynchronous serial line (such as /dev/ttyUSB0 on Linux, or a host UNIX domain socket for a QEMU emulator) connected to a Fuchsia target device's serial port (exposed under /dev/class/serial/).
Communication operates at a high line rate (defaulting to 1,000,000 baud) using the ResendSP sliding-window framing protocol, which provides reliable bidirectional delivery with checksums, acknowledgments, and session tracking across device reboots.
On Linux hosts, accessing TTY character devices (e.g., /dev/ttyUSB0) requires membership in the dialout group:
sudo usermod -a -G dialout $USER
You must log out and back in (or run newgrp dialout) for the group membership to take effect.
ffx {:#enable-uart-discovery}By default, ffx target discovery monitors mDNS and USB discovery streams. To enable the UartWatcher subsystem to monitor active UART connections and list them in ffx target list, set connectivity.enable_uart to true:
ffx config set connectivity.enable_uart true
On physical hardware platforms (such as boards using DesignWare 8250/APB UART controllers), high-speed serial rates (1,000,000 baud) are calibrated using Divisor Latch Fraction (DLF) registers to minimize bit timing error.
Because single-port targets share the physical serial line between the kernel console and userspace services, enabling ffx over UART requires handing off serial port ownership to the userspace FDomain UART driver (fdomain-uart-driver) via kernel command-line arguments (for example, in local/BUILD.gn developer overrides):
dev.fdomain.uart=true: Enables the target-side fdomain-uart-driver component to discover and bind to the serial port in /dev/class/serial/.dev.fdomain.uart.baud=1000000: Configures the target serial port baud rate.kernel.serial=none: Disables the Zircon kernel serial console so kernel debug prints do not collide with binary ResendSP frames.console.shell=false: Disables the userspace interactive serial console shell (console.cm).Note: Disabling kernel.serial suppresses raw early-boot serial output and synchronous kernel panic dumps over the physical UART pins. Once userspace boots and ffx connects, kernel debug logs (klog / dlog) and component logs remain available through ffx log.
Unlike network or USB interfaces which support automatic background enumeration, serial ports are shared physical resources with no standard bus discovery mechanism. The ffx uart tool provides explicit subcommands to manage the connection lifecycle and ensure mutual exclusion across host tools.
To establish a UART connection to a physical device:
ffx -t /dev/ttyUSB0 uart connect
(You may also include the uart: prefix, e.g., ffx -t uart:/dev/ttyUSB0 uart connect, or specify a running QEMU emulator instance name such as ffx -t fuchsia-emulator uart connect; see Using Fuchsia Emulators).
ffx uart connect defaults to 1,000,000 baud. You can specify a custom baud rate if your board configuration requires it:
ffx -t /dev/ttyUSB0 uart connect --baud 115200
When connecting:
flock) on the serial device to prevent concurrent access from other processes.ffx-uart-driver background daemon to multiplex FDomain traffic.ffx shared data directory (ffx_uart/).Once connected, you can run any standard ffx command targeting the UART device using the uart: address prefix:
ffx -t uart:/dev/ttyUSB0 target echo
ffx -t uart:/dev/ttyUSB0 log
To verify whether a physical serial port is responsive and communicating with the target's FDomain UART service:
ffx -t /dev/ttyUSB0 uart probe
The probe command performs the following checks:
To view all active UART driver instances and their associated devices:
ffx uart list
Example output:
TARGET PID BAUD PROTOCOL STATUS /dev/ttyUSB0 12345 1000000 ResendSP Connected
When connectivity.enable_uart is enabled and the UART background driver is active, ffx automatically discovers the target:
ffx target list
Example output:
NAME SERIAL TYPE STATE ADDRS/IP MANUAL RCS fuchsia-54b7-e1d8-7af6 1234567890ab minimal.x64 Product [uart:/dev/ttyUSB0] N Y
ffx discovers UART targets passively by monitoring connection metadata written by ffx-uart-driver. The target's nodename and serial number are obtained by the driver upon connection and stored in metadata, allowing discovery to detect and enumerate connected devices immediately without contending for the physical serial port. If the same device is also connected over USB or network, ffx merges the addresses under a single target entry by matching the hardware serial number.
To inspect real-time transmission statistics for an active connection:
ffx -t /dev/ttyUSB0 uart status
This queries the driver daemon's local control socket and metadata to report operational details including:
ResendSP).Estimated RTT), retransmission count, CRC checksum errors, connection drops, and handshake failures.Last Target Error).To diagnose host-side UART connection problems across all connections or for a specific target:
ffx uart doctor
ffx -t /dev/ttyUSB0 uart doctor
ffx uart doctor executes a sequence of diagnostic checks:
<shared_data>/ffx_uart/ for empty or corrupted JSON metadata files, orphaned .sock / .sock.control UNIX domain sockets, and metadata referencing dead daemon PIDs.ffx-uart-driver process is running (not a zombie) and responsive on its control socket.flock) to detect contention from another process or a leaked ffx-uart-driver instance.To automatically repair detected issues where possible, pass --fix:
ffx uart doctor --fix
When --fix is enabled, the doctor tool removes stale or corrupted metadata and socket files (while sparing targets that have an active connection), terminates unresponsive or leaked ffx-uart-driver daemons, and restarts stalled connections using cached target parameters.
To terminate the background driver and release the serial device lock:
ffx -t /dev/ttyUSB0 uart disconnect
Releasing the connection frees the serial device for other uses, such as interactive debug consoles or firmware flashing.
To restart the background driver using saved metadata (for instance, after a cable disconnect or transient host issue):
ffx -t /dev/ttyUSB0 uart connect --reconnect
You can run ffx over UART locally using the QEMU emulator (--engine qemu) without physical hardware. Just like physical targets, emulators do not expose a uart: address in ffx target list until you explicitly run ffx uart connect.
Start the QEMU emulator with -c "dev.fdomain.uart=true" and --console (or --headless):
ffx emu start -c "dev.fdomain.uart=true" --console --engine qemu
-c "dev.fdomain.uart=true": Passes the kernel command-line argument that starts fdomain-uart-driver on the target and configures QEMU's second emulated 16550 serial port (uart16550) as a host UNIX domain socket.--console (or --headless): Attaches serial port 0 to the interactive console while serial port 1 carries FDomain UART traffic. Use --headless for non-interactive runs.--net none (optional): Disables emulated networking to test a pure UART-only environment.Connect the host UART driver using the emulator's instance name:
ffx -t fuchsia-emulator uart connect
ffx uart connect resolves fuchsia-emulator to the running emulator instance‘s serial socket on the host and spawns ffx-uart-driver. Once connected, ffx target list includes uart:fuchsia-emulator in the target’s address list.
When both network and UART addresses are available on an emulator, ffx defaults to the network transport. Specify the uart: prefix (or set it as your default target with fx set-device uart:fuchsia-emulator) to route commands over the emulated UART link:
ffx -t uart:fuchsia-emulator target echo
When finished, disconnect the UART daemon and stop the emulator:
ffx -t fuchsia-emulator uart disconnect ffx emu stop
+-------------------------------------------------------------+ | Host Machine | | | | +------------+ +-------------------------------+ | | | ffx CLI | <----> | ffx-uart-driver (Daemon) | | | +------------+ (UNIX +-------------------------------+ | | Socket) | | | | (ResendSP Frames) | | v | | [/dev/ttyUSB0] (flock) | +-------------------------------------------------------------+ | | Physical Serial Cable | (1,000,000 Baud, 8N1) v +-------------------------------------------------------------+ | Target Hardware | | | | [/dev/class/serial/<instance>] | | | | | v | | +-----------------------------------+ | | | fdomain-uart-driver -> RCS | | | +-----------------------------------+ | +-------------------------------------------------------------+
The UART transport uses the ResendSP framing protocol to stream data over raw byte-oriented serial links:
HdrChk, CRC-8 polynomial 0x07) on the 13-byte frame header and a 32-bit IEEE 802.3 CRC (CRC-32) on frame payloads detect transmission errors caused by electrical line noise.ffx uart doctor to diagnose host-side state, port lock contention, and control socket health, or ffx uart doctor --fix to automatically clean up and repair issues./dev/ttyUSB0: Ensure your user account is in the dialout group (id $USER), and verify device permissions.EWOULDBLOCK / EAGAIN during connect): Another process holds an exclusive lock on the TTY device. Verify that no other serial terminal programs (e.g., minicom, screen, picocom) are open on the port.connect or probe: Check that the physical TX/RX lines are wired correctly, the bootloader UART mux and clock are configured for 1,000,000 baud, and the target booted with dev.fdomain.uart=true, kernel.serial=none, and console.shell=false.