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

RS485 stop working #38

Open
kzoltaan opened this issue Mar 16, 2017 · 17 comments
Open

RS485 stop working #38

kzoltaan opened this issue Mar 16, 2017 · 17 comments

Comments

@kzoltaan
Copy link

kzoltaan commented Mar 16, 2017

This is my RS485 config on boneblack.

`&am33xx_pinmux {
uart1_pins: uart1_pins {
pinctrl-single,pins = <
0x178 (PIN_OUTPUT | MUX_MODE7) /* uart1_ctsn.uart1_ctsn /
0x17c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /
uart1_rtsn.uart1_rtsn /
0x180 (PIN_INPUT_PULLUP | MUX_MODE0) /
uart1_rxd.uart1_rxd /
0x184 (PIN_OUTPUT | MUX_MODE0) /
uart1_txd.uart1_txd */
>;
};

};

&ocp{
P9_19_pinmux {
status = "disabled";
};

    P9_20_pinmux{
            status = "disabled";
    };

    P9_24_pinmux{
            status = "disabled";
    };


    P9_26_pinmux {
            status = "disabled";
    };

};

&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
status = "okay";
rts-gpio = <&gpio0 13 GPIO_ACTIVE_HIGH>;
rs485-rts-active-high;
rs485-rx-during-tx;
rs485-rts-delay = <1 1>;
linux,rs485-enabled-at-boot-time;
};
`

This is working on 4.2.5-armv7-x2 but not working on 4.9.0-armv7-x3. RTS pin is not working. Receive is OK. What is wrong?

@kinkazu
Copy link

kinkazu commented Mar 17, 2017

does
rts-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
make a difference?

@kzoltaan
Copy link
Author

I tried it! And no. Beacause: I think this is OMAP serial, and
https://github.com/torvalds/linux/blob/master/drivers/tty/serial/omap-serial.c
at line 1623
up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags);

@kinkazu
Copy link

kinkazu commented Mar 18, 2017

I am on 4.9.15-bone4 and have got 8250

@kzoltaan
Copy link
Author

it is working on 4.9.15-bone4? what is 8250?
not works on 4.10.1-armv7-x1 :(

@kzoltaan
Copy link
Author

kzoltaan commented Apr 23, 2017

Oh YES! S1 is rs485
[ 0.009123] WARNING: Your 'console=ttyO0' has been replaced by 'ttyS0' [ 2.182018] 44e09000.serial: ttyS0 at MMIO 0x44e09000 (irq = 158, base_baud = 3000000) is a 8250 [ 2.194875] console [ttyS0] enabled [ 2.195884] 48022000.serial: ttyS1 at MMIO 0x48022000 (irq = 159, base_baud = 3000000) is a 8250 [ 2.196708] 48024000.serial: ttyS2 at MMIO 0x48024000 (irq = 160, base_baud = 3000000) is a 8250 [ 2.197488] 481a6000.serial: ttyS3 at MMIO 0x481a6000 (irq = 161, base_baud = 3000000) is a 8250

@kzoltaan kzoltaan reopened this Apr 23, 2017
@kzoltaan
Copy link
Author

This is the problem. 8250 IS NOT SUPPORT RTS GPIO. but fixme. previous was OMAP UART

@kinkazu
Copy link

kinkazu commented Apr 23, 2017

Would be nice to have rts gpio working on 8250 and dts shared, I don't know why this is not important for 8250 developers.

@RobertCNelson
Copy link
Owner

Switch to the non generic omap serial driver. There was one developer working on it for the generic 8250 driver, but he seems to have disappeared.

Regards,

@kzoltaan
Copy link
Author

kzoltaan commented Apr 24, 2017

Here is the modification for rs485 by driver author.
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/271071.html

8250 driver also refer to omap3-uart, so when I change the driver in the device tree, there is no effect.
https://github.com/RobertCNelson/linux-stable-rcn-ee/blob/4.10-armv7-x1/drivers/tty/serial/8250/8250_omap.c#L1082

How can I switch the driver without rebuild the kernel? Can I do this?

@ercint
Copy link

ercint commented Aug 13, 2017

Hi @kzoltaan ,

did you find a way to do that?

Thanks in advance

@kzoltaan
Copy link
Author

kzoltaan commented Aug 14, 2017

I have an idea. I tried out and the RTS is working with user led.
I made a copy from https://github.com/RobertCNelson/linux-stable-rcn-ee/blob/4.9.9-ti-rt-r22/drivers/tty/serial/omap-serial.c ( i use 4.9.9-ti kernel right now)
I rewrite the ids

static const struct of_device_id omap_serial_of_match[] = {
        { .compatible = "ti,omap-uart-rs485" },
        {},
};

--- use it for uart1 ---


 uart1: serial@48022000 {
                        compatible = "ti,omap-uart-rs485";
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                        reg = <0x48022000 0x2000>;
                        interrupts = <73>;
                        status = "disabled";
                        dmas = <&edma 28 0>, <&edma 29 0>;
                        dma-names = "tx", "rx";
                };

I build the module:

Makefile:
obj-m += omap-serial.o

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

run make, copy the ko into drivers/tty/serial and run depmod

dtsi:

&uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart1_pins>;
        status = "okay";
        rts-gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>; // now this is user led
        rs485-rts-active-high;
        rs485-rx-during-tx;
        rs485-rts-delay = <10 0>;
        linux,rs485-enabled-at-boot-time;
};

build your device tree and try it. I'm using rs232 this is with 8250 and looks good.

[    2.397068] 44e09000.serial: ttyS0 at MMIO 0x44e09000 (irq = 158, base_baud = 3000000) is a 8250
[    2.411349] 48024000.serial: ttyS2 at MMIO 0x48024000 (irq = 160, base_baud = 3000000) is a 8250
[   19.639940] 48022000.serial: ttyO1 at MMIO 0x48022000 (irq = 159, base_baud = 3000000) is a OMAP UART1

please confirm!

@Ib2cool
Copy link

Ib2cool commented May 16, 2018

I have without success tried the get RS485 with RTS to drive DE and /RE.
I'm using kernel 4.9.88 and BB-UART4-RS485-00A0.dtbo
I have verified that I can toggle P9_27 as GPIO, but nothing happens when UART4 transmits
I tried with the default 8250 driver and I have also compiled the OMAP-SERIAL
A lot of the overlays handling have been changed and I have lost the overview.
Can someone provide a guide to get RS485 with RTS working?

@kzoltaan
Copy link
Author

my solution is working

@tkuschel
Copy link

@kzoltaan
Thanks for sharing your idea, I finally got my circuit to work properly with the RS485 on my UART2 and the RS-485-DE signal switched automatically. My use case was a connection of the RS-485 (EIA-485) directly to the BeagleBone Black UART2 via RS-485 driver IC MAX3483.

What I finally did with prerequisites installing lzop and lzma bison flex pkg-config libmpc-dev u-boot-tools libncurses5-dev:amd64 libssl-dev:amd64 on my Debian 10
1.) Cloning the bb-kernel and switch to 4.19 branch with:

git clone git@github.com:RobertCNelson/bb-kernel.git
cd bb-kernel
git checkout am33x-v4.19
./build_deb.sh

2.) Kernel Configuration: Device Drivers ---> Character Devices ---> Serial Drivers ---> OMAP serial port support <Y>
(set for includes), i.e. CONFIG_SERIAL_OMAP=y
3.) After Kernel compilation,
Edit/patch the files inside directory KERNEL/:

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 37ea4e662f8e..4d2aa7661b95 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -496,7 +496,7 @@
                };
 
                uart2: serial@48024000 {
-                       compatible = "ti,am3352-uart", "ti,omap3-uart";
+                       compatible = "ti,omap-uart-rs485";
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                        reg = <0x48024000 0x2000>;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6420ae581a80..b1b3c528c4ba 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1907,9 +1907,7 @@ static const struct dev_pm_ops serial_omap_dev_pm_ops = {
 
 #if defined(CONFIG_OF)
 static const struct of_device_id omap_serial_of_match[] = {
-       { .compatible = "ti,omap2-uart" },
-       { .compatible = "ti,omap3-uart" },
-       { .compatible = "ti,omap4-uart" },
+       { .compatible = "ti,omap-uart-rs485" },
        {},
 };
 MODULE_DEVICE_TABLE(of, omap_serial_of_match);

3.) Rebuild the Kernel with (do not build it again with build_deb.sh, it overwrites your changes from 2.)
./tools/rebuild_deb.sh
4.) Compile your device tree overlay file (BB-OAG2-00A0.dts), add the BB-OAG2-00A0.dtbo to /lib/firmware/, and
edit the following line inside /boot/uEnv.txt:

###Additional custom capes
uboot_overlay_addr4=/lib/firmware/BB-OAG2-00A0.dtbo

Extract from the dts overlay source file BB-OAG2-00A0.dts:

/*
 * compiled with
 * dtc -O dtb -o BB-OAG2-00A0.dtbo -b 0 -@ BB-OAG2-00A0.dts
 * tested on BeagleBone Black rev C
*/ 

/dts-v1/;
/plugin/;

#include <dt-bindings/board/am335x-bbw-bbb-base.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/am33xx.h>

/{
	compatible = "ti,beaglebone", "ti,beaglebone-black", "ti,beaglebone-green";

	/* identification */
	part-number = "BB-OAG2";
	version = "00A0";

	/* resources this cape uses */
	exclusive-use =
		"P9.18",  /* i2c1_sda SPI0_D1   GPIO_5  U2.18 */
		"P9.17",  /* i2c1_scl SPI0_CS0  GPIO_4  U2.17 */
		"P8.12",  /* led0     GPIO1_12  GPIO_44 U2.58 P1.8  P5.8  POWER */
		"P8.14",  /* led1     GPIO0_26  GPIO_26 U2.60 P1.7  P5.7  RUN   */
		"P8.16",  /* led2     GPIO1_14  GPIO_46 U2.62 P1.10 P5.10 USER  */
		"P9.21",  /* uart2    UART2_TXD GPIO_3  U2.21 P1.12 P5.12 */
		"P9.22",  /* uart2    UART2_RXD GPIO_2  U2.22 P1.9  P5.9  */

	/* preparation for a de/re Pin for RS485 through Linux driver */
		"P9.23",  /* rs485de  GPIO1_17  GPIO_49 U2.23 P2.9  P6.9 */
		"gpio1_17",/* rs485de GPIO1_17  GPIO_49 U2.23 P2.9  P6.9 */
	/* end of preparation for de/re Pin RS485 */

		"i2c1",	  /* hardware ip used */
		"uart2";  /* hardware ip used */

	/*
	 * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
	 */
	fragment@0 {
		target-path="/";
		__overlay__ {
			chosen {
				overlays {
					BB-OAG2-00A0 = __TIMESTAMP__;
				};
			};
		};
	};

	/*
	 * Free up the pins used by the cape from the pinmux helpers.
	 */
	fragment@1 {
		target = <&ocp>;
		__overlay__ {
			P9_17_pinmux { status = "disabled"; };	/* i2c1_scl */
			P9_18_pinmux { status = "disabled"; };	/* i2c1_sda */
			P8_12_pinmux { status = "disabled"; };	/* led0 power */
			P8_14_pinmux { status = "disabled"; };	/* led1 run */
			P8_16_pinmux { status = "disabled"; };	/* led2 user */
			P9_21_pinmux { status = "disabled"; };	/* uart2_txd */
			P9_22_pinmux { status = "disabled"; };	/* uart2_rxd */
			P9_23_pinmux { status = "disabled"; };	/* uart_de/re */
		};
	};

	fragment@2 {
		target = <&am33xx_pinmux>;
		__overlay__ {
			bb_i2c1_pins: pinmux_bb_i2c1_pins {
				pinctrl-single,pins = <
					BONE_P9_18 0x72	/* spi0_d1.i2c1_sda,  SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
					BONE_P9_17 0x72	/* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
				>;
			};

			bb_gpio_led_pins: pinmux_bb_gpio_led_pins {
				pinctrl-single,pins = <
					BONE_P8_12 (PIN_OUTPUT | MUX_MODE7)	/* P8_12: gpmc_ad12.gpio1_12 */
					BONE_P8_14 (PIN_OUTPUT | MUX_MODE7)	/* P8_14: gpmc_ad10.gpio0_26 */
					BONE_P8_16 (PIN_OUTPUT | MUX_MODE7)	/* P8_16: gpmc_ad14.gpio1_14 */
				>;
			};

			bb_uart2_rs485_pins: pinmux_bb_uart2_rs485_pins {
				pinctrl-single,pins = <
					BONE_P9_21 (PIN_OUTPUT | MUX_MODE1)		/* P9_21: spi0_d0.uart2_txd */
					BONE_P9_22 (PIN_INPUT_PULLUP | MUX_MODE1)	/* P9_22: spi0_sclk.uart2_rxd */
					BONE_P9_23 (PIN_OUTPUT | MUX_MODE7)		/* P9_23: gpmc_a1.gpio1_17 */
				>;
			};
		};
	};

	fragment@3 {
		target-path="/";
		__overlay__ {
			aliases {
				rtc0 = &extrtc;
				/* The OMAP RTC implementation in the BBB is
				 * buggy, so that it cannot be used as a
				 * battery-backed RTS, so that it loses its
				 * contents when power is removed from the
				 * Beaglebone...
				 *
				 * We move the omap built-in RTC to rtc1, so
				 * that userspace defaults to using the DS1338.
				 *
				 * The omap RTC must remain enabled because it
				 * is also used during the reboot process on the
				 * BBB.
				 */
				rtc1 = "/ocp/rtc@44e3e000";
			};
			
			leds {
				pinctrl-names = "default";
				pinctrl-0 = <&bb_gpio_led_pins>;

				compatible = "gpio-leds";

				P8_12 {
					label = "oag2:pwr";
					gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
					linux,default-trigger = "none";
					default-state = "on";
				};
				P8_14 {
					label = "oag2:run";
					gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
					linux,default-trigger = "activity";
					default-state = "on";
				};
				P8_16 {
					label = "oag2:usr";
					gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
					linux,default-trigger = "none";
					default-state = "on";
				};
			};
		};
	};

	fragment@4 {
		target = <&i2c1>;
		__overlay__ {
			status = "okay";
			pinctrl-names = "default";
			pinctrl-0 = <&bb_i2c1_pins>;
			/* configuration part */
			clock-frequency = <400000>;
			#address-cells = <1>;
			#size-cells = <0>;
			/* add any i2c devices on the bus here */
			extrtc: ds3231@68 {
				compatible = "maxim,ds3231";
				reg = <0x68>;
			};
		};
	};
	fragment@5 {
		target = <&uart2>;
		__overlay__ {
			status = "okay";
			pinctrl-names = "default";
			pinctrl-0 = <&bb_uart2_rs485_pins>;
			rts-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
			rs485-rts-active-high;
			/* rs485-rx-during-tx; */
			rs485-rts-delay = <1 0>; /* 1 ms delay before send, no delay after send */
			linux,rs485-enabled-at-boot-time;
		};
	};
};

5.) After transfer of the three deploy/*.deb files to the beagle board, install it with sudo dpkg -i linux-*.deb
6.) Reboot and test with 19200 baud rate: stty -F /dev/ttyO2 19200, and echo blabla > /dev/ttyO2

@RobertCNelson
Copy link
Owner

RobertCNelson commented Jan 30, 2021

@tkuschel impressive i like what you did here!

we should be able to actually do the 'whole"..

-                       compatible = "ti,am3352-uart", "ti,omap3-uart";
+                       compatible = "ti,omap-uart-rs485";

in the overlay

We will still have to patch the kernel compable layer:

 static const struct of_device_id omap_serial_of_match[] = {
-       { .compatible = "ti,omap2-uart" },
-       { .compatible = "ti,omap3-uart" },
-       { .compatible = "ti,omap4-uart" },
+       { .compatible = "ti,omap-uart-rs485" },
        {},
 };

but yeah, i like it!

@willeccles
Copy link

This is the problem. 8250 IS NOT SUPPORT RTS GPIO. but fixme. previous was OMAP UART

For anyone curious, OMAP 8250 (tested in 4.19 and 5.10) does support the RTS GPIO. However, it will not support arbitrary GPIOs. For example, when using UART1, your RTS GPIO must be UART1_RTSN. However, I was still unable to get this to work. As it turned out, I had to actually mux the pin in mode 7 to make it a GPIO.

As I understand it, the 8250 driver doesn't support arbitrary GPIOs, while the older OMAP serial driver does. I have not tested this theory in more recent versions. I did, however, find that 4.20+ introduced an issue where FIFOs were not properly cleared for RS-485, which Robert has already added a patch for (see #65 for details).

My final config is like this:

/* excerpt from am33xx_pinmux */
uart0_pins: pinmux-uart0-pins {
  pinctrl-single,pins = <
    AM33XX_IOPAD(0x970, PIN_INPUT | MUX_MODE0) /* uart0_rxd */
    AM33XX_IOPAD(0x974, PIN_OUTPUT | MUX_MODE0) /* uart0_txd */
    AM33XX_IOPAD(0x96c, PIN_OUTPUT | MUX_MODE7) /* uart0_rtsn.gpio1[9] */
  >;
};

&uart0 {
  ...
  linux,rs485-enabled-at-boot-time;
  rts-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
  rs485-rts-delay = <0 0>; /* note: some older versions of the driver may require at least <1 1> */
  rs485-rts-active-high;
};

I have disabled the OMAP serial driver and enabled the 8250-based driver. This has been tested and works with an ADM3061 with UART1_RTSN routed to the RE/DE pin. It took me quite a while to realize that the pin had to be mapped as a GPIO rather than as the RTSN pin (which is a bit misleading IMO), but this setup seems to work on 4.19+ at the very least.

@breshead
Copy link

I am using the BB-UART4-RS485-00A0.dtbo overlay which uses the 'MUX_MODE7' on P9_27 so I am not seeing anything that should keep it from working, however P9_27 (RE/DE line) is never going low. The 8250 driver is being used.
I assumed given this (correct?) configuration, the hardware signaling should work (Driving a MAX485 chip).
Did I miss anything?

$ uname -a
Linux beaglebone 4.19.94-ti-r42 #1buster SMP PREEMPT Tue Mar 31 19:38:29 UTC 2020 armv7l GNU/Linux


$ dmesg | grep -i 8250
[    0.863340] Serial: 8250/16550 driver, 6 ports, IRQ sharing disabled
[    0.867027] 44e09000.serial: ttyS0 at MMIO 0x44e09000 (irq = 30, base_baud = 3000000) is a 8250
[    0.878359] 481a8000.serial: ttyS4 at MMIO 0x481a8000 (irq = 31, base_baud = 3000000) is a 8250
debian@beaglebone:~/dev/c_pivot_logic/src$ 



$ sudo cat /sys/kernel/debug/pinctrl/44e10800.pinmux-pinctrl-single/pingroups | grep -A4 uart4
group: pinmux_bb_uart4_rs485_pins
pin 29 (PIN29)
pin 28 (PIN28)
pin 105 (PIN105)

From here (Setting Up the BeagleBone Black's GPIO Pins
) I read that

  • P9_11 == pin 28
  • P9_13 == pin 29
  • P9_27 == pin 105

P9_27 always stays high so it is only able to send through max485 chip.

Changes I made to /boot/uEnv.txt

# Enable UART4 pins as rs485 control.
uboot_overlay_addr3=/lib/firmware/BB-UART4-RS485-00A0.dtbo

# enable SPI0 for display panel
uboot_overlay_addr4=/lib/firmware/BB-SPIDEV0-00A0.dtbo


###Cape Universal Enable
#enable_uboot_cape_universal=1
###

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

No branches or pull requests

8 participants