[英]How to use I2C GPIO expander's pin instead of RTS to control the RS485 direction, in Linux AUART kernel driver?
我正在基于NXP(Freescale)的i.MX287处理器创建一个嵌入式系统。 我正在使用一个通过迷你PCIe连接器连接到我的评估板上的核心处理板。
UART 0、3、4用作RS232,而UART 1,2用作RS485。 核心板不在其引脚上提供RTS信号,因此我必须使用I2C GPIO扩展器中的引脚来控制RS485方向。 GPIO扩展器模块还用于控制板上的其他一些设备。
在用户空间中,我可以使用libi2c控制方向针,但是我的客户要求我将方向针控制放在UART驱动程序中。
问题:
1-如何与auart驱动程序中的i2c设备进行交互? (可能吗)
2-如果可能,那么如何防止i2c-0总线被内核阻塞? (我还需要对libi2c的userspace调用才能正常工作)
我在Google上搜索了很多,但是大多数情况是关于如何使用I2C驱动程序或如何在sysfs中激活GPIO引脚的,我能够做到所有这些。
libi2c用于用户空间,所以我不能在这里调用它。 我也知道在内核中打开文件(/ dev / i2c-0)并对其进行读写不是一个好主意。 我试图了解什么是处理此问题的最佳方法,而又不会引起任何并发访问问题。
我将不胜感激
PS-
编辑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
};
然后重建内核。 我还编辑了mxs_auart_init_gpios
-auart.c驱动程序中的mxs_auart_init_gpios
函数,以在启动时打印所有auart GPIO的引脚说明。 但是gpiod = mctrl_gpio_to_gpiod(s->gpios, i)
始终为NULL。 未在/sys/class/gpio/
下添加pca8575 GPIO控制器
root# ls /sys/class/gpio
export gpiochip128 gpiochip64 unexport
gpiochip0 gpiochip32 gpiochip96
编辑2:
来自imx28.dtsi
文件的auart1_2pins_a
和auart2_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>;
};
我正在使用内核4.14.13
我对您的董事会完全不熟悉,因此请稍作调整,但我注意到您的文件中有一些有趣的事情。
首先,您需要定义要用于在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>;
};
确保您仔细检查要使用的引脚名称,但我不确定这是正确的名称。
然后,您似乎缺少了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>;
};
};
我无法确认您的reg
和您的密码,但我假设您是从董事会文档中获取的。 如果没有,请确保找到硬件的可靠来源。
最后,我不确定为什么要使RTS线路为低电平有效,大多数收发器都有DE /〜RE输入,这意味着您需要使线路为高电平来驱动总线。 也许你的司机不一样...
您正在尝试做的事情被证明可以在其他主板上使用,所以我想除非有错误,您应该能够使它工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.