Jump to content

RTS signal and uart2 init


garinus

Recommended Posts

Armbianmonitor:

Hi all,

I need to enable rts/cts on my OrangePi Zero with Armbian buster with Linux 5.4.26-sunxi installed.
I added the "param_uart2_rtscts=1" (I'm using /dev/ttyS2) to the /boot/armbianEnv.txt file

 

On mi code I use this initialization of the port.

xxxxx.c_cflag |=
        port_parity |
        port_bits |
        port_stop |
        CLOCAL |
        CRTSCTS |
        CREAD;

 

Not only rts/cts but also the tx and rx pin aren't working now.

Has anyone managed to enable the port on this board? Am I doing something wrong?

Link to comment
Share on other sites

I'm trying to debug it using the oscilloscope, and I see that the TX signal is not initialized to 3v3 when I add the "param_uart2_rtscts=1" in the armbianEnv.txt file.
If I do not edit the armbianEnv file, the board initializes correctly the TX and RX signals.

Link to comment
Share on other sites

I found this in boot:

 

Applying kernel provided DT overlay sun8i-h3-usbhost2.dtbo
504 bytes read in 5 ms (97.7 KiB/s)
Applying kernel provided DT overlay sun8i-h3-usbhost3.dtbo
502 bytes read in 5 ms (97.7 KiB/s)
Applying kernel provided DT overlay sun8i-h3-uart2.dtbo
502 bytes read in 5 ms (97.7 KiB/s)
Applying kernel provided DT overlay sun8i-h3-uart3.dtbo
4155 bytes read in 5 ms (811.5 KiB/s)
Applying kernel provided DT fixup script (sun8i-h3-fixup.scr)
## Executing script at 44000000
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND

## Loading init Ramdisk from Legacy Image at 43300000 ...
   Image Name:   uInitrd
   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
   Data Size:    7347265 Bytes = 7 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK

 

what can be the cause of this error? 
 

Link to comment
Share on other sites

UART2 with TX/RX should work out of the box if you enable the "uart2" overlay in armbianEnv.txt. I see you also have uart3 activated, afaik this port is not routed out on a OPZ.
RTS/CTS for UART2 is missing at the moment, but you can add it to the device tree manually. Create the file "uart2_rtscts_fix.dts" in your home folder:

/dts-v1/;
/plugin/;

/ {
	compatible = "allwinner,sun8i-h3";

	fragment@0 {
		target = <&pio>;
		__overlay__ {
			uart2_rts_cts: uart2_rts_cts {
				pins = "PA2", "PA3";
				function = "uart2";
			};
		};
	};
};

Then run this to compile and add the custom overlay it to the device tree:

armbian-add-overlay uart2_rtscts_fix.dts

You need to keep param_uart2_rtscts=1, and on the next reboot, the error should be gone.

 

Edit: Oh and systemd likes to start a getty shell on all serial ports, so you may need to kill that service to make the port usable:

systemctl stop serial-getty@ttyS2.service

 

Link to comment
Share on other sites

thank you yoq,

i did all what you said, but the serial works until i add param_uart2_rtscts=1 in the armbianEnv.txt file:

 

verbosity=1
logo=disabled
console=serial
disp_mode=1920x1080p60
overlay_prefix=sun8i-h3
overlays=uart2 usbhost2 usbhost3
rootdev=UUID=48c1e88a-b408-42ec-9d6c-9aaacd147312
rootfstype=ext4
user_overlays=uart2_rtscts_fix
param_uart2_rtscts=1
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u

 

Link to comment
Share on other sites

25 minutes ago, garinus said:

but the serial works until i add param_uart2_rtscts=1 in the armbianEnv.txt file:

This thread reveal some bug present in fixup scripts that were not be updated since introduction of 5.x.y :

 

I've done some fixes and committed this morning.

You can either wait for new images, or build yourself a new image, or try to fix the sun8i-h3-fixup.scr yourself manually.

Link to comment
Share on other sites

Hi,

thanks Martin.

I built the last image. There aren't errors on boot and the ttS2 now works when I add the param param_uart2_rtscts=1.  I have still some problems on rts. 

The signal is high until I open the serial connection, then goes low for all the time the serial stay open and then it become high when I close the serial connection. 

I made several tries with all the settings I know. 

The simplest metod to test it is using tio: tio /dev/ttyS2 -f hard-b 115200

With -f none (no hardwae flow control) the serial has the same behaviour.

Link to comment
Share on other sites

Yes, the goal is to use a 485 tranceiver directly, without acting at high level on RTS pin. Now I use ioctl to verify the finish of the tx and i change the state of the pin. This works in 99% of cases except when the cpu is doing something and there is a delay before the change of the signal.

 

I'm having diffculties in applying the patch because i'm a noob in git and kernel compiling. 

 

Please correct me if I do something wrong:

 

put the file .patch in the folder build/cache/sources/linux-mainline/orange-pi-5.5

 

launch the command git apply rs485-8250_dw.patch

error: patch failed: drivers/tty/serial/8250/8250.h:136
error: drivers/tty/serial/8250/8250.h: patch does not apply
error: patch failed: drivers/tty/serial/8250/8250_dw.c:637
error: drivers/tty/serial/8250/8250_dw.c: patch does not apply

 

then if the apply goes well launch 

compile.sh in /build

 

I'm doing something wrong that i receive this errors?

Link to comment
Share on other sites

On 4/3/2020 at 8:26 AM, martinayotte said:

This patch will add RS485 emulation ...

 

Hello, I need RS485 half-duplex too.

I applied the patch, but behaviour is the same. RTS goes down when transmition started ang goes up only when application closed.

Maybe I missed how to turn ON the emulation mode?

Any advice please

thanks

Link to comment
Share on other sites

15 hours ago, mycnc said:

Maybe I missed how to turn ON the emulation mode?

After having built a kernel with the above patch to get half-duplex emulation, you also need to initialize the port with proper flags, with either "-i" or not, depending of ActiveHigh or ActiveLow output.

 



#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <linux/serial.h>
#include <sys/ioctl.h>


void init_port(char *port, int rts_state) {
    struct serial_rs485 rs485conf = {0};
    struct termios tty;    

    int fd = open(port, O_RDWR);
    if (fd < 0) {
        printf("ERROR! Open() failed \r\n");
    }

    rs485conf.flags = SER_RS485_ENABLED;
    if (rts_state == 0)
        rs485conf.flags |= SER_RS485_RTS_ON_SEND;
    else
        rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
    if (ioctl(fd, TIOCSRS485, &rs485conf) < 0) {
        printf("ERROR! ioctl settings update failed \r\n");
    }

    if (tcgetattr(fd, &tty) < 0) {
        printf("Error from tcgetattr: %s\n", strerror(errno));
    }
    cfsetospeed(&tty, (speed_t)115200);
    cfsetispeed(&tty, (speed_t)115200);

    tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;         /* 8-bit characters */
    tty.c_cflag &= ~PARENB;     /* no parity bit */
    tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
    tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */
    
    /* setup for non-canonical mode */
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;

    /* fetch bytes as they become available */
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 1;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        printf("Error from tcsetattr: %s\n", strerror(errno));
    }
    
    if (close(fd) < 0) {
        /* Error handling. See errno. */
        printf("ERROR! Close() failed \r\n");
    }
}
    

