树莓派编译CH348驱动的一点问题

CH348

CH348芯片的主要功能和特点

  1. 高速传输:内置单片机高速480Mbps USB收发器和控制器。
  2. 单口高集:各串口内部置独立收发FIFO,支持高达6Mbps波特率。
  3. 双电源设计:串口IO电压支持3.3V/2.5V/1.8V(默认3.3V)。
  4. 多功能:集成了UART、Modem信号、GPIO和RS485发射使能等功能。
  5. USB配置功能:支持USB设备描述符、供应商ID、产品ID、串号等配置。
  6. 驱动提供:支持Windows、Linux、Android、macOS等操作系统。
  7. 封装:提供LQFP100和LQFP48封装。
  8. TTM(Time To Market):快速上市时间。
  9. 技术支持:提供产品手册、驱动与应用软件、参考设计、芯片与评估板等技术支持资源。
  10. 兼容操作系统:支持Windows、Linux、Android和macOS操作系统。

在树莓派上编译驱动时遇到了一点问题,记录一下。

Linux驱动库开源在 https://github.com/WCHSoftGroup/ch9344ser_linux。

编译驱动

按照 README 中的方法进行编译:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ch9344 linux serial driver

## Description

This driver supports USB to quad serial ports chip ch9344 and USB to octal serial ports chip ch348.

1. Open "Terminal"
2. Switch to "driver" directory
3. Compile the driver using "make", you will see the module "ch9344.ko" if successful
4. Type "sudo make load" or "sudo insmod ch9344.ko" to load the driver dynamically
5. Type "sudo make unload" or "sudo rmmod ch9344.ko" to unload the driver
6. Type "sudo make install" to make the driver work permanently
7. Type "sudo make uninstall" to remove the driver
8. You can refer to the link below to acquire uart application, you can use gcc or Cross-compile with cross-gcc
https://github.com/WCHSoftGroup/tty_uart

Before the driver works, you should make sure that the usb device has been plugged in and is working properly, you can use shell command "lsusb" or "dmesg" to confirm that, USB VID of these devices are [1A86], you can view all IDs from the id table which defined in "ch9344.c".

If the device works well, the driver will created tty devices named "ttyCH9344USBx" in /dev directory.

## Note

Any question, you can send feedback to mail: tech@wch.cn

大概率会遇到找不到指定路径的问题。

打开 driver 目录下的 Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CONFIG_MODULE_SIG=n

ifeq ($(KERNELRELEASE), )
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD)
clean:
rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
load:
insmod ch9344.ko
unload:
rmmod ch9344
install: default
insmod ch9344.ko || true
mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
cp -f ./ch9344.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
depmod -a
uninstall:
rmmod ch9344 || true
rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch9344.ko || true
depmod -a
else
obj-m := ch9344.o
endif

问题应该是出在KERNELDIR这里了,不同的Linux发行版,源码头文件安装位置不太一样,并且很多发行版默认是不安装源码的,所以需要手动安装下。

在树莓派上,可以使用以下命令安装:

1
sudo apt-get install raspberrypi-kernel-headers

在树莓派上编译内核模块,需要知道你的树莓派的内核版本,并且需要有对应版本的内核源代码。可以通过以下命令获取内核版本:

1
uname -r

树莓派的源码是安装在 /usr/src 目录下的,所以需要修改 Makefile 中的 KERNELDIR/usr/src/linux-headers-$(shell uname -r)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CONFIG_MODULE_SIG=n

ifeq ($(KERNELRELEASE), )
# 需要根据你的实际情况修改路径
KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r)
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean

...

这个Makefile首先尝试使用环境变量KERNELDIR,如果没有设置,就使用/usr/src/linux-headers-$(shell uname -r)$(shell uname -r)会被替换为你的内核版本。

default目标会编译你的内核模块,clean目标会清理编译生成的文件。

注意,你可能需要使用sudo来运行make命令,因为编译内核模块通常需要管理员权限。

不是所有的Linux发行版都会默认设置KERNELDIR这个环境变量。实际上,KERNELDIR通常不会被默认设置,它通常在编译内核或内核模块时,由用户或脚本显式设置。

在Linux系统中,你可以使用echo命令来查看环境变量的值。如果你想查看KERNELDIR环境变量,你可以在终端中输入以下命令:

1
echo $KERNELDIR

这将会打印出KERNELDIR环境变量的值。如果这个环境变量没有被设置,那么这个命令将不会输出任何内容。

在Makefile中,KERNELDIR被用作一个变量,代表内核源代码的位置。如果没有在环境中设置这个变量,需要在Makefile中提供一个默认值,或者在调用make命令时,通过命令行参数提供这个值。

例如,你可以在Makefile中提供一个默认值:

1
KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r)

或者在调用make命令时,通过命令行参数提供这个值:

1
make KERNELDIR=/usr/src/linux-headers-$(uname -r)

然后再次按照 README 中的方法执行剩下的步骤应该就可以正常加载驱动了。