我正在尝试使用真正的FTDI USB在Linux中以1兆波特(而不是通常的115200)进行串行传输。这一切都很好,但有时我似乎失去了数据。当使用TIOCGICOUNT ioctl调用检查计数器时,我可以看到出现溢出错误(而不是buf_overflow)。
在查找FTDI-linux驱动程序的源代码(https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ftdi_sio.c)时,当芯片发送包含FTDI-RS-OE错误标志的USB数据包时,就会执行此操作。
(作为参考,当我使用完全相同的用户空间应用程序,但使用完全不同的串行设备(imx6 mxc)时,我不会得到这些错误。这真的是FTDI驱动程序特有的东西)
对此我发现很少,奇怪的是,windows驱动程序似乎没有遇到这个问题。如果有人让这些FTDI芯片在linux中高速运行,请随时帮助我!
谨致问候,
阿诺
最佳答案
我想我明白了。归根结底,这是一个真正的RX溢出,因为我的代码读uart缓冲不够快。当我确保足够快地“读取”串行端口时,我可以获得恒定的Mbaud数据速率。我完全误入歧途的原因(以及奇怪和出乎意料的FTDI-RS-OE被发送)我将在下面解释。
关于我正在使用的协议的一些注释。我在串行线路上发送一些“请求”数据包,希望得到一个大的答复。(并在循环中这样做)。”我的错误“是我希望远程设备能很快回复,如果不停止处理的话。这个超时时间太短了,但实际的回复还是出现了。”一些“缓冲区溢出,导致RX溢出。
但是,这不是很清楚。一些微妙之处:
rx溢出计数器仅在下一次uart read syscall时递增(例如,几分钟后,如果我的代码进入某个空闲状态)(不是在实际问题发生后立即递增,这非常令人困惑)
我的假设是,就像imx6驱动程序一样,如果输入的数据是可用的,linux内核总是简单地为USB设备提供服务。数据将被发送到640kB的缓冲区(定义为https://elixir.bootlin.com/linux/v4.9.192/source/drivers/tty/tty_buffer.c)。在imx6驱动程序中,可以清楚地看到如果缓冲区溢出会发生什么情况
但事实并非如此。相反,我对这里发生的事情(我还没有分析/调试内核来验证这一点)的最佳猜测是发生了串行“抛出”。当这个640kB已满时,linux将向FTDI驱动程序发出一个“throttle”回调。然后简单地使用通用usb串行通用油门,它设置一个标志,并在https://elixir.bootlin.com/linux/latest/ident/usb_serial_generic_read_bulk_callback中丢弃传入的urb数据。这可以解释为什么在事件实际发生时没有“检测到”溢出,但在(例如,在1分钟不活动后)我重新启动读取操作时突然检测到溢出。由于这个机制,FTDI芯片的内部缓冲区必须溢出,因此需要设置这个FTDI RS_OE标志,然后在再次禁用throtteling时才实际正确解析该标志。
所以结论:主要问题在我这边,但是FTDI驱动程序没有正确地实现它的溢出计数器(它们只显示“迟到”或者根本不显示,这取决于用例),因为很可能是linux的throttleing特性。
关于linux - 1Mbaud上的Linux FTDI USB到串行溢出错误FTDI_RS_OE,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58008752/