RobertCNelson / bb-kernel

MIT License
130 stars 102 forks source link

RS485 stop working #38

Open kzoltaan opened 7 years ago

kzoltaan commented 7 years ago

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 commented 7 years ago

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

kzoltaan commented 7 years ago

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 commented 7 years ago

I am on 4.9.15-bone4 and have got 8250

kzoltaan commented 7 years ago

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

kzoltaan commented 7 years ago

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 commented 7 years ago

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

kinkazu commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 6 years ago

Hi @kzoltaan ,

did you find a way to do that?

Thanks in advance

kzoltaan commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

my solution is working

tkuschel commented 3 years ago

@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, andecho blabla > /dev/ttyO2`

RobertCNelson commented 3 years ago

@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 commented 3 years ago

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 commented 2 years ago

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_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
###