Pi models and serial consoles¶
You operate the fleet and want to know how the Raspberry Pi models in it differ where it matters (the serial port on the 40-pin header, the console, the USB-C port), and how to free that serial port for a board, before you wire a board to one or debug its UART. Each row says where it is from.
The models¶
Pi 3B+ |
Pi 4 |
Pi 5 |
Compute Module 4 |
Compute Module 5 |
|
|---|---|---|---|---|---|
Where in the fleet (the site pages’ tables) |
welland: NeTV2 and Fomu hosts, Tiny Tapeout ASIC hosts on switch 2 ports 6 to 8; ps1: Arty pi7, pi9 |
welland: Tiny Tapeout ASIC hosts on ports 3 to 5 and the FPGA hosts on 33 to 36; ps1: Arty pi3 |
welland: the Acorn hosts on switch 2 |
ps1: pi14, pi18 (Compute Blades) |
ps1: pi16, pi20 (Compute Blades) |
Header UART (GPIO14/15) |
|
|
|
|
|
Kernel console in welland’s root |
|
|
|
not booted from it |
not booted from it |
USB-C console (gadget mode) in welland’s root |
no: its only USB controller is the gadget one |
yes ( |
yes ( |
not booted from it |
not booted from it |
Sources: the 40-pin and console rows for welland are roles/fixpi/tasks/tweeks.yml and the two command-line
templates in fpgas.online-infra (main, read 2026-10-07); the Compute Module rows are the pinctrl reads of the
four ps1 blades on 2026-10-07 (Acorns at ps1: what was read on each
blade). The ps1 blades boot ps1’s own root, with the kernel
console on ttyAMA0 and a login on it; that is why JTAG and the FPGA’s UART cannot be used there as they are.
Compute Module 4. GPIO14 = TXD0 and GPIO15 = RXD0 at alt0, on the BCM2711 serial blocks, and only
/dev/ttyAMA0 exists. There is no mux option that makes GPIO15 a transmitter, so an FPGA’s TX must land on
GPIO15: one correct wiring, no software escape (from the earlier docs page, not re-checked). The pinctrl set 14,15 a0 step for a CM4 is on Compute Blade JTAG.
Compute Module 5. GPIO14/15 at alt4 on the RP1 (read on the four ps1 blades on 2026-10-07, above). Like the
Pi 5, the RP1 offers several UART instances plus PIO, so pins can be reassigned in software. Measured on CM5
Lite modules, but this is the RP1’s behaviour, not something specific to the Lite (from the earlier docs page,
not re-checked; it also named /dev/ttyAMA10 on the CM5).
Why the Pi 5 differs: dtoverlay=disable-bt frees the header UART on a Pi 0 to 4 as a side effect, because
disable-bt.dtbo is compatible="brcm,bcm2835" and one of its fragments turns uart0 on. On a Pi 5 the
firmware resolves the same line to disable-bt-pi5.dtbo (compatible="brcm,bcm2712"), whose only fragment
targets bluetooth, and the Pi 5 device tree ships the RP1 header UART disabled; so it stays off until
uart0-pi5 turns it on. Source: the comment in ansible/roles/fixpi/tasks/tweeks.yml (read 2026-10-07),
added with uart0-pi5 by fpgas.online-infra PR #32, merged 2026-08-31. Turning it on would put a console=serial0 console onto
the FPGA’s UART; the Pi 5’s command line therefore names ttyAMA10. These console rows are what the templates
serve; a /proc/cmdline read on each model at welland is still to do.
Which GPIO chip carries the header, for libgpiod tools such as openFPGALoader’s libgpiod cable, depends on
the model and the kernel: Acorn on a Raspberry Pi 5: the Pi’s settings
has what was read on the welland Pi 5s.
Freeing the header UART for a board¶
When an FPGA board will drive the header UART, nothing else may hold it. In welland’s root no console or
login is on it, so check that the Pi has the port and that nothing has it open. fuser is in the psmisc
package; if the root lacks it, sudo apt install psmisc puts it in this boot’s tmpfs.
$ if [ -e /dev/serial0 ]; then sudo fuser -v "$(readlink -f /dev/serial0)"; else echo "no header UART on this Pi"; fi
If it printed “no header UART on this Pi”, stop here: there is nothing to free.
If a login is on it (a Pi booted from another root, such as a ps1 blade), stop it for this boot. stop alone
is not enough, because systemd starts it again; mask it, then stop it:
$ GETTY="serial-getty@$(basename "$(readlink -f /dev/serial0)").service"
$ sudo systemctl mask "$GETTY"
$ sudo systemctl stop "$GETTY"
$ sudo fuser -v "$(readlink -f /dev/serial0)" # expect nothing
The mask lives in the tmpfs layer, so it is gone at the next reboot. A kernel console on that UART cannot be moved without a reboot; on ps1’s blades that is the change Acorns at ps1 asks for.
Warning
A design that transmits on the UART while the kernel console is on it does more than print noise: on a
Compute Blade at ps1 it produced bytes the kernel read as SysRq commands, ending in a reboot (the kernel
console on the FPGA UART). welland’s
root sets kernel.sysrq = 0 as well as keeping the console off that UART.
Other serial ports on a Pi¶
A Tiny Tapeout board’s own USB serial is
/dev/ttboard: a udev rule infpgas-online-tt(debian/60-fpgas-tt.rules, main, read 2026-10-07) gives the demo board’s RP2040/RP2350 CDC port that symlink, matching2e8a:0005and2e8a:000f,GROUP="dialout", mode 0660. Thefpgas-ttdaemon holds the port open permanently and fans it out over WebSocket, sompremoteand the programming scripts cannot open it while the daemon runs (The Tiny Tapeout stack; the consequences are under Serial port ownership).The USB-C console on a Pi 4 or Pi 5, and the kernel log over the network (
netconsoleto the gateway, 10.21.0.1): When a Pi does not boot.