项目背景
最近在华为昇腾310B开发板上需要连接一个使用CH341芯片的USB转串口设备。虽然Linux内核通常自带CH341驱动,但在这个定制化的昇腾开发板环境中,遇到了内核模块版本不匹配的问题。本文将完整记录从问题诊断到最终解决的全过程。
环境说明
- 开发板:华为昇腾310B(Atlas 200I DK A2)
- 操作系统:Ubuntu 22.04 LTS
- 内核版本:5.10.0+(定制版本)
- 目标驱动:CH341 USB转串口驱动
问题诊断
初始错误
# 尝试编译驱动时遇到的第一错误
make -C /lib/modules/5.10.0+/build M=/root/yolo_sdk_python_sample/driver
make[1]: *** /lib/modules/5.10.0+/build: No such file or directory. Stop.
根本原因分析
- 内核头文件目录缺失
- 内核源码路径不正确
- 版本字符串不匹配(vermagic)
- 内核配置不一致(抢占模式)
前期准备
官网下载对应源码包Ascend-hdk-310b-sdk-soc_23.0.rc2.zip(自行解压到对应位置)
CH341对应5.10.0版本的ch341.c(自行更改ch341.c的代码)
[ch341.c - drivers/usb/serial/ch341.c - Linux source code v5.10.244 - Bootlin Elixir Cross Referencer](https://)
解决过程
第一步:定位内核源码
通过系统诊断发现,昇腾开发板使用了定制化的内核源码结构:
(/usr/src/Ascend310B-source/kernel/kernel/kernel中含有kernel.tar.gz包,自行解压)
# 查找内核源码
find / -name "Makefile" | grep kernel | head -5
# 发现路径:/usr/src/Ascend310B-source/kernel/kernel/kernel/kernel/Makefile
#/usr/src/Ascend310B-source/kernel/kernel/kernel中含有kernel.tar.gz包,自行解压
# 验证内核版本
head -5 /usr/src/Ascend310B-source/kernel/kernel/kernel/kernel/Makefile
# 输出:VERSION = 5, PATCHLEVEL = 10, SUBLEVEL = 0
第二步:设置正确的符号链接
# 创建正确的符号链接
sudo mkdir -p /lib/modules/5.10.0+
sudo rm -f /lib/modules/5.10.0+/build
sudo ln -sf /usr/src/Ascend310B-source/kernel/kernel/kernel/kernel /lib/modules/5.10.0+/build
# 验证链接
ls -l /lib/modules/5.10.0+/build
第三步:准备内核构建环境
## 进入内核源码目录
cd /usr/src/Ascend310B-source/kernel/kernel/kernel/kernel
# 生成默认配置
make ARCH=arm64 defconfig
# 准备构建环境
make prepare
make scripts
到此步内核问题解决,接下来解决内核与驱动的版本不匹配问题
第四步:解决版本不匹配问题
问题现象:
# 模块版本信息
modinfo ch341.ko | grep vermagic
# vermagic: 5.10.0 SMP preempt mod_unload aarch64
# 运行内核版本
uname -r
# 5.10.0+
# dmesg错误信息
dmesg | tail -5
# ch341: version magic '5.10.0 SMP preempt mod_unload aarch64' should be '5.10.0+ SMP mod_unload aarch64'
解决方案:
- 修改驱动Makefile:
# 在Makefile中明确指定版本后缀
default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) EXTRAVERSION=+ modules
- 禁用抢占配置:
# 修改内核配置
cd /usr/src/Ascend310B-source/kernel/kernel/kernel/kernel
echo "# CONFIG_PREEMPT is not set" >> .config
echo "CONFIG_PREEMPT_NONE=y" >> .config
make ARCH=arm64 olddefconfig
make prepare
第五步:编译和测试驱动
# 回到驱动目录
cd ~/yolo_sdk_python_sample/driver
# 清理并重新编译
make clean
make
# 验证版本信息
modinfo ch341.ko | grep vermagic
# 期望输出:vermagic: 5.10.0+ SMP mod_unload aarch64
# 加载驱动
sudo insmod ch341.ko
第六步:系统化安装
# 使用Makefile的安装目标
sudo make install
# 验证安装结果
lsmod | grep ch341
ls -la /lib/modules/5.10.0+/kernel/drivers/usb/serial/ch341.ko
关键技术点总结
1. 内核源码路径识别
- 昇腾开发板的内核源码位于特定目录结构
- 需要正确设置
/lib/modules/$(uname -r)/build符号链接
2. 版本字符串匹配
vermagic必须与运行内核完全一致- 使用
EXTRAVERSION=+参数确保版本后缀匹配
3. 内核配置一致性
- 抢占模式(preempt)配置必须一致
- 需要通过内核配置文件确保编译环境与运行环境匹配
4. 构建环境准备
- 必须执行
make prepare和make scripts - 需要正确的架构指定(ARCH=arm64)
完整可用CH341的Makefile
CONFIG_MODULE_SIG=n
# 指定内核版本和路径
KERNEL_VERSION = 5.10.0+
KERNEL_DIR = /usr/src/Ascend310B-source/kernel/kernel/kernel/kernel
ifeq ($(KERNELRELEASE), )
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) EXTRAVERSION=+ modules
clean:
rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
load:
insmod ch341.ko
unload:
rmmod ch341
install: default
rmmod ch341 || true
insmod ch341.ko || true
mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
cp -f ./ch341.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
depmod -a
uninstall:
rmmod ch341 || true
rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch341.ko || true
depmod -a
else
obj-m := ch341.o
endif
经验教训
- 嵌入式环境特殊性:嵌入式开发板的内核通常是定制化的,不能直接使用通用发行版的方法
- 版本一致性至关重要:内核模块编译必须与运行环境完全一致
- 诊断工具的使用:
dmesg、modinfo、lsmod等工具是诊断驱动问题的关键 - 循序渐进的方法:从简单问题开始解决,逐步深入复杂问题
后续使用
驱动安装成功后,CH341设备插入时会自动识别:
# 检查设备识别
ls -la /dev/ttyCH341*
# 使用串口工具测试
sudo minicom -D /dev/ttyCH3410 -b 9600
结论
通过系统性的问题诊断和解决,成功在昇腾310B开发板上编译并加载了CH341 USB转串口驱动。这个过程不仅解决了具体的技术问题,也提供了在定制化嵌入式环境中处理内核驱动兼容性问题的通用方法。
关键词:昇腾310B、CH341、内核驱动、版本匹配、vermagic、内核编译、嵌入式Linux
本文记录了一次完整的内核驱动移植过程,希望对在类似嵌入式平台上进行驱动开发的同行有所帮助。

被折叠的 条评论
为什么被折叠?



