简体   繁体   English

在Linux AUART内核驱动程序中,如何使用I2C GPIO扩展器的引脚而不是RTS来控制RS485方向?

[英]How to use I2C GPIO expander's pin instead of RTS to control the RS485 direction, in Linux AUART kernel driver?

I'm creating an embedded system based on i.MX287 processor from NXP(Freescale). 我正在基于NXP(Freescale)的i.MX287处理器创建一个嵌入式系统。 I'm using a core processing board which is connected to my evaluation board via a mini PCIe connector. 我正在使用一个通过迷你PCIe连接器连接到我的评估板上的核心处理板。

UARTs 0,3,4 are used as RS232 and UARTs 1,2 as RS485. UART 0、3、4用作RS232,而UART 1,2用作RS485。 The core board does not provide the RTS signals in its pinout, so I have to use pins from an I2C GPIO expander to control the RS485 direction. 核心板不在其引脚上提供RTS信号,因此我必须使用I2C GPIO扩展器中的引脚来控制RS485方向。 The GPIO expander module is also used for controlling some other devices on the board. GPIO扩展器模块还用于控制板上的其他一些设备。

In user-space, I can control the direction pin using libi2c, but my client asked me to put the direction pin control in the UART driver. 在用户空间中,我可以使用libi2c控制方向针,但是我的客户要求我将方向针控制放在UART驱动程序中。

Questions: 问题:

1 - how can I interact with an i2c device inside the auart driver? 1-如何与auart驱动程序中的i2c设备进行交互? (is it possible) (可能吗)

2 - if it is possible, then how to prevent the i2c-0 bus from being blocked by the kernel? 2-如果可能,那么如何防止i2c-0总线被​​内核阻塞? (I also need the userspace calls to the libi2c to work properly) (我还需要对libi2c的userspace调用才能正常工作)

I googled a lot, but most cases are about how to use the I2C driver or how to activate GPIO pins in the sysfs, and I was able to do all of those. 我在Google上搜索了很多,但是大多数情况是关于如何使用I2C驱动程序或如何在sysfs中激活GPIO引脚的,我能够做到所有这些。

The libi2c is for userspace so I cannot call it here. libi2c用于用户空间,所以我不能在这里调用它。 I also know that opening a file(/dev/i2c-0) in kernel and reading or writing to it is not a good idea. 我也知道在内核中打开文件(/ dev / i2c-0)并对其进行读写不是一个好主意。 I am trying to understand what is the best way to handle this problem, without causing any concurrent access issues. 我试图了解什么是处理此问题的最佳方法,而又不会引起任何并发访问问题。

I would appreciate any ideas 我将不胜感激

PS - I don't have a deep understanding of how Linux kernel works, so sorry if my question is a little vague. PS- 我对Linux内核的工作方式没有深刻的了解,如果我的问题有点含糊,请您谅解。

Edit 1: based on @0andriy 's suggestion, I edited the DTS file and added the following to /arch/arm/boot/dts/my_dts_file.dts : 编辑1:根据@ 0andriy的建议,我编辑了DTS文件,并将以下内容添加到/arch/arm/boot/dts/my_dts_file.dts

/dts-v1/;
#include "imx28.dtsi"

/ {

// some definitions

apbx@80040000 {    
    i2c0: i2c@80058000 {
        pca8575: gpio@20 {
            compatible = "nxp,pca8575";
            reg = <0x20>;   // PCA8575PW Address -0-0-0
            gpio-controller;
            #gpio-cells = <2>;
        };
    };

    auart1: serial@8006c000 {
        pinctrl-names = "default";
        pinctrl-0 = <&auart1_2pins_a>;
        linux,rs485-enabled-at-boot-time;
        rs485-rts-delay = <0 0>;        // in milliseconds
        rts-gpios = <&pca8575 4 GPIO_ACTIVE_LOW>;
        rs485-rts-active-low;
        status = "okay";
    };

    auart2: serial@8006e000 {
        pinctrl-names = "default";
        pinctrl-0 = <&auart2_2pins_b>;
        linux,rs485-enabled-at-boot-time;
        rs485-rts-delay = <0 0>;        // in milliseconds
        rts-gpios = <&pca8575 5 GPIO_ACTIVE_LOW>;
        rs485-rts-active-low;
        status = "okay";
    };
};

// some definitions
};

and then rebuilt the kernel. 然后重建内核。 I also edited the mxs_auart_init_gpios function in the mxs-auart.c driver to print out the pin description of all the auart GPIOs at boot time. 我还编辑了mxs_auart_init_gpios -auart.c驱动程序中的mxs_auart_init_gpios函数,以在启动时打印所有auart GPIO的引脚说明。 but gpiod = mctrl_gpio_to_gpiod(s->gpios, i) is always NULL. 但是gpiod = mctrl_gpio_to_gpiod(s->gpios, i)始终为NULL。 the pca8575 GPIO controller is not added under /sys/class/gpio/ 未在/sys/class/gpio/下添加pca8575 GPIO控制器

root# ls /sys/class/gpio
export       gpiochip128  gpiochip64   unexport
gpiochip0    gpiochip32   gpiochip96

Edit 2: 编辑2:

auart1_2pins_a and auart2_2pins_b from the imx28.dtsi file : 来自imx28.dtsi文件的auart1_2pins_aauart2_2pins_b

auart2_2pins_b: auart2-2pins@1 {
reg = <1>;
fsl,pinmux-ids = <
        MX28_PAD_AUART2_RX__AUART2_RX
        MX28_PAD_AUART2_TX__AUART2_TX
    >;
    fsl,drive-strength = <MXS_DRIVE_4mA>;
    fsl,voltage = <MXS_VOLTAGE_HIGH>;
    fsl,pull-up = <MXS_PULL_DISABLE>;
};

auart1_2pins_a: auart1-2pins@0 {
    reg = <0>;
    fsl,pinmux-ids = <
            MX28_PAD_AUART1_RX__AUART1_RX
            MX28_PAD_AUART1_TX__AUART1_TX
        >;
    fsl,drive-strength = <MXS_DRIVE_4mA>;
    fsl,voltage = <MXS_VOLTAGE_HIGH>;
    fsl,pull-up = <MXS_PULL_DISABLE>;
};

I'm using kernel 4.14.13 我正在使用内核4.14.13

the figure below demonstrates what I'm trying to achieve : 下图演示了我要实现的目标: 在此处输入图片说明

I'm not familiar at all with your board so take this answer with a pinch of salt, but I've noticed some funny things on your files. 我对您的董事会完全不熟悉,因此请稍作调整,但我注意到您的文件中有一些有趣的事情。

First off, you need to define the I2C pin you want to use for toggling the direction inside the UART pinmux: 首先,您需要定义要用于在UART pinmux内部切换方向的I2C引脚:

auart2_2pins_b: auart2-2pins@1 {
reg = <1>;
fsl,pinmux-ids = <
        MX28_PAD_AUART2_RX__AUART2_RX
        MX28_PAD_AUART2_TX__AUART2_TX
        MX28_PAD_I2C0_SCL__I2C0_SCL
    >;
    fsl,drive-strength = <MXS_DRIVE_4mA>;
    fsl,voltage = <MXS_VOLTAGE_HIGH>;
    fsl,pull-up = <MXS_PULL_DISABLE>;
};

Make sure you double-check the pin name you want to use, I cannot be sure that is the right one. 确保您仔细检查要使用的引脚名称,但我不确定这是正确的名称。

Then, you seem to be missing the pinctrl for the I2C controller: 然后,您似乎缺少了I2C控制器的pinctrl

i2c0: i2c@80058000 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c0_pins_a>;
        status = "okay";

        pca8575: gpio@20 {
            compatible = "nxp,pca8575";
            reg = <0x20>;   // PCA8575PW Address -0-0-0
            gpio-controller;
            #gpio-cells = <2>;
        };
    };

I could not confirm your reg and your pin numbers but I'm assuming you took it from your board's documentation. 我无法确认您的reg和您的密码,但我假设您是从董事会文档中获取的。 If you didn't, make sure you find a reliable source for your hardware. 如果没有,请确保找到硬件的可靠来源。

Finally, I'm not sure why you want to have the RTS line active low, most transceivers have a DE/~RE input, which means you need to have the line active high to drive the bus. 最后,我不确定为什么要使RTS线路为低电平有效,大多数收发器都有DE /〜RE输入,这意味着您需要使线路为高电平来驱动总线。 Maybe your driver is different... 也许你的司机不一样...

What you are trying to do is documented to be working for other boards so I guess unless there is a bug you should be able to make it work. 您正在尝试做的事情被证明可以在其他主板上使用,所以我想除非有错误,您应该能够使它工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM