我正在尝试在Linux中使用真正的FTDI USB转串行接口,速度为1Mbaud (而不是通常的115200)。这一切都很好,但有时我似乎丢失了数据。当使用TIOCGICOUNT ioctl调用检查计数器时,我可以看到出现溢出错误(不是buf_overrun)。
在查看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中高速工作,请随时帮助我!
致以良好的问候,阿诺特
发布于 2019-09-21 14:41:45
我想我想通了。归根结底,这是一个真正的RX溢出,因为我的代码读取uart缓冲区的速度不够快。当我确保足够快地“读取”串行端口时,我可以获得恒定的Mbaud数据速率。我完全被误导的原因(以及发送了奇怪和意想不到的FTDI_RS_OE )我将在下面解释。
关于我使用的协议的一些注释。我在串行线上发送了一些“请求”包,并期望得到一个大的回复。(并在循环中执行此操作)。“我的bug”是,我希望远程设备能够快速响应,如果没有响应,就会停止处理。这个超时时间太短了,但是实际的回复还是进来了。然后,“某些”缓冲区溢出,导致RX溢出。
但是,这并不是很清楚。以下是一些微妙之处:
会发生什么情况
但事实证明并非如此。相反,我对这里发生的事情的最好猜测(我还没有分析/调试内核来验证这一点)是串行“节流”发生的。当这个640kB“变满”时,linux将向FTDI驱动程序发出一个“油门”回调。然后简单地使用设置标志的通用usb_serial_generic_throttle,并丢弃https://elixir.bootlin.com/linux/latest/ident/usb_serial_generic_read_bulk_callback中传入的urb数据。这将解释为什么当事件实际发生时没有“检测到”溢出,而当我重新启动读取操作时(例如,在1分钟不活动之后)突然检测到溢出。由于这种机制,FTDI芯片的内部缓冲区必须溢出,从而导致设置此FTDI_RS_OE标志,然后只有在再次禁用节流时才能真正正确地解析它。
所以总结:主要的问题在我身边,但是FTDI驱动程序没有正确地实现它的溢出计数器(它们只会“延迟”出现,甚至从来不会出现,这取决于用例),这很可能是由于linux的节流特性。
https://stackoverflow.com/questions/58008752
复制相似问题