int main(int argc, char *argv[]) {
    if (argc > 1) {
        if (strcmp(argv[1], "-i") == 0) {
            printf("inverted port = %s\n", argv[2]);
            init_port(argv[2], 1);
        }
        else {
            printf("port = %s\n", argv[1]);
            init_port(argv[1], 0);
        }
    }
    else {
        printf("usage :   rs485-init <port>\n example : rs485-init /dev/ttyS1\n");
    }
    return 0;
}

 

Link to comment
Share on other sites

On 4/3/2020 at 7:26 PM, martinayotte said:

Are you wish to use RTS as RS485 HalfDuplex control pin ?

In such case, you will need another patch since the dw8250 driver doesn't support it.

This patch will add RS485 emulation ...

 

rs485-8250_dw.patch 12.08 kB · 30 downloads

I got an error compiling your patch

 

Processing file /home/pacol/build/patch/kernel/sunxi-dev/rs485-8250_dw.patch
1 out of 1 hunk FAILED -- saving rejects to file include/linux/serial_8250.h.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250.h.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250_omap.c.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250_core.c.rej
4 out of 8 hunks FAILED -- saving rejects to file drivers/tty/serial/8250/8250_port.c.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250_of.c.rej
 

Link to comment
Share on other sites

45 minutes ago, iqbal said:

I got an error compiling your patch

 

Processing file /home/pacol/build/patch/kernel/sunxi-dev/rs485-8250_dw.patch
1 out of 1 hunk FAILED -- saving rejects to file include/linux/serial_8250.h.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250.h.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250_omap.c.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250_core.c.rej
4 out of 8 hunks FAILED -- saving rejects to file drivers/tty/serial/8250/8250_port.c.rej
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/8250/8250_of.c.rej
 

 

Quote

sunxi-dev

wrong kernel version. Try legacy

Link to comment
Share on other sites

7 hours ago, iqbal said:

I got an error compiling your patch

My patch was working with <=5.7.y, but not anymore with >=5.8.y due to someone else patch been mainlined .

I'm still investigating how to make it work again and/or make the someone else patch working as my previous one ...

Link to comment
Share on other sites

On 8/20/2020 at 12:26 PM, martinayotte said:

I'm still investigating how to make it work again and/or make the someone else patch working as my previous one ...

 

Hi,

 

do you update/fix rs485-8250 patch for current kernel (5.10)?

Link to comment
Share on other sites

On 11/1/2021 at 6:51 PM, martinayotte said:

 

I don't know ... I've worked on this since almost a year ...

So ... I was trying to look too.

 

Looks like this patch (series) make mess with your rs485-8250 patch, but don't enable software emulated rs485 for dw variant nor provide own workaround for chips without "end transmit" interrupt.

 

I created minimal patch for add this workaround (from your patch) to current kernel:

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 9c00d7504..bc8cd87ee 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -469,6 +469,10 @@ static int dw8250_probe(struct platform_device *pdev)
 	p->set_ldisc	= dw8250_set_ldisc;
 	p->set_termios	= dw8250_set_termios;
 
+	p->rs485_config = serial8250_em485_config;
+	up->rs485_start_tx = serial8250_em485_start_tx;
+	up->rs485_stop_tx = serial8250_em485_stop_tx;
+
 	p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
 	if (!p->membase)
 		return -ENOMEM;
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index be779eb9e..c9f5b626e 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1541,8 +1541,14 @@ static inline void __stop_tx(struct uart_8250_port *p)
 		 * shift register are empty. It is for device driver to enable
 		 * interrupt on TEMT.
 		 */
-		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
-			return;
+		//if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
+		//	return;
+		// TODO: use if / while variant depending on the support / not support interrupt ...
+		// TODO: or provide different serial8250_stop_tx for chips without interrupt
+		while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) {
+			lsr = serial_in(p, UART_LSR);
+			cpu_relax();
+		}
 
 		__stop_tx_rs485(p);
 	}

This is more "dirty hack" than "good patch" (always use "no interrupt" approach - see todo note in code), but it's work for me :) (at least for now, more tests shortly).

Link to comment
Share on other sites

Attached is a git diff, which includes 2 patches:

  • rs485-8250_dw.patch - manually merged for 5.13.3
  • [PATCH] tty: 8250_of: Use software emulated RS485 direction control @ 2019-09-13 5:01 Heiko Schocher

As you can see it's for the current/latest armbian kernel version 5.13.3 . I haven't re-applied the patch to see if patching works but with these changes RS485 works great for me on my NanoPI Neo.

 

I don't use any additional ENV-vars for booting, but this DTS::

/dts-v1/;
/plugin/;

/ {
	compatible = "allwinner,sun8i-h3";

	fragment@0 {
		target = <&uart2>;
		 __overlay__ {
			pinctrl-names = "default";
			pinctrl-0 = <&uart2_pins>;
			linux,rs485-enabled-at-boot-time;
			rs485-rts-active-low;
			//rs485-rx-during-tx;
			rts-gpios = <&pio 0 2 1>;
			status = "okay";
		};
	};
};

 

 

This took me 3 days but I wouldn't get it running without this forum.

 

Thanks Armbian Team!

rs485-8250_dw-8250_of.patch

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines