一、BUG现象
今天公司设备出现一个问题,在RK3399上的USB上插着三个设备,分别是4G模块、二维码模块与身份证模块,在这三个设备同时插在设备上时再开机,会出现4G模块连不上网络的情况,无论怎么插拔4G模块都无法联网。而这时把二维码模块拔出,只留身份证模块与4G模块,并重启开机,则可以正常的上网,4G模块通信正常,此时再把二维码模块重新插回,也工作正常。
此时我非常的迷茫,甚至想跑路。。。。。。
二、分析原因
在冷静的分析一番后,我发现一个问题在二维码模块挂载后,无论怎么去挂载4G模块都是失败的,而只要是4G模块比二维码模块先挂载就不会有问题,初步的分析是二维码模块与4G模块的挂载冲突造成的。所以下面来分析这两个设备的挂载。
2.1 二维码模块
二维码模块在挂载后会在/dev
下生成ttyACM0
节点,ACM
并不是设备生成的,而是内核分配的名字含义如下:
USB CDC ACM(虚拟串口)
-
CDC-ACM
(Abstract Control Model
抽象控制模型)允许任何通信设备提供串行通信接口(例如发送和接收AT
命令的调制解调器设备)。该设备类型是在PSTN
(Public Switched Telephone Network
)中定义的。 -
CDC-ACM
驱动程序将USB设备作为虚拟调制解调器或虚拟COM
端口暴露给操作系统。驱动程序可以通过ACM
(通过不同通道分离数据和AT命令)或通过串行仿真(按原样传递AT命令和作为数据流的一部分)发送数据和AT
命令。
什么是ttyACM?
USB 实施者论坛组织已经描述了符合通信设备类 (CDC) 的设备应如何将自己呈现给 USB 主机。 USB 实现者论坛还指定了 CDC 子类应如何操作,包括那些旨在通过公共交换电话网络 (PSTN) 相互通信的设备。这些被称为调制解调器,因为数据在发送端经过调制操作,将比特转换为可以通过电话线传输的模拟信号,然后通过接收端的解调操作将模拟信号转换回原始位。
要与调制解调器讨论,主机 USB 驱动程序必须使用现有控制模型之一。例如,直接线路控制模型控制主机和调制解调器之间如何通过音频类接口交换数据,主机负责调制、解调、数据压缩(如V.42bis)和纠错(如如 V.42)。这种模型被一些USB软调制解调器使用,它们非常便宜,因为它们大多包含一个DSP芯片和一些放大和线路适配层。
另一个控制模型,恰当地命名为抽象控制模型或 ACM,让调制解调器硬件执行模拟功能,并要求它支持 ITU V.250(以前也称为 Hayes)命令集,无论是在数据流或作为单独的控制流通过通信类接口。当命令与数据流中的数据复用时,诸如 Hayes 302(也称为“1 sec +++ 1 sec”)或 TIES(没人记得)之类的转义序列必须允许主机将调制解调器放入命令模式。
在需要通过 USB 与计算机交换数据的支持 USB 的嵌入式微控制器上进行开发时,很容易使用几乎所有操作系统都支持的标准化通信方式。这就是为什么大多数人选择使用 ACM 实现 CDC/PSTN(您是否注意到 /dev/ttyACM0 的 Linux 内核驱动程序名为 cdc_acm?),因为它是交换原始数据的最简单方法。
但是强制性的 V.250 命令集呢?它几乎从未在此类设备中实现,但由于主机没有理由自行生成 V.250 命令,因此设备将永远不必回答它们。假装嵌入式设备是调制解调器是与其通信的最简单方式,即使它可能永远不会执行任何调制或解调任务。 Linux 不会知道该设备在撒谎,而是将其显示为 /dev/ttyS0。
源代码位置为cdc_acm.c
中:
在有ttyACM设备挂载后,就会调用到acm_probe()中
当处理完成后会就打印出ACM的编号。
2.2 4G模块
4G模块在内核中的显示为ttyUSBx
,
2.2.1什么是ttyUSB?
有时,嵌入式微控制器不带有硬件 USB 接口。虽然可以使用纯软件USB
堆栈,但 CPU
的额外限制和通常较小的存储空间通常会导致电路板设计人员包含专用的 UART
转 USB
桥接器。一些供应商,例如 FTDI
或 Prolific
,以几欧元的价格出售专用芯片。
这些供应商选择不向主机撒谎,让芯片宣布自己是 USB 调制解调器,而实际上它们不是。每个供应商都定义了自己的(通常是专有的)协议,其中的命令允许控制芯片的功能,例如设置波特率或控制用于实现硬件流控制的附加信号。
如果可行,Linux
会将具有相似功能的设备分组到相同的默认设备或接口名称下。例如,您计算机上的 UART
(如果有)将被命名为 /dev/ttyS0
和 /dev/ttyS1
,即使其中一个是传统的 16550
芯片,另一个是 MAX3100 SPI
控制的 UART
。同样,提供 UART-over-USB
功能的设备被命名为 /dev/ttyUSB0
、/dev/ttyUSB1
等,即使它们实际上使用不同的设备驱动程序。
也就是说ttyUSB
是uart
转USB
设备。
在drivers/usb/serial/bus.c中ttyUSB设备接入会进入此,并打印log:
三、处理方法
因为是二维码模块先挂载后导致4G模块连不上网络,所以就先时4G模块先行挂载,然后再挂载二维码模块,处理方法是在cdc_acm.c
的acm_probe
中添加延时函数:
实验成功,方法有点暴力。