解决Ubuntu 18.04 minicom 不支持 1500000 波特率的问题

最近使用 Ubuntu 18.04 作为台式机的办公系统,需要使用串口调试功能,于是安装了 minicom, 但是配置波特率的时候发现无法配置高于 1000000 以上波特率。

$ sudo stty -F /dev/ttyUSB0 1500000
stty: /dev/ttyUSB0: unable to perform all requested operations

谷歌了许久也没找到方法,只能自己探索下了。

问题排查

为此,我测试了以下几种情况:

  1. 在笔记本 win10 上可以正常配置,排除串口线和串口工具问题
  2. 在笔记本 ubuntu 16.04 上可以正常配置
  3. 在台式机的 win10 系统上可以,排查台式机USB接口问题
  4. 在台式机的 ubuntu 16.04 虚拟机上正常配置,说明与 ubuntu 18.04 系统有关
  5. 在台式机的 ubuntu 18.04 上使用ch341驱动,可以正常配置,说明是 cp210x 驱动问题

最终确定是 ubuntu 18.04cp210x 驱动不支持高波特率的配置,这里涉及到两个因素:

  1. ubuntu 版本号 18.04
  2. cp210x 驱动

解决方案

那么怎么解决呢,总不可能重装个 ubuntu 16.04 的系统吧,所以我首先想到的是替换驱动。把 ubuntu 18.04 的驱动替换为 16.04 的驱动,但是失败了。

$ sudo insmod cp210x.ko
insmod: ERROR: could not insert module cp210x.ko: Invalid module format

提示格式无效,搜索发现 insmod 会比对内核模块的版本号。所以直接替换是不可行的,那就只能重新编译新的 .ko 文件。

先把 ubuntu 16.04 所在内核版本的 cp210x.c 源码下载下来,可以从 这里 下载。

然后编写Makefile, 与 cp210x.c 放在同一个目录。

serial
├── cp210x.c
└── Makefile
obj-m += cp210x.o

KDIR := /lib/modules/`uname -r`/build
PWD:=`pwd`
all:
        make -C $(KDIR) M=$(PWD) modules
clean:
        rm -f *.ko *.o *.symvers *.cmd *.cmd.o

执行 make 就编译好了。

$ make
make -C /lib/modules/`uname -r`/build M=`pwd` modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-73-generic'
  CC [M]  /home/litreily/workspace/serial/cp210x.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC [M]  /home/litreily/workspace/serial/cp210x.mod.o
  LD [M]  /home/litreily/workspace/serial/cp210x.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-73-generic'
$ ls
cp210x.c  cp210x.ko  cp210x.mod     cp210x.mod.c   cp210x.mod.o  
cp210x.o  Makefile   modules.order  Module.symvers

然后替换掉原有的 .ko 文件,最好把旧的备份下, 以防万一。

sudo cp /lib/modules/`uname -r`/kernel/drivers/usb/serial/cp210x.ko cp210x.ko.backup
sudo cp cp210x.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial/cp210x.ko

最后,重新加载 cp210x.ko, 执行前先拔掉所以串口线。

sudo rmmod cp210x
sudo insmod cp210x

正常加载完成就说明成功了。

测试

最后来测试下,修改波特率为1500000.

$ sudo stty -F /dev/ttyUSB0 1500000
$ sudo stty -F /dev/ttyUSB1 
speed 1500000 baud; line = 0;
-brkint -imaxbel

大功告成!有兴趣的可以去对比下驱动源码,看看为啥 5.4.0 的内核为啥不支持高波特率的配置。

reference