Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow disabling FIFOs on PL011 UART #5794

Open
wants to merge 2 commits into
base: rpi-6.1.y
Choose a base branch
from

Conversation

ITachiLab
Copy link

The BCM2835 PL011 implementation assumes that Rx/Tx FIFOs should be always enabled. Although this is desirable for most of the time, there are rare occasions when FIFOs introduce unwanted delay on the line. The delay is unnoticeable for the common UART use cases but it can lead to communication failures in UART-based protocols expecting fast responses, such as eBUS.

The solution is to add a new disable-fifos property to Pi DTBs and use the presence of that property to forcefully set FIFOs size to 1, and prevent FIFOs from being enabled in the PL011 driver.

Example issues that might be originating from the delay introduced by FIFO buffering:

Tested with ebusd on Raspberry Pi Zero W v1.1. I was able to communicate with eBUS's participants after adding dtoverlay=uart0,disable_fifos to config.txt. If it's not appropriate to keep this flag in the "uart0" overlay, a dedicated overlay for the flag can be created instead.

Results on logic analyzer

For a simple test I tied TX and RX pins together, and I ran a simple program written in C in which I'm writing a single character, reading it back, and then writing and reading it again. This way I can test if there are any delays in both write and read queues.

FIFO is enabled

The first screenshot shows that when FIFOs are enabled, the gap between consecutive write/read/write operations is roughly 13 milliseconds.

FIFO is disabled

The same test repeated when FIFOs are disabled shows that the gap is now only 30 microseconds. This is 430 times smaller than when FIFOs were enabled.

The code I used for testing:

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

int main() {
    int port = open("/dev/ttyAMA0", O_RDWR);

    if (port < 0) {
        printf("Cannot open port\n");
        return -1;
    }

    struct termios tty;

    tty.c_cflag &= ~(PARENB | CSTOPB | CRTSCTS);
    tty.c_cflag |= CREAD | CLOCAL | CS8;

    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG);

    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR 
            | ICRNL | IXON | IXOFF | IXANY);

    tty.c_oflag &= ~(OPOST | ONLCR);

    tty.c_cc[VTIME] = 10;
    tty.c_cc[VMIN] = 0;

    cfsetispeed(&tty, B2400);

    if (tcsetattr(port, TCSANOW, &tty) != 0) {
        printf("Cannot write attributes\n");
        close(port);

        return -1;
    }

    char read_buffer[1];
    unsigned char msg[] = { 'a' };
    int read_chars;

    write(port, msg, 1);
    read_chars = read(port, read_buffer, 1);

    write(port, msg, 1);
    read(port, read_buffer, 1);

    close(port);

    printf("Read: %d\n", read_chars);

    return 0;
}

The BCM2835 PL011 implementation assumes that Rx/Tx FIFOs should be
always enabled. Although this is desirable for most of the time, there
are rare occasions when FIFOs introduce unwanted delay on the line.
The delay is unnoticeable for the common UART use cases but it can lead
to communication failures in UART-based protocols expecting fast
responses, such as eBUS.

Add a "disable-fifos" property to Pi DTBs and use the presence of that
property to forcefully set FIFOs size to 1, and prevent FIFOs from being
enabled.

Signed-off-by: Bak, Krzysztof <github@bittern.com.pl>
Add a "disable_fifos" switch to existing "uart0-overlay.dts". The new
switch can be used to disable FIFOs on PL011 (uart0).

Signed-off-by: Bak, Krzysztof <github@bittern.com.pl>
@ITachiLab
Copy link
Author

CC: @pelwell (Based on recent changes done to the same source files)

@pelwell
Copy link
Contributor

pelwell commented Jan 3, 2024

  1. I'm not particularly interested in taking on a niche patch such as this, given that we will have to maintain it.
  2. "The BCM2835 PL011 implementation assumes that Rx/Tx FIFOs should be always enabled." Do other drivers make FIFO usage conditional in some way?
  3. You don't need to patch sbsa_uart_probe - that code path is not used on Raspberry Pis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants