ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ubuntu下找不到ttyUSB0?嵌入式Linux串口调试排查指南

Ubuntu下找不到ttyUSB0?嵌入式Linux串口调试排查指南 把开发板接到Ubuntu主机上插上USB线打开串口调试助手结果发现/dev下面压根没有ttyUSB0连个影子都找不到。刚接触嵌入式Linux的朋友十有八九会在这个环节卡住我自己也在这上面折腾过不少时间。这个问题的根源通常不是板子坏了而是USB转串口芯片的驱动、内核枚举或者权限配置出了岔子。这篇就是针对“开发板串口连上Ubuntu后找不到设备文件”这件事把排查思路和解决方案从头到尾捋一遍适合正在用STM32、全志T113、i.MX6ULL这类开发板做开发却卡在串口识别这一步的读者。1. 先搞清楚“设备文件”到底是怎么来的1.1 一根USB线背后的角色分工很多新手容易把“开发板和电脑用USB线连起来”理解成插上就能通实际上这里面有一个容易被忽略的中间环节。绝大多数开发板上自带的串口物理电平是TTL电平通常是3.3V或5V而电脑主板的USB口是USB差分信号两者根本不能直接对话。所以板子上通常会有一颗USB转串口芯片常见的型号包括CH340、CH341、CP2102、CP210x系列、FT232等也有不少新板子用CH9102这类高速型号。这颗芯片的作用就是把板子的UART TX/RX信号转换成USB协议再通过USB线送到电脑。换句话说电脑识别到的不是“开发板”而是这颗USB转串口芯片。系统在枚举USB设备时会根据芯片的VID厂商ID和PID产品ID去匹配对应的驱动程序匹配成功后再注册一个字符设备节点也就是我们常说的/dev/ttyUSB0或者/dev/ttyACM0。如果这一步某个环节没接通那你在/dev下自然看不到设备文件。1.2 为什么偏偏是ttyUSB0和ttyACM0这里顺便把设备名的命名规则说清楚因为很多人拿到设备后第一反应是找ttyS0那是错的。ttyS是主板原生串口也就是物理COM口对应的设备节点和USB转出来的串口是两套体系。USB转串口芯片在Linux内核里走的通常是USB子系统注册出来的设备名是ttyUSB比如ttyUSB0、ttyUSB1对应的驱动框架是usb-serial。而ttyACM*则是另一种情况它走的是内核里的USB ACMAbstract Control Model驱动。这个驱动最开始主要是为USB Modem设计的但很多单片机开发板用USB直接虚拟串口时比如STM32的USB CDC类也会被识别成ttyACM0。所以判断设备属于哪一类直接看设备名就能猜个大概ttyUSB开头基本都是外置USB转串口芯片ttyACM开头往往是芯片内置USB控制器虚拟出来的串口。这两种设备在权限配置和驱动处理上略有差别后面会具体说。2. 三步定位到底是哪一层断了2.1 第一步看USB总线上的枚举结果设备文件没出现先别急着装驱动第一步应该先确认USB总线层面有没有认出这颗芯片。把板子通过USB线接到电脑后在终端执行lsusb这个命令会列出当前USB总线上所有设备的VID和PID信息以及厂商名称如果能识别的话。正常情况下的输出大概是这个样子$ lsusb Bus 001 Device 008: ID 1a86:7523 QinHeng Electronics CH340 serial converter看到1a86:7523这行说明USB枚举已经成功CH340芯片被系统正常识别了。1a86就是沁恒的厂商ID7523对应CH340这个型号。如果输出里压根没有新设备出现那就说明USB物理链路有问题需要去排查线材、USB口或者芯片供电。如果lsusb能看到设备但/dev下没有ttyUSB节点问题基本就锁定在驱动匹配环节。如果lsusb连设备都看不到则要从硬件连接开始查起。很多时候是数据线的问题——有些MicroUSB线只能充电不能传数据这种线在开发板上非常常见换根线往往就好了。2.2 第二步确认内核驱动与设备名lsusb正常之后下一步用dmesg查看内核日志。执行$ dmesg | tail -n 30插入板子后如果驱动加载成功日志里会出现类似下面的内容usb 1-2: new full-speed USB device number 8 using xhci_hcd usb 1-2: New USB device found, idVendor1a86, idProduct7523, ... usb 1-2: New USB device strings: Mfr1, Product2, SerialNumber3 usbcore: registered new interface driver ch341 usbserial: USB Serial support registered for ch341-uart ch341-uart now attached to ttyUSB0倒数第二行的ch341就是内核为这颗芯片加载的驱动模块名最后一行清楚标明了设备节点注册到了ttyUSB0。如果你的日志里有类似信息那设备文件其实已经生成了问题大概率出在权限或者你查看的时机不对。如果lsusb能看到设备但dmesg里没有任何与usbserial、ch341、cp210x、ftdi相关的输出说明内核没有加载对应的驱动模块。这时候可以手动尝试$ sudo modprobe ch341加载完再执行dmesg看有没有新日志或者直接ls /dev/ttyUSB*确认节点是否出现。不同芯片对应模块名不一样这个下一节详细列个对照表。2.3 第三步检查串口占用与权限/dev/ttyUSB0已经存在但串口工具打不开或者打开后一片空白这种情况多半是权限或占用问题。先看设备节点权限$ ls -l /dev/ttyUSB0 crw-rw---- 1 root dialout 188, 0 5月 30 10:23 /dev/ttyUSB0默认属主是root组是dialout普通用户没有读写权限。如果不加sudo直接打开串口就会提示Permission denied。解决办法是把当前用户加进dialout组$ sudo usermod -aG dialout $USER执行完后需要重新登录一次才能生效。注意这个操作在Ubuntu 20.04及之后几乎所有版本上通用但如果你用的是其他发行版组名可能不一样比如有些发行版用的是uucp或者lock组。Ubuntu桌面版和服务器版的默认组策略也有些细微差异但dialout是主流选择。另外还有一种情况就是串口被别的进程占用了。用sudo lsof /dev/ttyUSB0或者sudo fuser /dev/ttyUSB0查一下谁在占用然后把进程关掉再试。3. 驱动不是万能的但缺了它真不行3.1 主流USB转串口芯片与内核模块对照市面上常见的USB转串口芯片就那么几种Linux内核从4.x时代开始基本就全部内置了对应的驱动模块。我整理了一张表覆盖了主流芯片对应的模块名和典型VID方便排查时对照芯片型号内核模块典型VID:PID备注CH340 / CH341ch3411a86:7523最常见的国产芯片CH9102ch3411a86:55d4高速版本CP2102 / CP210xcp210x10c4:ea60硅谷老牌方案FT232 / FT2232ftdi_sio0403:6001FTDI经典款PL2303pl2303067b:2303老芯片内核版本兼容性一般CH9350ch93501a86:e010带HID功能需要单独处理STM32 USB CDCcdc_acm0483:5740设备是ttyACM*排查时直接用lsusb对照这张表就能知道系统是否识别到了芯片以及该用哪个模块去验证。3.2 手动加载模块与内核编译的取舍在绝大多数情况下Ubuntu自带的官方内核已经包含了上述所有模块不需要额外安装驱动。这也和Windows平台不一样——Windows上装CH340驱动是常规操作但Linux上通常免驱因为驱动都在内核里了。不过有两个例外情况需要手动介入。第一种情况是内核模块虽然存在但因为某种原因没有被自动加载。这时候手动modprobe即可。但要注意modprobe只能解决“模块存在但未加载”的问题。如果模块本身就不存在比如你用的内核是裁剪过的嵌入式板载系统、或者自己编译内核时没勾选USB串口支持那就需要重新编译内核或者单独编译驱动模块。第二种情况就是前面提到过的高通、瑞芯微等平台方案中有些自定义USB转串口芯片并不在标准内核驱动列表里这时候需要到厂商官网找驱动源码自行编译。比如某些国产开发板附带的USB转串口工具芯片是定制版CH340虽然VID还是1a86但PID可能不在驱动默认支持列表里这时候不能直接modprobe ch341而要在ch341.c源码里把对应的PID添加进去重新编译模块。这里额外提一个编译驱动的经验内核模块编译非常依赖内核头文件版本编译前一定要确保uname -r输出的版本和/usr/src/linux-headers-$(uname -r)目录存在且匹配。很多人在Ubuntu上编译驱动失败原因就是提前装了linux-headers-generic但版本和当前内核不一致。3.3 权限与udev规则一次配到位前面提到的usermod -aG dialout是临时解法换个电脑或换用户又要重新设置。对于团队共用开发机、或者频繁插拔不同开发板的场景更推荐写一条udev规则来固定设备权限和名称。在/etc/udev/rules.d/下新建一个规则文件比如99-usb-serial.rules内容如下KERNELttyUSB[0-9]*, MODE0666保存后执行$ sudo udevadm control --reload-rules $ sudo udevadm trigger这样做的效果是所有ttyUSB设备节点权限自动变成666任何用户都能直接读写不用每次sudo。但要注意这个规则没有限制具体设备如果你电脑上同时插着多个USB转串口设备它们都会获得这个权限。如果你希望只对特定设备生效可以按VID过滤比如SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}7523, MODE0666另外还可以用udev规则给设备创建一个固定别名。比如多个开发板同时插着ttyUSB0和ttyUSB1的顺序可能随插拔顺序变化这对自动化脚本来说非常痛苦。通过udev规则根据设备序列号创建软链接可以解决这个问题SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{serial}0001, SYMLINKttyBoardA, MODE0666之后在脚本里直接用/dev/ttyBoardA访问再也不担心节点漂移。4. 虚拟机、开发板端配置与进阶坑点4.1 虚拟机USB直通的三个细节如果你的Ubuntu是跑在VMware或者VirtualBox里的虚拟机问题会多一层。虚拟机的USB直通有几处容易踩坑的地方。第一确认虚拟机设置里USB控制器启用了哪个版本。很多开发板是USB 2.0全速设备但虚拟机默认可能只开启USB 3.0控制器导致设备识别异常。建议同时勾选USB 2.0和USB 3.0控制器。VMware Workstation里依次点击“虚拟机设置”-“USB控制器”把“USB兼容性”设为USB 2.0甚至更低的兼容模式很多时候问题直接解决。第二插上板子后会弹窗问你是连接到主机还是连接到虚拟机一定要选虚拟机。如果不小心点了“连接到主机”那设备就被宿主机占用了。第三连接成功后在虚拟机里执行lsusb确认设备是否在虚拟机内可见。如果lsusb里能看到设备但/dev下没有节点回到前面第2节的驱动排查流程。如果lsusb里看不到多半是直通没生效重新插拔USB线、或者重置一下虚拟机的USB控制器驱动多数能解决。4.2 开发板端的设备树与串口节点这个问题排查到一定深度之后有些读者可能会把“Ubuntu主机找不到ttyUSB”和“开发板启动后串口没有输出”混为一谈这两个其实是完全不同的链路。前者是主机侧的问题后者则涉及开发板端的设备树Device Tree配置以及U-Boot的启动参数。如果你是“开发板上电后串口终端完全无输出”那需要检查的是开发板端的设备树文件里UART节点是否被正确使能以及U-Boot的console参数是否指向了正确的串口。比如i.MX6ULL这类板子U-Boot环境变量里的consolettymxc0,115200就对应着板子上的UART1。如果这个参数和实际接线不一致或者设备树里该UART节点被disable那终端就什么都看不到。常见的一个坑是板卡厂商提供的设备树文件配置完整但你自己改了设备树之后UART节点引脚被复用成了GPIO导致串口物理上不通。排查方法很简单恢复到出厂设备树文件试一次能通就说明是你的配置问题慢慢对比差异即可。4.3 那些让人崩溃的“假·串口”最后分享几个我实际工作中遇到的“看似驱动没问题但死活不出设备节点”的特殊场景给读者提个醒。第一个是供电不足。有些开发板USB转串口芯片的供电和板子主控共用板子功耗大、供电电流不够的时候USB芯片会反复复位表现就是lsusb能看到设备一闪一闪的或者频繁掉线。用外部电源给板子独立供电往往能解决。第二个是劣质USB hub。带供电的劣质hub在传输USB信号时可能会有电平畸变串口芯片偶尔能被枚举到但dmesg里伴随大量的usb 1-1: device descriptor read/64, error -110这类报错。这种报错高度疑似hub或者线材问题而不是驱动问题。直接把板子插到主机背后的USB口上绕开hub再试是最快的验证方法。第三个是内核版本与芯片兼容性的问题。比如PL2303这颗老芯片内核从5.x开始对部分TA即早期版本芯片进行了更严格的校验导致某些芯片被拒绝识别dmesg里会明确提示PL2303: unknown chip, please report。这属于芯片本身的克隆问题无解只能换芯片。第四个是串口工具本身的问题。如果lsusb、dmesg、/dev节点全部正常但minicom或者串口助手打开后没有任何反应检查一下工具的波特率、数据位、停止位、流控配置是否匹配开发板的默认串口参数。很多开发板默认是115200/8N1但流控是否开启要看具体板子有一些板子在出厂Bootloader阶段会开启硬件流控导致半双工通信不正常。还有一个非常容易忽略的细节如果你用的是Windows和Ubuntu双系统在Windows下安装过厂商提供的驱动那么重启到Ubuntu后某些国产USB转串口芯片会残留D2XX驱动模式FTDI的D2XX模式就经常这样。这种模式下芯片不会注册为ttyUSB设备。解决办法是把芯片切回VCP模式通常需要用到厂商的配置工具或者在Windows下卸载驱动后重新在Ubuntu里插拔。这些年遇到类似问题的板子不少提醒读者留意。在我实际调试过的项目里大概有七成“找不到设备文件”的情况是出在物理链路或者权限配置上真正的驱动缺失反而少见。所以排查的时候建议按照本文的顺序来先看lsusb确认USB枚举再看dmesg确认驱动加载最后检查/dev节点权限。一步一步来不要第一步就钻进驱动源码里出不来了。
返回列表