UART receive error when data stream contains long breaks

Open
#5,985 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
c, linux

Research direction

Start with the amba-pl011 UART receive path and reproduce on a Raspberry Pi 5 through /dev/ttyAMA0 using the supplied C transmitter and long-break sequence. Compare DMA_ENGINE enabled with it disabled, then verify that DMA-enabled reception returns the complete 77-byte stream accurately.

Written by the indexing model from the issue text.

Description

Describe the bug

UART (/dev/ttyAMBA0) erroneously receives only around 32 bytes of mostly incorrect data during transmissions containing long break signals.

Disabling DMA_ENGINE for amba-pl011 resolves the issue, ensuring accurate reception of all data (77 bytes).

Steps to reproduce the behaviour

Tx from host sending to Raspberry Pi 5:

  • 7 times this pattern:
    long-break, 0x55, 0xe2, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x30

Rx flowing into Raspberry Pi 5:

root@rpi5:~# od -v -w1 -t x1 /dev/ttyAMA0
0x00
0x00
0x55
0x80
0x00
0xf9
0xf9
0x78
0xf0
0xf9
0xc1
0xf9
0xf9
0xf9
0xf8
0xa0
0x95
0xfe
0x3c
0xe0
0xf9
0xf1
0xe4
0xf9
0xf9
0xf9
0xf9
0x01
0x00
0x55
0xe2
0xf9
0xf9

C test program for host to generate the Tx data (including long breaks):

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>

int set_speed(int fd, int speed) {
	struct termios tty;
	memset(&tty, 0, sizeof tty);
	if (tcgetattr(fd, &tty) != 0) {
		printf("Error %d from tcgetattr: %s\n", errno, strerror(errno));
		return -1;
	}
	cfsetospeed(&tty, speed);
	cfsetispeed(&tty, speed);
	if (tcsetattr(fd, TCSANOW, &tty) != 0) {
		printf("Error %d from tcsetattr: %s\n", errno, strerror(errno));
		return -1;
	}
	return 0;
}

int set_interface_attribs(int fd) {
	struct termios tty;
	if (tcgetattr(fd, &tty) != 0) {
		printf("Error %d from tcgetattr: %s\n", errno, strerror(errno));
		return -1;
	}

	tty.c_cflag &= ~(PARENB | PARODD | CRTSCTS | CSIZE);
	tty.c_cflag |= (CS8 | CLOCAL | CREAD);
	tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
	tty.c_oflag &= ~OPOST;
	tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);

	if (tcsetattr(fd, TCSANOW, &tty) != 0) {
		printf("Error %d from tcsetattr: %s\n", errno, strerror(errno));
		return -1;
	}
	return 0;
}

void send_lin_frame(int fd) {
	unsigned char lin_frame[] = {0x55, 0xe2, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x30};
	write(fd, lin_frame, sizeof(lin_frame));
}

int main() {
	char *portname = "/dev/ttyUSB0";
	int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
	if (fd < 0) {
		printf("Error %d opening %s: %s\n", errno, portname, strerror(errno));
		return -1;
	}
	set_interface_attribs(fd);

	for (int i = 0; i < 7; i++) {
		set_speed(fd, B2400);
		write(fd, "\0", 1); // Send long break signal
		set_speed(fd, B9600);
		send_lin_frame(fd); // Send LIN frame
	}

	close(fd);
	return 0;
}
Device (s)

Raspberry Pi 5

System

Tested on a Raspberry Pi 5 with kernel from current branch rpi-6.8.y (6.8.0-rc5 + Raspberry patches).

root@rpi5:~# cat /etc/rpi-issue
Raspberry Pi reference 2023-12-05
Generated using pi-gen, https://github.com/RPi-Distro/pi-gen, 70cd6f2a1e34d07f5cba7047aea5b92457372e05, stage4

root@rpi5:~# vcgencmd version
2024/01/05 15:57:40 
Copyright (c) 2012 Broadcom
version 30cc5f37 (release) (embedded)

root@rpi5:~# uname -a
Linux rpi5 6.8.0-rc5 #1 SMP PREEMPT Fri Feb 23 23:38:34 CET 2024 aarch64 GNU/Linux
Logs

No response

Additional context

No response

Dominant language
C
Stars
13.2k
Forks
5.5k
Avg merge
2d 21h
Merged PRs (30d)
21

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from raspberrypi/linux

All issues in raspberrypi/linux

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.