Skip to main content

Enabling an External UART on AutoPi TMU CM4 Devices

Prerequisites

  1. SSH access or Physical HDMI/USB console.
  2. Micro‑jumper wires or a breakout header to reach pins 27/28.
  3. A multimeter (optional but handy for continuity checks).

Why GPIO 0/1?

The CM4 has six UART blocks but only GPIO 0 & 1 expose the pins for UART 2 (alt‑function 4). Your other free pins—GPIO22‑24, 27—can do many clever things (SPI, PCM, PWM) but not TX/RX. Hence we use the HAT‑EEPROM I²C pins (ID_SDID_SC) for serial use.

EEPROM probe vs. UART

Normally the Pi firmware tugs GPIO0/1 low during the first 200 ms of boot while it looks for a HAT EEPROM. The force_eeprom_read=0 flag in the next section disables that so your external device sees a clean idle‑high line from power‑up.


1  Hardware wiring

HAT labelBCM GPIOUART2 signalConnect to
ID_SD0TXD2 (Pi → device)RX of the external device
ID_SC1RXD2 (device → Pi)TX of the external device
I2C1_SDA*2CTS2 (optional)RTS of the device
I2C1_SCL*3RTS2 (optional)CTS of the device
GNDCommon ground

Wire CTS/RTS only if you need hardware flow control and intend to enable it in the dtoverlay.

       AutoPi TMU CM4       External Device
┌──────────────┐ ┌────────────┐
ID_SD│27 TXD2 ➔──┼────►│ RX │
ID_SC│28 RXD2 ◄──┼─────│ TX │
SDA │ 3 CTS2 ◄──┼─────│ RTS (opt) │
SCL │ 5 RTS2 ➔──┼────►│ CTS (opt) │
GND │ 6 GND ───┼─────│ GND │
└──────────────┘ └────────────┘
Level shifting

If the external device works at 5 V TTL or ±12 V RS‑232, you must level‑shift or use a proper line driver (e.g. MAX3232, SN65HVD230 for RS‑485). Direct 5 V into a CM4 pin can permanently damage the SoC.


2  Enable UART2 in config.txt

Open the file with sudo nano /boot/config.txt and add:

# === External UART2 on GPIO0/1 ===
force_eeprom_read=0 # skip HAT‑EEPROM probe on GPIO0/1
dtoverlay=uart2 # TX=GPIO0, RX=GPIO1 => /dev/ttyAMA1
#dtoverlay=uart2,ctsrts # remove # to enable flow control on GPIO2/3
enable_uart=1 # leave as‑is if already present

Save, exit, and sudo reboot.

Check dmesg after the reboot:

dmesg | grep -i ttyAMA1

You should see a line similar to ttyAMA1 at MMIO 0x..... confirming the driver is active.


3  Verify with a loop‑back test

  1. Jumper GPIO0 to GPIO1 directly on the HAT.

  2. Open a terminal on the Pi and run:

    stty -F /dev/ttyAMA1 115200 raw -echo
    echo "hello" > /dev/ttyAMA1 &
    cat < /dev/ttyAMA1
  3. The word hello should appear. Press Ctrl‑C, remove the jumper, and connect your real device.

Alternative: use minicom

sudo apt install -y minicom
minicom -b 115200 -D /dev/ttyAMA1

Minicom gives you scroll‑back, line‑ending control and macros—handy for debugging.


4  Using the port in Python

import serial

ser = serial.Serial(
port='/dev/ttyAMA1',
baudrate=115200,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1
)

ser.write(b'AT\r') # send a modem‑style command
print(ser.readline()) # read back a line
ser.close()

Python’s pyserial package makes scripting trivial—ideal for quick sensor polls.


5  Troubleshooting

SymptomLikely cause & fix
No /dev/ttyAMA1Overlay typo or missing enable_uart=1. Re‑check /boot/config.txt.
Boot hang with garbage on consoleAnother service (e.g. serial‑getty@ttyAMA1.service) grabbed the port. Disable it with sudo systemctl disable --now serial-getty@ttyAMA1.service.
Lines held low for ~0.2 s after power‑upforce_eeprom_read=0 missing; firmware still probing EEPROM.
Flow‑control ignoredVerify you removed # in dtoverlay=uart2,ctsrts and wired GPIO2/3 correctly.
Overruns at >1 Mbit/sIncrease init_uart_clock in config.txt or use DMA mode via dwc_uart_fifo_enable=1.

6  Advanced topics

Disable I²C on GPIO0/1 entirely

If another overlay or user‑space application tries to re‑enable I²C0, add dtparam=i2c_vc=off to config.txt.

Throughput tuning

Use core_freq_min=250 to keep the UART clock stable during idle throttling, and prefer 8N1 framing for max payload density.


7  References