我正在创建一个基于 NXP(飞思卡尔)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 才能正常工作)

我在谷歌上搜索了很多,但大多数情况都是关于如何使用 I2C 驱动程序或如何激活 sysfs 中的 GPIO 引脚,而我能够完成所有这些。

libi2c 用于用户空间,所以我不能在这里调用它。我也知道在内核中打开文件 (/dev/i2c-0) 并读取或写入它不是一个好主意。我试图了解处理此问题的最佳方法是什么,而不会导致任何并发访问问题。

我会很感激任何想法

P.S. - 我对 Linux 内核的工作原理没有深入的了解,如果我的问题有点含糊,很抱歉。

编辑 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.c 驱动程序中的 mxs_auart_init_gpios 函数,以在启动时打印出所有 auart GPIO 的引脚描述。但是 gpiod = mctrl_gpio_to_gpiod(s->gpios, i) 始终为 NULL。 /sys/class/gpio/

下未添加 pca8575 GPIO Controller
root# ls /sys/class/gpio 
export       gpiochip128  gpiochip64   unexport 
gpiochip0    gpiochip32   gpiochip96 

编辑 2:

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>; 
}; 

我正在使用内核 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 Controller 的 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 输入,这意味着你需要让线路处于高电平状态才能驱动总线。也许您的驱动程序不同...

你正在尝试做的事情被记录为适用于其他董事会,所以我想除非有错误,否则你应该能够让它工作。


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!