陵水黎族自治县网站建设_网站建设公司_Python_seo优化
2025/12/24 5:44:35 网站建设 项目流程

手把手教你编译Linux下的CH340驱动:从零开始,不靠包管理器也能用串口

你有没有遇到过这种情况:手里的开发板插上电脑,ls /dev/tty*死活看不到/dev/ttyUSB0
dmesg 一查,满屏都是unknown USB device或者no such device……
而你用的不过是常见的 Arduino Nano CH340 版、ESP-12F 模块或者某宝十块钱包邮的 USB 转 TTL 线——核心芯片正是CH340

别急,这多半不是硬件坏了,而是你的 Linux 系统里缺了那个关键的小东西:ch34x 驱动模块

更糟的是,如果你用的是老旧发行版、定制嵌入式系统,甚至没网的工控机,想靠apt installyum install安装驱动?根本行不通。

那怎么办?总不能每次调试都换台电脑吧?

答案是:自己动手,编译一个.ko文件,把驱动“种”进内核里。

这篇文章不讲虚的,也不复制粘贴手册。我会带你一步步从源码开始,完成 CH340 驱动的获取、编译、安装和验证全过程。全程不需要联网下载额外包(除了源码),适合离线环境部署,也帮你真正搞懂 Linux 内核模块是怎么跑起来的。


为什么 CH340 在 Linux 上经常“失灵”?

我们先来理清楚一个问题:为什么 FTDI 和 CP210x 几乎即插即用,而 CH340 却常常要手动折腾?

简单说,就一句话:

CH340 不是标准的 CDC ACM 设备。

什么意思?

大多数现代 USB 转串芯片(比如 FT232RL、CP2102)遵循 USB 组织定义的CDC ACM(Communication Device Class - Abstract Control Model)标准。这类设备一旦插入,Linux 内核自带的cdc-acm驱动就会自动识别并绑定,立刻生成/dev/ttyACM0/dev/ttyUSB0

但 CH340 不走寻常路。它使用的是厂商自定义类(bInterfaceClass = 0xFF),不属于任何标准类别。这就意味着:必须有一个专门写给它的驱动程序才能工作。

这个驱动就是ch34x.ko

好消息是,从 Linux 内核4.10+ 开始,官方已经将ch34x驱动合并进了主线代码树。所以如果你用的是较新的 Ubuntu、Debian、Fedora,大概率插上去就能用。

坏消息是:
- 很多国产开发板配套的镜像基于老内核(如 3.18、4.4)
- 某些裁剪过的嵌入式系统为了精简体积,直接去掉了ch34x模块
- Secure Boot 启用后,第三方模块加载受限

这些情况都会导致你明明插了设备,系统却“视而不见”。

这时候,你就得自己动手丰衣足食了。


第一步:确认问题出在驱动,而不是别的地方

在动手前,先做一次快速诊断,避免白忙一场。

1. 插上设备,看内核日志

dmesg | tail -15

如果看到类似输出:

usb 1-1: new full-speed USB device number 5 using xhci_hcd usb 1-1: New USB device found, idVendor=1a86, idProduct=7523 usb 1-1: Product: USB2.0-Serial usb 1-1: Manufacturer: wch.cn

恭喜你,USB 层已经识别成功!VID 是1a86,PID 是7523—— 这正是 CH340G 的标志性参数。

但如果下面没有紧接着出现:

usbcore: registered new interface driver ch34x usbserial: USB Serial support registered for ch34x ch34x ttyUSB0: ch34x converter now attached

那就说明:驱动没加载。

2. 检查是否已有 ch34x 模块

运行:

lsmod | grep ch34x

如果有输出,说明模块已加载。如果没有,再查一下系统有没有这个模块文件:

find /lib/modules/$(uname -r) -name "ch34x.ko*"

如果找不到,那就只能自己编译了。


第二步:准备编译环境

要编译内核模块,你需要三样东西:

  1. 当前运行内核的头文件(headers)
  2. 构建工具链(make, gcc)
  3. 驱动源码

我们一个个来。

1. 安装内核头文件(最关键!)

模块编译必须与当前运行的内核版本完全匹配。否则会出现Unknown symbol in moduleModule version mismatch错误。

查看当前内核版本:

uname -r # 输出示例:5.4.0-42-generic

根据你的发行版安装对应的头文件包:

发行版命令
Ubuntu/Debiansudo apt install linux-headers-$(uname -r)
CentOS/RHELsudo yum install kernel-devel-$(uname -r)
Fedorasudo dnf install kernel-devel-$(uname -r)

⚠️ 注意:某些系统中uname -r返回的版本号可能无法直接用于包管理器(例如带有本地修改的定制内核)。此时需要手动查找匹配的 headers 包,或从源码重建。

2. 安装基本构建工具

# Debian/Ubuntu sudo apt install build-essential # RHEL/CentOS/Fedora sudo yum groupinstall "Development Tools"

3. 获取 CH340 驱动源码

最稳妥的方式是从Linux 内核源码树中提取ch34x.c,因为它保证与你当前使用的内核 API 兼容。

但我们也可以直接从沁恒官网或 GitHub 上找开源版本。

推荐使用社区维护良好的仓库:

git clone https://github.com/juliagoda/CH341SER.git cd CH341SER

该仓库包含了适用于多种平台的ch34x.c和 Makefile,并支持主流内核接口。

结构大致如下:

CH341SER/ ├── ch34x.c ├── Makefile └── README.md

第三步:编写正确的 Makefile 来编译模块

这是最容易出错的地方。很多人照搬网上老旧的 Makefile,结果编译失败。

我们要写一个符合kbuild 系统规范的双段式 Makefile。

创建Makefile文件内容如下:

