工具/软件:
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:
尊敬的 Thomas:
您能否使用 Linux 串行测试(https://github.com/cbrake/linux-serial-test)来测试 UART 端口、看看是否仍然出现读取问题?
尊敬的 Bin:
(我与 Tom 合作、让董事会有问题。) 我运行了 linux-serial-test、如果我设置了较小的 TX 大小并添加了写入延迟、则会得到虚假读取、具体而言、linux-serial-test 似乎挂起(^C 可以取消它)。 通过 strace、它从读取中获得一个正向返回、然后旋转、调用 Read 并尽可能快地获取 EAGAIN。 输出:
root@clairvoyant-E00016:~# ./linux-serial-test -p /dev/ttyS1 -w 10 -a 100 Linux serial test app RS485 already enabled on port, ignoring delays if set /dev/ttyS1: No data received for 2.0s. /dev/ttyS1: No data received for 3.0s. /dev/ttyS1: No data received for 4.0s. /dev/ttyS1: No data received for 5.0s. /dev/ttyS1: No data received for 6.0s. /dev/ttyS1: No data received for 7.0s. /dev/ttyS1: No data received for 8.0s. /dev/ttyS1: No data received for 9.0s. /dev/ttyS1: No data received for 10.0s. /dev/ttyS1: No data received for 11.0s. /dev/ttyS1: No data received for 12.0s.
和转换时间附近的 strace 输出:
poll([{fd=3, events=POLLIN|POLLOUT|POLLNVAL|POLLRDNORM|POLLMSG|POLLRDHUP|0x4000}], 1, 1000) = 1 ([{fd=3, revents=POLLOUT}]) clock_gettime64(CLOCK_MONOTONIC, {tv_sec=36629, tv_nsec=900483111}) = 0 poll([{fd=3, events=POLLIN|POLLOUT|POLLNVAL|POLLRDNORM|POLLMSG|POLLRDHUP|0x4000}], 1, 1000) = 1 ([{fd=3, revents=POLLOUT}]) clock_gettime64(CLOCK_MONOTONIC, {tv_sec=36629, tv_nsec=901780314}) = 0 write(3, "\350\351\352\353\354\355\356\357\360\361", 10) = 10 poll([{fd=3, events=POLLIN|POLLOUT|POLLNVAL|POLLRDNORM|POLLMSG|POLLRDHUP|0x4000}], 1, 1000) = 1 ([{fd=3, revents=POLLOUT}]) clock_gettime64(CLOCK_MONOTONIC, {tv_sec=36629, tv_nsec=903770472}) = 0 poll([{fd=3, events=POLLIN|POLLOUT|POLLNVAL|POLLRDNORM|POLLMSG|POLLRDHUP|0x4000}], 1, 1000) = 1 ([{fd=3, revents=POLLIN|POLLOUT|POLLRDNORM}]) clock_gettime64(CLOCK_MONOTONIC, {tv_sec=36629, tv_nsec=904943217}) = 0 read(3, "llllllllllllllllllllllllllllllll"..., 1024) = 48 read(3, 0xbebd570c, 1024) = -1 EAGAIN (Resource temporarily unavailable) read(3, 0xbebd570c, 1024) = -1 EAGAIN (Resource temporarily unavailable) read(3, 0xbebd570c, 1024) = -1 EAGAIN (Resource temporarily unavailable) read(3, 0xbebd570c, 1024) = -1 EAGAIN (Resource temporarily unavailable) read(3, 0xbebd570c, 1024) = -1 EAGAIN (Resource temporarily unavailable) read(3, 0xbebd570c, 1024) = -1 EAGAIN (Resource temporarily unavailable) read(3, 0xbebd570c, 1024) = -1 EAGAIN (Resource temporarily unavailable)
发生这种情况时、没有来自 dmesg 或 journalctl 的输出。
运行 linux-serial-test 时、除了端口之外没有其他参数、并添加短写入但不添加延迟、反之亦然、似乎可以按预期工作、至少要持续几分钟。
尊敬的 Owen:
在这个 Linux 串行测试中、您如何知道发生了虚假读取? 通过以下 strace log?
读取(3、"llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
如何在硬件中配置 AM335x UART1端口? 已连接 RS485收发器、但没有与此收发器连接?
如何在内核器件树中配置此 UART 端口?
尊敬的 Bin:
对所有点都是正确的。 使用 linux-serial-test、我依靠 strace 来显示读取、因为它在 EAGAIN 循环中被"卡住"。 为了进一步验证,我刚刚修补了 linux-serial-test.c 以跳过在 EAGAIN 上的继续,我得到了这个:
root@clairvoyant-E00016:~# ./linux-serial-test-noeagin -p /dev/ttyS1 -w 10 -a 100 -R Linux serial test app RS485 already enabled on port, ignoring delays if set /dev/ttyS1: No data received for 2.0s. /dev/ttyS1: No data received for 3.0s. /dev/ttyS1: No data received for 4.0s. /dev/ttyS1: No data received for 5.0s. Read 48 bytes /dev/ttyS1: No data received for 2.0s. /dev/ttyS1: No data received for 3.0s. /dev/ttyS1: No data received for 4.0s. /dev/ttyS1: No data received for 5.0s. /dev/ttyS1: No data received for 6.0s. /dev/ttyS1: No data received for 7.0s. /dev/ttyS1: No data received for 8.0s. /dev/ttyS1: No data received for 9.0s. /dev/ttyS1: No data received for 10.0s. /dev/ttyS1: No data received for 11.0s. /dev/ttyS1: No data received for 12.0s. Read 48 bytes /dev/ttyS1: No data received for 2.0s. /dev/ttyS1: No data received for 3.0s.
同样正确的连接:我们已将 UART1连接到 TI ISO1420隔离式 RS485收发器、没有任何连接到收发器。 原理图如下:
对于设备树、UART1定义为:
&uart1 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&uart1_pins>; rts-gpios=<&gpio2 5 GPIO_ACTIVE_HIGH>; dtr-gpios=<&gpio2 3 GPIO_ACTIVE_LOW>; rs485-rts-active-high; rs485-rts-delay = <0 0>; linux,rs485-enabled-at-boot-time; };
其中参考了 uart1引脚:
&am33xx_pinmux { uart1_pins: pinmux_uart1_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* (D18) uart1_rxd.uart1_rxd */ AM33XX_IOPAD(0x984, PIN_OUTPUT | MUX_MODE0) /* (C19) uart1_txd.uart1_txd */ AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE7) /* rs485_rxe (W9) gpmc_oen_ren.gpio2[3] */ AM33XX_IOPAD(0x89C, PIN_OUTPUT | MUX_MODE7) /* rs485_txe (V8) gpmc_be0n_cle.gpio2[5]) */ >; }; uart2_pins: pinmux_uart2_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x92c, PIN_INPUT | MUX_MODE1) /* (N19) gmii1_txclk.uart2_rxd */ AM33XX_IOPAD(0x930, PIN_OUTPUT | MUX_MODE1) /* (M19) gmii1_rxclk.uart2_txd */ >; }; };
尊敬的 Bin:
我们移除了器件树中的电阻器和 RS485部分、不再看到48字节读取。 我们在重新启动后立即运行的第一次运行时看到了1字节读取、但在重新启动后没有看到。 linux-serial-test 的输出:
root@clairvoyant-E0000B:~# ./linux-serial-test -p /dev/ttyS1 -w 10 -a 100 -R Linux serial test app /dev/ttyS1: No data received for 2.0s. /dev/ttyS1: No data received for 3.0s. /dev/ttyS1: No data received for 4.0s. /dev/ttyS1: No data received for 5.0s. /dev/ttyS1: No data received for 6.0s. /dev/ttyS1: No data received for 7.0s. /dev/ttyS1: No data received for 8.0s. /dev/ttyS1: No data received for 9.0s. <...trimmed...> /dev/ttyS1: No data received for 1152.2s. /dev/ttyS1: No data received for 1153.2s. /dev/ttyS1: No data received for 1154.2s. ^CTerminating ... /dev/ttyS1: count for this session: rx=0, tx=114320, rx err=0 /dev/ttyS1: TIOCGICOUNT: ret=0, rx=1, tx=196320, frame = 0, overrun = 0, parity = 0, brk = 1, buf_overrun = 0 Exit handler: Cleaning up ...
在我看来、这必须与 RS485功能相关、并在软件中的某个位置、因为收发器的 RX 线上没有活动。
抱歉、我打算在最后一个帖子中包含修改后的设备树。 非 RS485 UART1看起来像:
&am33xx_pinmux { uart1_pins: pinmux_uart1_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE7) /* rs485_rxe (W9) gpmc_oen_ren.gpio2[3] */ AM33XX_IOPAD(0x89C, PIN_OUTPUT | MUX_MODE7) /* rs485_txe (V8) gpmc_be0n_cle.gpio2[5]) */ >; }; uart2_pins: pinmux_uart2_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x92c, PIN_INPUT | MUX_MODE1) /* (N19) gmii1_txclk.uart2_rxd */ AM33XX_IOPAD(0x930, PIN_OUTPUT | MUX_MODE1) /* (M19) gmii1_rxclk.uart2_txd */ >; }; }; &uart1 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&uart1_pins>; };
尊敬的 Bin:
与之前一样、在电阻器仍移除但原始器件树后、它会生成虚假 RX 数据。
root@clairvoyant-E0000B:~# ./linux-serial-test-noeagin -p /dev/ttyS1 -w 10 -a 100 -R Linux serial test app RS485 already enabled on port, ignoring delays if set /dev/ttyS1: No data received for 2.0s. /dev/ttyS1: No data received for 3.0s. /dev/ttyS1: No data received for 4.0s. /dev/ttyS1: No data received for 5.0s. /dev/ttyS1: No data received for 6.0s. /dev/ttyS1: No data received for 7.0s. /dev/ttyS1: No data received for 8.0s. /dev/ttyS1: No data received for 9.0s. /dev/ttyS1: No data received for 10.0s. /dev/ttyS1: No data received for 11.0s. /dev/ttyS1: No data received for 12.0s. /dev/ttyS1: No data received for 13.0s. /dev/ttyS1: No data received for 14.0s. /dev/ttyS1: No data received for 15.0s. /dev/ttyS1: No data received for 16.0s. /dev/ttyS1: No data received for 17.0s. /dev/ttyS1: No data received for 18.0s. /dev/ttyS1: No data received for 19.0s. /dev/ttyS1: No data received for 20.0s. /dev/ttyS1: No data received for 21.0s. /dev/ttyS1: No data received for 22.0s. Read 48 bytes /dev/ttyS1: No data received for 2.0s. /dev/ttyS1: No data received for 3.0s. /dev/ttyS1: No data received for 4.0s. /dev/ttyS1: No data received for 5.0s. /dev/ttyS1: No data received for 6.0s. /dev/ttyS1: No data received for 7.0s. /dev/ttyS1: No data received for 8.0s. /dev/ttyS1: No data received for 9.0s. /dev/ttyS1: No data received for 10.0s. Read 48 bytes
删除"linux、RS485-enabled-at-boot-time"行似乎可以消除问题。 我在 linux-serial-test 命令行中添加了"--RS485 1"参数以尝试确保它仍处于 RS485模式;它运行~10分钟而未接收到 RX 数据。 (我此时终止了它;问题似乎在前1到30秒内出现。) 移除电阻器后、整个电路板上仍然如此。
我还尝试移除(一次移除一次) RS485-RTS 高电平有效和 RS485-RTS 延迟线路;这没有什么区别、它们仍然显示了虚假读取。
所以这个问题似乎与 RS485支持启动时的参数有关;这似乎很令人惊讶、因为它添加了 SER_RS485_enabled 标志(我正在查看9.01.00.001 SDK 中的 serial_core.c 第3445行)、但证据很清楚。
星期一、我将尝试删除 RS485 enabled-at-boot-time 参数、然后让我们的用户空间应用程序启用 RS485。
感谢您的所有测试。
因此问题似乎与启用了 RS485-at-boot-time 参数有关;
在得出结论之前、我们还需要再进行几次测试。
您能否在器件树中保留"RS485-enabled-at-boot-time"、但删除"dtr-GPIO"及其引脚多路复用? 我不确定内核 UART 驱动程序是否处理了收发器 RE 引脚的 DTR 引脚、我记得我在驱动程序中读取了任何相关代码。
我已从器件树中删除了这条线、如果我完全按照 Linux 串行测试的功能进行操作、那么这条线在我的测试应用中似乎能按预期工作(没有观察到虚假数据)。 添加了初始化代码:
struct serial_rs485 rs485_settings = {0}; rs485_settings.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX; int ioctl_result = ioctl(fd, TIOCSRS485, &rs485_settings); if (ioctl_result < 0) { perror("ioctl"); return 2; }
奇怪的是、这组确切的标志似乎是必需的;我最初尝试只是SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND
(省略SER_RS485_RX_DURING_TX
、因为我们不需要全双工)、但这确实会导致仍然存在虚假数据。