Raspberry Pi serial interface issues

How to avoid dreaded SA818 DMOERROR message


            

There is a problem I forgot to take care before creating the custom image for my radio node project. Programming SA818 module via Raspberry Pi’s UART interface cannot be done unless the UART interface is released from any interaction in console mode. I was banging my head for hours because of sustained DMOERROR message for each and every single command it was issued on the UART interface.

Understanding UART, miniUART, Bluetooth, and Console Interaction on the Raspberry Pi (BCM2837)

Overview

The Broadcom BCM2837 System-on-Chip (SoC), used in Raspberry Pi 3 and some later models, provides two UART peripherals:

  • PL011 UART – A full-featured UART derived from the ARM PrimeCell PL011.
  • miniUART – A simpler UART with limited features and dependent clocking.

The interplay between these two UARTs, the Bluetooth module, and the Linux console configuration confused me (and surely had caused confusion among other users) — especially when serial communication appears to fail unless Bluetooth or the serial console is disabled. Programming SA818 module is a very good example.

This document tries to provide a complete, structured explanation.

BCM2837 UART Architecture

Available UART Interfaces

Interface Name Features Default usage
PL011 UART /dev/ttyAMA0 Full-featured UART with independent clock, FIFOs, and flow control Used for Bluetooth on Raspberry Pi 3/4
miniUART /dev/ttyS0 Simplified UART, no independent baud rate generator, clock-tied to CPU core frequency Used for GPIO serial (pins 14/15) by default

Clock Dependencies

  • PL011 UART:
    Uses a dedicated clock source, unaffected by CPU frequency scaling.
    → Stable baud rate under all operating conditions.
  • miniUART:
    Derives its clock from the core clock (VPU frequency).
    → If the CPU frequency changes (for power saving, DVFS), the baud rate changes, breaking serial communication stability. Because of this instability, the miniUART is not ideal for reliable serial communication unless the core clock is fixed.

Bluetooth and UART Resource Reassignment

Original UART Assignments (Pre–Raspberry Pi 3)

Function Device UART GPIO Pins
Primary UART (Serial Console) /dev/ttyAMA0 PL11 GPIO 14 (TX), GPIO 15 (RX)
No Bluetooth present

New Assignments (Raspberry Pi 3 and later)

Function Device UART GPIO Pins
Bluetooth /dev/ttyAMA0 PL11 Internal connection to BT chip
Serial GPIO (pins 14/15) /dev/ttyS0 miniUART GPIO header

Thus, for newer models, the hardware UART (PL011) is taken over by the Bluetooth controller, and users are left with the miniUART for serial console or communication — unless Bluetooth is disabled.

Why This Causes Problems

  1. The miniUART is clock-dependent → unstable baud rate.
  2. The console or serial login service is enabled by default on serial0.
  3. The default device tree overlay ties /dev/serial0 to the miniUART.
  4. Bluetooth occupies /dev/ttyAMA0 unless explicitly disabled.

Therefore:

  • If Bluetooth is active → PL011 is unavailable for GPIO serial.
    If console mode is active → miniUART is already reserved for system console use.
  • Result: No reliable UART available for custom serial communication.

Disabling Bluetooth to Reclaim PL011 for GPIO Serial

Device Tree Overlay Control

The Raspberry Pi OS device tree overlays determine which UART is assigned to which function.

To disable Bluetooth and reclaim the PL011 UART for GPIO edit /boot/config.txt or /boot/firmware/config.txt:

dtoverlay=disable-bt
enable_uart=1
  • dtoverlay=disable-bt → disables the Bluetooth service and reassigns PL011 to GPIO 14/15.
  • enable_uart=1 → ensures UART pins are active and not power-gated.

After reboot:

  • /dev/ttyAMA0 → GPIO pins (PL011, stable)
  • /dev/ttyS0 → unused
  • Bluetooth → disabled

Serial Console Interaction

What Is the Serial Console

The serial console allows kernel messages and shell access over UART. This is configured at boot by passing kernel parameters through /boot/cmdline.txt. Example default entry:

console=serial0,115200 console=tty1

This means:

  • Kernel logs are sent to serial0 (UART).
  • Console is also available on the HDMI display (tty1).

Device Aliases: serial0 and serial1

To provide consistency across models:

Alias Description
serial0 The primary UART (can map to PL011 or miniUART depending on configuration)
serial1 The secondary UART

The serial0 mapping depends on whether Bluetooth is enabled.

Bluetooth state serial0 maps to Type
Enabled /dev/ttyS0 miniUART
Disabled (dtoverlay=disable-bt) /dev/ttyAMA0 PL011

The cmdline.txt Effect

If you have an entry such as:

console=serial0,9600

This line reserves the serial port for kernel and login console use, meaning:

  • The system kernel and getty service take control of the UART.
  • Your user program cannot open the port because it is locked by the system.

This is why serial communication “does not work” when this line is present — the port is already in use by the kernel and login console. This is the BOTTOM of the SA818 DMOERROR problem !

SOLUTION: How to Free the UART for Application Use

Step-by-Step

Edit /boot/config.txt:

enable_uart=1
dtoverlay=disable-bt

Edit /boot/cmdline.txt:

Remove any console=serial0,... or console=ttyAMA0,... entries.
Example final version:

console=tty1 root=PARTUUID=xxxxxxxx-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

Disable serial console service:

sudo systemctl stop serial-getty@serial0.service
sudo systemctl disable serial-getty@serial0.service

Reboot

After reboot:

  • /dev/ttyAMA0 (PL011) is free for user-level serial communication.
  • Bluetooth and console no longer interfere.

Verifying UART Functionality

Checking UART Device Mapping

ls -l /dev/serial*

Expected output (after disabling BT):

serial0 -> ttyAMA0
serial1 -> ttyS0

Checking Configuration

vcgencmd get_config enable_uart

Should return:

enable_uart=1

Testing

sudo minicom -b 115200 -o -D /dev/serial0

Or use Python:

import serial
ser = serial.Serial('/dev/serial0', 115200)
ser.write(b'Hello UART!\n')
ser.close()
Scenario Bluetooth Console Enabled GPIO UART Device Stable ? User Access
Default (Raspberry Pi 3) ON YES MiniUART /dev/ttyS0 NO NO
Bluetooth ON, Console Disabled ON NO miniUART /dev/ttyS0 NO YES
Bluetooth OFF, Console Disabled OFF NO PL011 /dev/ttyAMA0 YES YES
Bluetooth OFF, Console Enabled OFF YES PL011 /dev/ttyAMA0 YES NO

Key Takeaways

Finally — and this was a long post ! — the following are the key takeaways:

  • BCM2837 has two UARTs: PL011 (stable, clocked) and miniUART (unstable, clock-dependent).
  • Bluetooth uses the PL011, forcing the GPIO UART to use miniUART unless disabled.
  • The serial console in cmdline.txt prevents user access to UART.
  • To use UART for your own program:
    • Disable Bluetooth (dtoverlay=disable-bt)
    • Enable UART (enable_uart=1)
    • Remove console from cmdline.txt
    • Disable serial-getty service

Using lsof

lsof command can show which processes are using which resources. This is extremely useful for troubleshooting. Basic syntax is:

lsof [options] [file]

Without arguments, it lists all open files on the system (requires root privileges).

Common Use Cases and Examples:

Find which process is using a file:

tom@rpi-i2s:~ $ sudo lsof /dev/serial0
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
screen 795 root 6u CHR 204,64 0t0 133 /dev/ttyAMA0

Find which process is using a port:

tom@rpi-i2s:~ $ sudo lsof -i :80

The above command Lists processes using TCP/UDP port 80 (e.g., web server).

List all open files by a specific user:

tom@rpi-i2s:~ $ lsof -u pi

The command above shows all files opened by user pi.

List all network connections:

tom@rpi-i2s:~ $ sudo lsof -i

The command above displays all open network sockets and connections.

List all open files for a process:

tom@rpi-i2s:~ $ lsof -p 1234

The command above shows all files opened by the process with PID 1234.

Find which process is using a mount point or device:

tom@rpi-i2s:~ $ sudo lsof /dev/sda1

The command above is useful when you get a “device is busy” error during unmount.

Option Description
-p <pid> List files opened by a specific process ID
-u <user> Show files opened by a user
-i Show network connections
+D <dir> Recursively list all files opened under a directory
-t Output only PIDs (useful in scripts)
-n Skip DNS resolution (faster output)
-P Show port numbers instead of names

Practical Example on Raspberry Pi

If you find that the UART (/dev/ttyAMA0 or /dev/serial0) is busy or inaccessible, run:

sudo lsof /dev/serial0

You might see:

COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
agetty    1014 root    3u   CHR 204,64      0t0  1234 /dev/ttyAMA0

This means the serial console service (agetty) is occupying the UART — so your program can’t use it until you stop that service.

In Summary

Task Command Purpose
Check which process uses a port sudo lsof -i :22 Find SSH or HTTP process
Check which process uses a file/device lsof /dev/ttyAMA0 Check serial port usage
See all network connections sudo lsof -i Network diagnostics
Kill a process holding a file kill $(sudo lsof -t /path/to/file) Release a locked file

kill user:

fuser -k /dev/ttyUSB9

That’s it !

Thanks for reading

73

Further reading:

https://raspberrypi.stackexchange.com/questions/45570/how-do-i-make-serial-work-on-the-raspberry-pi3-pizerow-pi4-or-later-models

Attempt to read property “slug” on null

While developing my website I frequently got warnings. When WordPress tries to access the property slug of an object that doesn’t exist (is null), it throws the following (or similar) warning: This usually happens when a menu, a snippet or other piece of code references a category that no longer exist. This means somewhere in […]

Cloning a Raspberry Pi SD card

Recently I had to make a bootable SD card for a Raspberry Pi Zero and I faced some issues. I thought to write some hints on how to properly clone and shrink a Pi image on an SD card. Here’s how you can create a compressed ISO (or disk image) from your Raspberry Pi SD […]

Comments are closed.