ifneq ($(KERNELRELEASE),) obj-m := ch34x.o else KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -f *.o *.ko *.mod.* *.cmd *.markers *.order *.symvers endif

关键点解释:

  • obj-m := ch34x.o:表示我们要把ch34x.c编译为可加载模块(注意是obj-m,不是obj-y
  • $(MAKE) -C $(KDIR):跳转到内核构建目录(通常是/lib/modules/.../build,它是指向真实内核源码的符号链接)
  • M=$(PWD):告诉内核构建系统“回到当前目录继续编译模块”
  • 双段结构是为了兼容内核构建系统的递归调用机制

保存后执行:

make

如果一切顺利,你会看到:

Building modules, stage 2. MODPOST 1 modules CC ch34x.mod.o LD [M] ch34x.ko

并且生成了ch34x.ko文件。

🎉 成功一半了!


第四步:加载模块并验证功能

现在进入最后一步:把.ko文件“注入”内核。

1. 加载模块

sudo insmod ch34x.ko

不出意外的话,你应该能在 dmesg 中看到:

ch34x: loading out-of-tree module taints kernel. USB Serial support registered for ch34x ch34x: ch34x converter detected usbcore: registered new interface driver ch34x ch34x ttyUSB0: ch34x converter now attached

同时,设备节点也生成了:

ls /dev/ttyUSB* # 应该输出 /dev/ttyUSB0

2. 测试通信

可以用screenminicom连接测试:

sudo screen /dev/ttyUSB0 115200

如果你连接的是单片机并发送了日志,这时应该能看到输出了!

Ctrl+AKY退出 screen。


常见坑点与解决方法

❌ 问题1:insmod: error inserting 'ch34x.ko': -1 Invalid module format

原因:内核版本不匹配,或者 headers 没装对。

解决方案:
- 确认uname -r与安装的 headers 完全一致
- 检查/lib/modules/$(uname -r)/build是否存在且能访问
- 尝试重新安装 headers 包


❌ 问题2:Unknown symbol in module(如 usb_serial_register)

这是典型的 API 变更问题。旧版驱动用了已被废弃的函数。

解决方案:
- 使用更新的驱动源码(优先选用 Linux 主线中的版本)
- 或打补丁修复符号引用

建议参考 Linux 内核源码中的drivers/usb/serial/ch341.c(注意名字是 ch341,但它也支持 ch340)


❌ 问题3:Secure Boot 阻止模块加载

在启用了安全启动的系统上(如 Ubuntu 20.04+ 默认开启),加载第三方模块会报错:

The system is running in secure boot mode...

解决方案有两个:

方法一:禁用 Secure Boot(临时方案)

进 BIOS 设置,关闭 Secure Boot。

方法二:签名模块(生产级做法)

生成密钥并对模块签名:

# 生成私钥和公钥 openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=CH34X Driver/" # 注册公钥到 MOK(Machine Owner Key) sudo mokutil --import MOK.der # 重启后按提示设置密码,完成注册 # 签名模块 /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 ./MOK.priv ./MOK.der ch34x.ko # 再加载 sudo insmod ch34x.ko

这样就能通过 Secure Boot 验证了。


如何让驱动开机自动加载?

每次重启都要手动insmod太麻烦。我们可以让它自动加载。

方法1:加入模块加载列表

echo 'ch34x' | sudo tee /etc/modules-load.d/ch34x.conf

系统启动时会自动执行modprobe ch34x

方法2:安装到系统模块路径

sudo cp ch34x.ko /lib/modules/$(uname -r)/kernel/drivers/usb/serial/ sudo depmod -a

然后就可以用modprobe ch34x替代insmod了。


进阶技巧:为 ARM 板交叉编译驱动

如果你的目标平台是树莓派、全志H3/H5、RK3399 等 ARM 设备,就不能在 x86 主机上直接编译。

你需要做交叉编译。

修改 Makefile 添加架构和工具链:

ARCH ?= arm CROSS_COMPILE ?= arm-linux-gnueabihf- KDIR := /path/to/target/kernel/build obj-m := ch34x.o all: $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules clean: rm -f *.o *.ko *.mod.* *.cmd *.markers *.order *.symvers

然后在主机上运行:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KDIR=/home/user/rpi-kernel/build

生成的.ko文件拷贝到开发板即可加载。


总结一下:我们到底学会了什么?

这不是一篇“复制命令就能跑”的快餐教程。我们真正掌握的是:

✅ 如何判断 CH340 设备是否被正确识别
✅ 如何搭建独立的内核模块编译环境
✅ 如何使用标准 kbuild 系统编译.ko文件
✅ 如何手动加载模块并排查常见错误
✅ 如何应对 Secure Boot 和交叉编译等现实挑战

更重要的是,你不再依赖别人打包好的.deb.rpm文件。你可以面对任何一台没有网络、没有包管理器、甚至连驱动都没装的嵌入式设备,自信地说一句:

“让我给你装个驱动。”

而这,正是嵌入式工程师的核心能力之一。


最后一点建议

虽然现在主流发行版基本都自带ch34x支持,但在国产化替代浪潮下,越来越多的设备采用 CH340/CH341 芯片。了解其驱动机制,不仅能解决眼前问题,还能帮助你在面试、项目评审、故障排查中脱颖而出。

下次当你看到同事还在百度“Linux 插 CH340 没反应怎么办”,你可以默默打开终端,敲下make && sudo insmod ch34x.ko,然后看着/dev/ttyUSB0出现在屏幕上。

那一刻,你已经不是一个普通的使用者,而是掌控系统的那个人。

如果你觉得这篇实战指南有用,欢迎收藏转发。也欢迎在评论区分享你在实际项目中遇到的奇葩驱动问题,我们一起拆解解决。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询